]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/cam/scsi/scsi_all.c
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / sys / cam / scsi / scsi_all.c
1 /*-
2  * Implementation of Utility functions for all SCSI device types.
3  *
4  * Copyright (c) 1997, 1998, 1999 Justin T. Gibbs.
5  * Copyright (c) 1997, 1998, 2003 Kenneth D. Merry.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions, and the following disclaimer,
13  *    without modification, immediately at the beginning of the file.
14  * 2. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/param.h>
34 #include <sys/types.h>
35 #include <sys/stdint.h>
36
37 #ifdef _KERNEL
38 #include <opt_scsi.h>
39
40 #include <sys/systm.h>
41 #include <sys/libkern.h>
42 #include <sys/kernel.h>
43 #include <sys/lock.h>
44 #include <sys/malloc.h>
45 #include <sys/mutex.h>
46 #include <sys/sysctl.h>
47 #else
48 #include <errno.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #endif
53
54 #include <cam/cam.h>
55 #include <cam/cam_ccb.h>
56 #include <cam/cam_queue.h>
57 #include <cam/cam_xpt.h>
58 #include <cam/scsi/scsi_all.h>
59 #include <sys/ata.h>
60 #include <sys/sbuf.h>
61
62 #ifdef _KERNEL
63 #include <cam/cam_periph.h>
64 #include <cam/cam_xpt_sim.h>
65 #include <cam/cam_xpt_periph.h>
66 #include <cam/cam_xpt_internal.h>
67 #else
68 #include <camlib.h>
69 #include <stddef.h>
70
71 #ifndef FALSE
72 #define FALSE   0
73 #endif /* FALSE */
74 #ifndef TRUE
75 #define TRUE    1
76 #endif /* TRUE */
77 #define ERESTART        -1              /* restart syscall */
78 #define EJUSTRETURN     -2              /* don't modify regs, just return */
79 #endif /* !_KERNEL */
80
81 /*
82  * This is the default number of milliseconds we wait for devices to settle
83  * after a SCSI bus reset.
84  */
85 #ifndef SCSI_DELAY
86 #define SCSI_DELAY 2000
87 #endif
88 /*
89  * All devices need _some_ sort of bus settle delay, so we'll set it to
90  * a minimum value of 100ms. Note that this is pertinent only for SPI-
91  * not transport like Fibre Channel or iSCSI where 'delay' is completely
92  * meaningless.
93  */
94 #ifndef SCSI_MIN_DELAY
95 #define SCSI_MIN_DELAY 100
96 #endif
97 /*
98  * Make sure the user isn't using seconds instead of milliseconds.
99  */
100 #if (SCSI_DELAY < SCSI_MIN_DELAY && SCSI_DELAY != 0)
101 #error "SCSI_DELAY is in milliseconds, not seconds!  Please use a larger value"
102 #endif
103
104 int scsi_delay;
105
106 static int      ascentrycomp(const void *key, const void *member);
107 static int      senseentrycomp(const void *key, const void *member);
108 static void     fetchtableentries(int sense_key, int asc, int ascq,
109                                   struct scsi_inquiry_data *,
110                                   const struct sense_key_table_entry **,
111                                   const struct asc_table_entry **);
112 #ifdef _KERNEL
113 static void     init_scsi_delay(void);
114 static int      sysctl_scsi_delay(SYSCTL_HANDLER_ARGS);
115 static int      set_scsi_delay(int delay);
116 #endif
117
118 #if !defined(SCSI_NO_OP_STRINGS)
119
120 #define D       (1 << T_DIRECT)
121 #define T       (1 << T_SEQUENTIAL)
122 #define L       (1 << T_PRINTER)
123 #define P       (1 << T_PROCESSOR)
124 #define W       (1 << T_WORM)
125 #define R       (1 << T_CDROM)
126 #define O       (1 << T_OPTICAL)
127 #define M       (1 << T_CHANGER)
128 #define A       (1 << T_STORARRAY)
129 #define E       (1 << T_ENCLOSURE)
130 #define B       (1 << T_RBC)
131 #define K       (1 << T_OCRW)
132 #define V       (1 << T_ADC)
133 #define F       (1 << T_OSD)
134 #define S       (1 << T_SCANNER)
135 #define C       (1 << T_COMM)
136
137 #define ALL     (D | T | L | P | W | R | O | M | A | E | B | K | V | F | S | C)
138
139 static struct op_table_entry plextor_cd_ops[] = {
140         { 0xD8, R, "CD-DA READ" }
141 };
142
143 static struct scsi_op_quirk_entry scsi_op_quirk_table[] = {
144         {
145                 /*
146                  * I believe that 0xD8 is the Plextor proprietary command
147                  * to read CD-DA data.  I'm not sure which Plextor CDROM
148                  * models support the command, though.  I know for sure
149                  * that the 4X, 8X, and 12X models do, and presumably the
150                  * 12-20X does.  I don't know about any earlier models,
151                  * though.  If anyone has any more complete information,
152                  * feel free to change this quirk entry.
153                  */
154                 {T_CDROM, SIP_MEDIA_REMOVABLE, "PLEXTOR", "CD-ROM PX*", "*"},
155                 sizeof(plextor_cd_ops)/sizeof(struct op_table_entry),
156                 plextor_cd_ops
157         }
158 };
159
160 static struct op_table_entry scsi_op_codes[] = {
161         /*
162          * From: http://www.t10.org/lists/op-num.txt
163          * Modifications by Kenneth Merry (ken@FreeBSD.ORG)
164          *              and Jung-uk Kim (jkim@FreeBSD.org)
165          *
166          * Note:  order is important in this table, scsi_op_desc() currently
167          * depends on the opcodes in the table being in order to save
168          * search time.
169          * Note:  scanner and comm. devices are carried over from the previous
170          * version because they were removed in the latest spec.
171          */
172         /* File: OP-NUM.TXT
173          *
174          * SCSI Operation Codes
175          * Numeric Sorted Listing
176          * as of  3/11/08
177          *
178          *     D - DIRECT ACCESS DEVICE (SBC-2)                device column key
179          *     .T - SEQUENTIAL ACCESS DEVICE (SSC-2)           -----------------
180          *     . L - PRINTER DEVICE (SSC)                      M = Mandatory
181          *     .  P - PROCESSOR DEVICE (SPC)                   O = Optional
182          *     .  .W - WRITE ONCE READ MULTIPLE DEVICE (SBC-2) V = Vendor spec.
183          *     .  . R - CD/DVE DEVICE (MMC-3)                  Z = Obsolete
184          *     .  .  O - OPTICAL MEMORY DEVICE (SBC-2)
185          *     .  .  .M - MEDIA CHANGER DEVICE (SMC-2)
186          *     .  .  . A - STORAGE ARRAY DEVICE (SCC-2)
187          *     .  .  . .E - ENCLOSURE SERVICES DEVICE (SES)
188          *     .  .  .  .B - SIMPLIFIED DIRECT-ACCESS DEVICE (RBC)
189          *     .  .  .  . K - OPTICAL CARD READER/WRITER DEVICE (OCRW)
190          *     .  .  .  .  V - AUTOMATION/DRIVE INTERFACE (ADC)
191          *     .  .  .  .  .F - OBJECT-BASED STORAGE (OSD)
192          * OP  DTLPWROMAEBKVF  Description
193          * --  --------------  ---------------------------------------------- */
194         /* 00  MMMMMMMMMMMMMM  TEST UNIT READY */
195         { 0x00, ALL, "TEST UNIT READY" },
196         /* 01   M              REWIND */
197         { 0x01, T, "REWIND" },
198         /* 01  Z V ZZZZ        REZERO UNIT */
199         { 0x01, D | W | R | O | M, "REZERO UNIT" },
200         /* 02  VVVVVV V */
201         /* 03  MMMMMMMMMMOMMM  REQUEST SENSE */
202         { 0x03, ALL, "REQUEST SENSE" },
203         /* 04  M    OO         FORMAT UNIT */
204         { 0x04, D | R | O, "FORMAT UNIT" },
205         /* 04   O              FORMAT MEDIUM */
206         { 0x04, T, "FORMAT MEDIUM" },
207         /* 04    O             FORMAT */
208         { 0x04, L, "FORMAT" },
209         /* 05  VMVVVV V        READ BLOCK LIMITS */
210         { 0x05, T, "READ BLOCK LIMITS" },
211         /* 06  VVVVVV V */
212         /* 07  OVV O OV        REASSIGN BLOCKS */
213         { 0x07, D | W | O, "REASSIGN BLOCKS" },
214         /* 07         O        INITIALIZE ELEMENT STATUS */
215         { 0x07, M, "INITIALIZE ELEMENT STATUS" },
216         /* 08  MOV O OV        READ(6) */
217         { 0x08, D | T | W | O, "READ(6)" },
218         /* 08     O            RECEIVE */
219         { 0x08, P, "RECEIVE" },
220         /* 08                  GET MESSAGE(6) */
221         { 0x08, C, "GET MESSAGE(6)" },
222         /* 09  VVVVVV V */
223         /* 0A  OO  O OV        WRITE(6) */
224         { 0x0A, D | T | W | O, "WRITE(6)" },
225         /* 0A     M            SEND(6) */
226         { 0x0A, P, "SEND(6)" },
227         /* 0A                  SEND MESSAGE(6) */
228         { 0x0A, C, "SEND MESSAGE(6)" },
229         /* 0A    M             PRINT */
230         { 0x0A, L, "PRINT" },
231         /* 0B  Z   ZOZV        SEEK(6) */
232         { 0x0B, D | W | R | O, "SEEK(6)" },
233         /* 0B   O              SET CAPACITY */
234         { 0x0B, T, "SET CAPACITY" },
235         /* 0B    O             SLEW AND PRINT */
236         { 0x0B, L, "SLEW AND PRINT" },
237         /* 0C  VVVVVV V */
238         /* 0D  VVVVVV V */
239         /* 0E  VVVVVV V */
240         /* 0F  VOVVVV V        READ REVERSE(6) */
241         { 0x0F, T, "READ REVERSE(6)" },
242         /* 10  VM VVV          WRITE FILEMARKS(6) */
243         { 0x10, T, "WRITE FILEMARKS(6)" },
244         /* 10    O             SYNCHRONIZE BUFFER */
245         { 0x10, L, "SYNCHRONIZE BUFFER" },
246         /* 11  VMVVVV          SPACE(6) */
247         { 0x11, T, "SPACE(6)" },
248         /* 12  MMMMMMMMMMMMMM  INQUIRY */
249         { 0x12, ALL, "INQUIRY" },
250         /* 13  V VVVV */
251         /* 13   O              VERIFY(6) */
252         { 0x13, T, "VERIFY(6)" },
253         /* 14  VOOVVV          RECOVER BUFFERED DATA */
254         { 0x14, T | L, "RECOVER BUFFERED DATA" },
255         /* 15  OMO O OOOO OO   MODE SELECT(6) */
256         { 0x15, ALL & ~(P | R | B | F), "MODE SELECT(6)" },
257         /* 16  ZZMZO OOOZ O    RESERVE(6) */
258         { 0x16, ALL & ~(R | B | V | F | C), "RESERVE(6)" },
259         /* 16         Z        RESERVE ELEMENT(6) */
260         { 0x16, M, "RESERVE ELEMENT(6)" },
261         /* 17  ZZMZO OOOZ O    RELEASE(6) */
262         { 0x17, ALL & ~(R | B | V | F | C), "RELEASE(6)" },
263         /* 17         Z        RELEASE ELEMENT(6) */
264         { 0x17, M, "RELEASE ELEMENT(6)" },
265         /* 18  ZZZZOZO    Z    COPY */
266         { 0x18, D | T | L | P | W | R | O | K | S, "COPY" },
267         /* 19  VMVVVV          ERASE(6) */
268         { 0x19, T, "ERASE(6)" },
269         /* 1A  OMO O OOOO OO   MODE SENSE(6) */
270         { 0x1A, ALL & ~(P | R | B | F), "MODE SENSE(6)" },
271         /* 1B  O   OOO O MO O  START STOP UNIT */
272         { 0x1B, D | W | R | O | A | B | K | F, "START STOP UNIT" },
273         /* 1B   O          M   LOAD UNLOAD */
274         { 0x1B, T | V, "LOAD UNLOAD" },
275         /* 1B                  SCAN */
276         { 0x1B, S, "SCAN" },
277         /* 1B    O             STOP PRINT */
278         { 0x1B, L, "STOP PRINT" },
279         /* 1B         O        OPEN/CLOSE IMPORT/EXPORT ELEMENT */
280         { 0x1B, M, "OPEN/CLOSE IMPORT/EXPORT ELEMENT" },
281         /* 1C  OOOOO OOOM OOO  RECEIVE DIAGNOSTIC RESULTS */
282         { 0x1C, ALL & ~(R | B), "RECEIVE DIAGNOSTIC RESULTS" },
283         /* 1D  MMMMM MMOM MMM  SEND DIAGNOSTIC */
284         { 0x1D, ALL & ~(R | B), "SEND DIAGNOSTIC" },
285         /* 1E  OO  OOOO   O O  PREVENT ALLOW MEDIUM REMOVAL */
286         { 0x1E, D | T | W | R | O | M | K | F, "PREVENT ALLOW MEDIUM REMOVAL" },
287         /* 1F */
288         /* 20  V   VVV    V */
289         /* 21  V   VVV    V */
290         /* 22  V   VVV    V */
291         /* 23  V   V V    V */
292         /* 23       O          READ FORMAT CAPACITIES */
293         { 0x23, R, "READ FORMAT CAPACITIES" },
294         /* 24  V   VV          SET WINDOW */
295         { 0x24, S, "SET WINDOW" },
296         /* 25  M   M M   M     READ CAPACITY(10) */
297         { 0x25, D | W | O | B, "READ CAPACITY(10)" },
298         /* 25       O          READ CAPACITY */
299         { 0x25, R, "READ CAPACITY" },
300         /* 25             M    READ CARD CAPACITY */
301         { 0x25, K, "READ CARD CAPACITY" },
302         /* 25                  GET WINDOW */
303         { 0x25, S, "GET WINDOW" },
304         /* 26  V   VV */
305         /* 27  V   VV */
306         /* 28  M   MOM   MM    READ(10) */
307         { 0x28, D | W | R | O | B | K | S, "READ(10)" },
308         /* 28                  GET MESSAGE(10) */
309         { 0x28, C, "GET MESSAGE(10)" },
310         /* 29  V   VVO         READ GENERATION */
311         { 0x29, O, "READ GENERATION" },
312         /* 2A  O   MOM   MO    WRITE(10) */
313         { 0x2A, D | W | R | O | B | K, "WRITE(10)" },
314         /* 2A                  SEND(10) */
315         { 0x2A, S, "SEND(10)" },
316         /* 2A                  SEND MESSAGE(10) */
317         { 0x2A, C, "SEND MESSAGE(10)" },
318         /* 2B  Z   OOO    O    SEEK(10) */
319         { 0x2B, D | W | R | O | K, "SEEK(10)" },
320         /* 2B   O              LOCATE(10) */
321         { 0x2B, T, "LOCATE(10)" },
322         /* 2B         O        POSITION TO ELEMENT */
323         { 0x2B, M, "POSITION TO ELEMENT" },
324         /* 2C  V    OO         ERASE(10) */
325         { 0x2C, R | O, "ERASE(10)" },
326         /* 2D        O         READ UPDATED BLOCK */
327         { 0x2D, O, "READ UPDATED BLOCK" },
328         /* 2D  V */
329         /* 2E  O   OOO   MO    WRITE AND VERIFY(10) */
330         { 0x2E, D | W | R | O | B | K, "WRITE AND VERIFY(10)" },
331         /* 2F  O   OOO         VERIFY(10) */
332         { 0x2F, D | W | R | O, "VERIFY(10)" },
333         /* 30  Z   ZZZ         SEARCH DATA HIGH(10) */
334         { 0x30, D | W | R | O, "SEARCH DATA HIGH(10)" },
335         /* 31  Z   ZZZ         SEARCH DATA EQUAL(10) */
336         { 0x31, D | W | R | O, "SEARCH DATA EQUAL(10)" },
337         /* 31                  OBJECT POSITION */
338         { 0x31, S, "OBJECT POSITION" },
339         /* 32  Z   ZZZ         SEARCH DATA LOW(10) */
340         { 0x32, D | W | R | O, "SEARCH DATA LOW(10)" },
341         /* 33  Z   OZO         SET LIMITS(10) */
342         { 0x33, D | W | R | O, "SET LIMITS(10)" },
343         /* 34  O   O O    O    PRE-FETCH(10) */
344         { 0x34, D | W | O | K, "PRE-FETCH(10)" },
345         /* 34   M              READ POSITION */
346         { 0x34, T, "READ POSITION" },
347         /* 34                  GET DATA BUFFER STATUS */
348         { 0x34, S, "GET DATA BUFFER STATUS" },
349         /* 35  O   OOO   MO    SYNCHRONIZE CACHE(10) */
350         { 0x35, D | W | R | O | B | K, "SYNCHRONIZE CACHE(10)" },
351         /* 36  Z   O O    O    LOCK UNLOCK CACHE(10) */
352         { 0x36, D | W | O | K, "LOCK UNLOCK CACHE(10)" },
353         /* 37  O     O         READ DEFECT DATA(10) */
354         { 0x37, D | O, "READ DEFECT DATA(10)" },
355         /* 37         O        INITIALIZE ELEMENT STATUS WITH RANGE */
356         { 0x37, M, "INITIALIZE ELEMENT STATUS WITH RANGE" },
357         /* 38      O O    O    MEDIUM SCAN */
358         { 0x38, W | O | K, "MEDIUM SCAN" },
359         /* 39  ZZZZOZO    Z    COMPARE */
360         { 0x39, D | T | L | P | W | R | O | K | S, "COMPARE" },
361         /* 3A  ZZZZOZO    Z    COPY AND VERIFY */
362         { 0x3A, D | T | L | P | W | R | O | K | S, "COPY AND VERIFY" },
363         /* 3B  OOOOOOOOOOMOOO  WRITE BUFFER */
364         { 0x3B, ALL, "WRITE BUFFER" },
365         /* 3C  OOOOOOOOOO OOO  READ BUFFER */
366         { 0x3C, ALL & ~(B), "READ BUFFER" },
367         /* 3D        O         UPDATE BLOCK */
368         { 0x3D, O, "UPDATE BLOCK" },
369         /* 3E  O   O O         READ LONG(10) */
370         { 0x3E, D | W | O, "READ LONG(10)" },
371         /* 3F  O   O O         WRITE LONG(10) */
372         { 0x3F, D | W | O, "WRITE LONG(10)" },
373         /* 40  ZZZZOZOZ        CHANGE DEFINITION */
374         { 0x40, D | T | L | P | W | R | O | M | S | C, "CHANGE DEFINITION" },
375         /* 41  O               WRITE SAME(10) */
376         { 0x41, D, "WRITE SAME(10)" },
377         /* 42       O          UNMAP */
378         { 0x42, D, "UNMAP" },
379         /* 42       O          READ SUB-CHANNEL */
380         { 0x42, R, "READ SUB-CHANNEL" },
381         /* 43       O          READ TOC/PMA/ATIP */
382         { 0x43, R, "READ TOC/PMA/ATIP" },
383         /* 44   M          M   REPORT DENSITY SUPPORT */
384         { 0x44, T | V, "REPORT DENSITY SUPPORT" },
385         /* 44                  READ HEADER */
386         /* 45       O          PLAY AUDIO(10) */
387         { 0x45, R, "PLAY AUDIO(10)" },
388         /* 46       M          GET CONFIGURATION */
389         { 0x46, R, "GET CONFIGURATION" },
390         /* 47       O          PLAY AUDIO MSF */
391         { 0x47, R, "PLAY AUDIO MSF" },
392         /* 48 */
393         /* 49 */
394         /* 4A       M          GET EVENT STATUS NOTIFICATION */
395         { 0x4A, R, "GET EVENT STATUS NOTIFICATION" },
396         /* 4B       O          PAUSE/RESUME */
397         { 0x4B, R, "PAUSE/RESUME" },
398         /* 4C  OOOOO OOOO OOO  LOG SELECT */
399         { 0x4C, ALL & ~(R | B), "LOG SELECT" },
400         /* 4D  OOOOO OOOO OMO  LOG SENSE */
401         { 0x4D, ALL & ~(R | B), "LOG SENSE" },
402         /* 4E       O          STOP PLAY/SCAN */
403         { 0x4E, R, "STOP PLAY/SCAN" },
404         /* 4F */
405         /* 50  O               XDWRITE(10) */
406         { 0x50, D, "XDWRITE(10)" },
407         /* 51  O               XPWRITE(10) */
408         { 0x51, D, "XPWRITE(10)" },
409         /* 51       O          READ DISC INFORMATION */
410         { 0x51, R, "READ DISC INFORMATION" },
411         /* 52  O               XDREAD(10) */
412         { 0x52, D, "XDREAD(10)" },
413         /* 52       O          READ TRACK INFORMATION */
414         { 0x52, R, "READ TRACK INFORMATION" },
415         /* 53       O          RESERVE TRACK */
416         { 0x53, R, "RESERVE TRACK" },
417         /* 54       O          SEND OPC INFORMATION */
418         { 0x54, R, "SEND OPC INFORMATION" },
419         /* 55  OOO OMOOOOMOMO  MODE SELECT(10) */
420         { 0x55, ALL & ~(P), "MODE SELECT(10)" },
421         /* 56  ZZMZO OOOZ      RESERVE(10) */
422         { 0x56, ALL & ~(R | B | K | V | F | C), "RESERVE(10)" },
423         /* 56         Z        RESERVE ELEMENT(10) */
424         { 0x56, M, "RESERVE ELEMENT(10)" },
425         /* 57  ZZMZO OOOZ      RELEASE(10) */
426         { 0x57, ALL & ~(R | B | K | V | F | C), "RELEASE(10)" },
427         /* 57         Z        RELEASE ELEMENT(10) */
428         { 0x57, M, "RELEASE ELEMENT(10)" },
429         /* 58       O          REPAIR TRACK */
430         { 0x58, R, "REPAIR TRACK" },
431         /* 59 */
432         /* 5A  OOO OMOOOOMOMO  MODE SENSE(10) */
433         { 0x5A, ALL & ~(P), "MODE SENSE(10)" },
434         /* 5B       O          CLOSE TRACK/SESSION */
435         { 0x5B, R, "CLOSE TRACK/SESSION" },
436         /* 5C       O          READ BUFFER CAPACITY */
437         { 0x5C, R, "READ BUFFER CAPACITY" },
438         /* 5D       O          SEND CUE SHEET */
439         { 0x5D, R, "SEND CUE SHEET" },
440         /* 5E  OOOOO OOOO   M  PERSISTENT RESERVE IN */
441         { 0x5E, ALL & ~(R | B | K | V | C), "PERSISTENT RESERVE IN" },
442         /* 5F  OOOOO OOOO   M  PERSISTENT RESERVE OUT */
443         { 0x5F, ALL & ~(R | B | K | V | C), "PERSISTENT RESERVE OUT" },
444         /* 7E  OO   O OOOO O   extended CDB */
445         { 0x7E, D | T | R | M | A | E | B | V, "extended CDB" },
446         /* 7F  O            M  variable length CDB (more than 16 bytes) */
447         { 0x7F, D | F, "variable length CDB (more than 16 bytes)" },
448         /* 80  Z               XDWRITE EXTENDED(16) */
449         { 0x80, D, "XDWRITE EXTENDED(16)" },
450         /* 80   M              WRITE FILEMARKS(16) */
451         { 0x80, T, "WRITE FILEMARKS(16)" },
452         /* 81  Z               REBUILD(16) */
453         { 0x81, D, "REBUILD(16)" },
454         /* 81   O              READ REVERSE(16) */
455         { 0x81, T, "READ REVERSE(16)" },
456         /* 82  Z               REGENERATE(16) */
457         { 0x82, D, "REGENERATE(16)" },
458         /* 83  OOOOO O    OO   EXTENDED COPY */
459         { 0x83, D | T | L | P | W | O | K | V, "EXTENDED COPY" },
460         /* 84  OOOOO O    OO   RECEIVE COPY RESULTS */
461         { 0x84, D | T | L | P | W | O | K | V, "RECEIVE COPY RESULTS" },
462         /* 85  O    O    O     ATA COMMAND PASS THROUGH(16) */
463         { 0x85, D | R | B, "ATA COMMAND PASS THROUGH(16)" },
464         /* 86  OO OO OOOOOOO   ACCESS CONTROL IN */
465         { 0x86, ALL & ~(L | R | F), "ACCESS CONTROL IN" },
466         /* 87  OO OO OOOOOOO   ACCESS CONTROL OUT */
467         { 0x87, ALL & ~(L | R | F), "ACCESS CONTROL OUT" },
468         /*
469          * XXX READ(16)/WRITE(16) were not listed for CD/DVE in op-num.txt
470          * but we had it since r1.40.  Do we really want them?
471          */
472         /* 88  MM  O O   O     READ(16) */
473         { 0x88, D | T | W | O | B, "READ(16)" },
474         /* 89 */
475         /* 8A  OM  O O   O     WRITE(16) */
476         { 0x8A, D | T | W | O | B, "WRITE(16)" },
477         /* 8B  O               ORWRITE */
478         { 0x8B, D, "ORWRITE" },
479         /* 8C  OO  O OO  O M   READ ATTRIBUTE */
480         { 0x8C, D | T | W | O | M | B | V, "READ ATTRIBUTE" },
481         /* 8D  OO  O OO  O O   WRITE ATTRIBUTE */
482         { 0x8D, D | T | W | O | M | B | V, "WRITE ATTRIBUTE" },
483         /* 8E  O   O O   O     WRITE AND VERIFY(16) */
484         { 0x8E, D | W | O | B, "WRITE AND VERIFY(16)" },
485         /* 8F  OO  O O   O     VERIFY(16) */
486         { 0x8F, D | T | W | O | B, "VERIFY(16)" },
487         /* 90  O   O O   O     PRE-FETCH(16) */
488         { 0x90, D | W | O | B, "PRE-FETCH(16)" },
489         /* 91  O   O O   O     SYNCHRONIZE CACHE(16) */
490         { 0x91, D | W | O | B, "SYNCHRONIZE CACHE(16)" },
491         /* 91   O              SPACE(16) */
492         { 0x91, T, "SPACE(16)" },
493         /* 92  Z   O O         LOCK UNLOCK CACHE(16) */
494         { 0x92, D | W | O, "LOCK UNLOCK CACHE(16)" },
495         /* 92   O              LOCATE(16) */
496         { 0x92, T, "LOCATE(16)" },
497         /* 93  O               WRITE SAME(16) */
498         { 0x93, D, "WRITE SAME(16)" },
499         /* 93   M              ERASE(16) */
500         { 0x93, T, "ERASE(16)" },
501         /* 94 [usage proposed by SCSI Socket Services project] */
502         /* 95 [usage proposed by SCSI Socket Services project] */
503         /* 96 [usage proposed by SCSI Socket Services project] */
504         /* 97 [usage proposed by SCSI Socket Services project] */
505         /* 98 */
506         /* 99 */
507         /* 9A */
508         /* 9B */
509         /* 9C */
510         /* 9D */
511         /* XXX KDM ALL for this?  op-num.txt defines it for none.. */
512         /* 9E                  SERVICE ACTION IN(16) */
513         { 0x9E, ALL, "SERVICE ACTION IN(16)" },
514         /* XXX KDM ALL for this?  op-num.txt defines it for ADC.. */
515         /* 9F              M   SERVICE ACTION OUT(16) */
516         { 0x9F, ALL, "SERVICE ACTION OUT(16)" },
517         /* A0  MMOOO OMMM OMO  REPORT LUNS */
518         { 0xA0, ALL & ~(R | B), "REPORT LUNS" },
519         /* A1       O          BLANK */
520         { 0xA1, R, "BLANK" },
521         /* A1  O         O     ATA COMMAND PASS THROUGH(12) */
522         { 0xA1, D | B, "ATA COMMAND PASS THROUGH(12)" },
523         /* A2  OO   O      O   SECURITY PROTOCOL IN */
524         { 0xA2, D | T | R | V, "SECURITY PROTOCOL IN" },
525         /* A3  OOO O OOMOOOM   MAINTENANCE (IN) */
526         { 0xA3, ALL & ~(P | R | F), "MAINTENANCE (IN)" },
527         /* A3       O          SEND KEY */
528         { 0xA3, R, "SEND KEY" },
529         /* A4  OOO O OOOOOOO   MAINTENANCE (OUT) */
530         { 0xA4, ALL & ~(P | R | F), "MAINTENANCE (OUT)" },
531         /* A4       O          REPORT KEY */
532         { 0xA4, R, "REPORT KEY" },
533         /* A5   O  O OM        MOVE MEDIUM */
534         { 0xA5, T | W | O | M, "MOVE MEDIUM" },
535         /* A5       O          PLAY AUDIO(12) */
536         { 0xA5, R, "PLAY AUDIO(12)" },
537         /* A6         O        EXCHANGE MEDIUM */
538         { 0xA6, M, "EXCHANGE MEDIUM" },
539         /* A6       O          LOAD/UNLOAD C/DVD */
540         { 0xA6, R, "LOAD/UNLOAD C/DVD" },
541         /* A7  ZZ  O O         MOVE MEDIUM ATTACHED */
542         { 0xA7, D | T | W | O, "MOVE MEDIUM ATTACHED" },
543         /* A7       O          SET READ AHEAD */
544         { 0xA7, R, "SET READ AHEAD" },
545         /* A8  O   OOO         READ(12) */
546         { 0xA8, D | W | R | O, "READ(12)" },
547         /* A8                  GET MESSAGE(12) */
548         { 0xA8, C, "GET MESSAGE(12)" },
549         /* A9              O   SERVICE ACTION OUT(12) */
550         { 0xA9, V, "SERVICE ACTION OUT(12)" },
551         /* AA  O   OOO         WRITE(12) */
552         { 0xAA, D | W | R | O, "WRITE(12)" },
553         /* AA                  SEND MESSAGE(12) */
554         { 0xAA, C, "SEND MESSAGE(12)" },
555         /* AB       O      O   SERVICE ACTION IN(12) */
556         { 0xAB, R | V, "SERVICE ACTION IN(12)" },
557         /* AC        O         ERASE(12) */
558         { 0xAC, O, "ERASE(12)" },
559         /* AC       O          GET PERFORMANCE */
560         { 0xAC, R, "GET PERFORMANCE" },
561         /* AD       O          READ DVD STRUCTURE */
562         { 0xAD, R, "READ DVD STRUCTURE" },
563         /* AE  O   O O         WRITE AND VERIFY(12) */
564         { 0xAE, D | W | O, "WRITE AND VERIFY(12)" },
565         /* AF  O   OZO         VERIFY(12) */
566         { 0xAF, D | W | R | O, "VERIFY(12)" },
567         /* B0      ZZZ         SEARCH DATA HIGH(12) */
568         { 0xB0, W | R | O, "SEARCH DATA HIGH(12)" },
569         /* B1      ZZZ         SEARCH DATA EQUAL(12) */
570         { 0xB1, W | R | O, "SEARCH DATA EQUAL(12)" },
571         /* B2      ZZZ         SEARCH DATA LOW(12) */
572         { 0xB2, W | R | O, "SEARCH DATA LOW(12)" },
573         /* B3  Z   OZO         SET LIMITS(12) */
574         { 0xB3, D | W | R | O, "SET LIMITS(12)" },
575         /* B4  ZZ  OZO         READ ELEMENT STATUS ATTACHED */
576         { 0xB4, D | T | W | R | O, "READ ELEMENT STATUS ATTACHED" },
577         /* B5  OO   O      O   SECURITY PROTOCOL OUT */
578         { 0xB5, D | T | R | V, "SECURITY PROTOCOL OUT" },
579         /* B5         O        REQUEST VOLUME ELEMENT ADDRESS */
580         { 0xB5, M, "REQUEST VOLUME ELEMENT ADDRESS" },
581         /* B6         O        SEND VOLUME TAG */
582         { 0xB6, M, "SEND VOLUME TAG" },
583         /* B6       O          SET STREAMING */
584         { 0xB6, R, "SET STREAMING" },
585         /* B7  O     O         READ DEFECT DATA(12) */
586         { 0xB7, D | O, "READ DEFECT DATA(12)" },
587         /* B8   O  OZOM        READ ELEMENT STATUS */
588         { 0xB8, T | W | R | O | M, "READ ELEMENT STATUS" },
589         /* B9       O          READ CD MSF */
590         { 0xB9, R, "READ CD MSF" },
591         /* BA  O   O OOMO      REDUNDANCY GROUP (IN) */
592         { 0xBA, D | W | O | M | A | E, "REDUNDANCY GROUP (IN)" },
593         /* BA       O          SCAN */
594         { 0xBA, R, "SCAN" },
595         /* BB  O   O OOOO      REDUNDANCY GROUP (OUT) */
596         { 0xBB, D | W | O | M | A | E, "REDUNDANCY GROUP (OUT)" },
597         /* BB       O          SET CD SPEED */
598         { 0xBB, R, "SET CD SPEED" },
599         /* BC  O   O OOMO      SPARE (IN) */
600         { 0xBC, D | W | O | M | A | E, "SPARE (IN)" },
601         /* BD  O   O OOOO      SPARE (OUT) */
602         { 0xBD, D | W | O | M | A | E, "SPARE (OUT)" },
603         /* BD       O          MECHANISM STATUS */
604         { 0xBD, R, "MECHANISM STATUS" },
605         /* BE  O   O OOMO      VOLUME SET (IN) */
606         { 0xBE, D | W | O | M | A | E, "VOLUME SET (IN)" },
607         /* BE       O          READ CD */
608         { 0xBE, R, "READ CD" },
609         /* BF  O   O OOOO      VOLUME SET (OUT) */
610         { 0xBF, D | W | O | M | A | E, "VOLUME SET (OUT)" },
611         /* BF       O          SEND DVD STRUCTURE */
612         { 0xBF, R, "SEND DVD STRUCTURE" }
613 };
614
615 const char *
616 scsi_op_desc(u_int16_t opcode, struct scsi_inquiry_data *inq_data)
617 {
618         caddr_t match;
619         int i, j;
620         u_int32_t opmask;
621         u_int16_t pd_type;
622         int       num_ops[2];
623         struct op_table_entry *table[2];
624         int num_tables;
625
626         /*
627          * If we've got inquiry data, use it to determine what type of
628          * device we're dealing with here.  Otherwise, assume direct
629          * access.
630          */
631         if (inq_data == NULL) {
632                 pd_type = T_DIRECT;
633                 match = NULL;
634         } else {
635                 pd_type = SID_TYPE(inq_data);
636
637                 match = cam_quirkmatch((caddr_t)inq_data,
638                                        (caddr_t)scsi_op_quirk_table,
639                                        sizeof(scsi_op_quirk_table)/
640                                        sizeof(*scsi_op_quirk_table),
641                                        sizeof(*scsi_op_quirk_table),
642                                        scsi_inquiry_match);
643         }
644
645         if (match != NULL) {
646                 table[0] = ((struct scsi_op_quirk_entry *)match)->op_table;
647                 num_ops[0] = ((struct scsi_op_quirk_entry *)match)->num_ops;
648                 table[1] = scsi_op_codes;
649                 num_ops[1] = sizeof(scsi_op_codes)/sizeof(scsi_op_codes[0]);
650                 num_tables = 2;
651         } else {
652                 /*      
653                  * If this is true, we have a vendor specific opcode that
654                  * wasn't covered in the quirk table.
655                  */
656                 if ((opcode > 0xBF) || ((opcode > 0x5F) && (opcode < 0x80)))
657                         return("Vendor Specific Command");
658
659                 table[0] = scsi_op_codes;
660                 num_ops[0] = sizeof(scsi_op_codes)/sizeof(scsi_op_codes[0]);
661                 num_tables = 1;
662         }
663
664         /* RBC is 'Simplified' Direct Access Device */
665         if (pd_type == T_RBC)
666                 pd_type = T_DIRECT;
667
668         /* Map NODEVICE to Direct Access Device to handle REPORT LUNS, etc. */
669         if (pd_type == T_NODEVICE)
670                 pd_type = T_DIRECT;
671
672         opmask = 1 << pd_type;
673
674         for (j = 0; j < num_tables; j++) {
675                 for (i = 0;i < num_ops[j] && table[j][i].opcode <= opcode; i++){
676                         if ((table[j][i].opcode == opcode) 
677                          && ((table[j][i].opmask & opmask) != 0))
678                                 return(table[j][i].desc);
679                 }
680         }
681         
682         /*
683          * If we can't find a match for the command in the table, we just
684          * assume it's a vendor specifc command.
685          */
686         return("Vendor Specific Command");
687
688 }
689
690 #else /* SCSI_NO_OP_STRINGS */
691
692 const char *
693 scsi_op_desc(u_int16_t opcode, struct scsi_inquiry_data *inq_data)
694 {
695         return("");
696 }
697
698 #endif
699
700
701 #if !defined(SCSI_NO_SENSE_STRINGS)
702 #define SST(asc, ascq, action, desc) \
703         asc, ascq, action, desc
704 #else 
705 const char empty_string[] = "";
706
707 #define SST(asc, ascq, action, desc) \
708         asc, ascq, action, empty_string
709 #endif 
710
711 const struct sense_key_table_entry sense_key_table[] = 
712 {
713         { SSD_KEY_NO_SENSE, SS_NOP, "NO SENSE" },
714         { SSD_KEY_RECOVERED_ERROR, SS_NOP|SSQ_PRINT_SENSE, "RECOVERED ERROR" },
715         { SSD_KEY_NOT_READY, SS_RDEF, "NOT READY" },
716         { SSD_KEY_MEDIUM_ERROR, SS_RDEF, "MEDIUM ERROR" },
717         { SSD_KEY_HARDWARE_ERROR, SS_RDEF, "HARDWARE FAILURE" },
718         { SSD_KEY_ILLEGAL_REQUEST, SS_FATAL|EINVAL, "ILLEGAL REQUEST" },
719         { SSD_KEY_UNIT_ATTENTION, SS_FATAL|ENXIO, "UNIT ATTENTION" },
720         { SSD_KEY_DATA_PROTECT, SS_FATAL|EACCES, "DATA PROTECT" },
721         { SSD_KEY_BLANK_CHECK, SS_FATAL|ENOSPC, "BLANK CHECK" },
722         { SSD_KEY_Vendor_Specific, SS_FATAL|EIO, "Vendor Specific" },
723         { SSD_KEY_COPY_ABORTED, SS_FATAL|EIO, "COPY ABORTED" },
724         { SSD_KEY_ABORTED_COMMAND, SS_RDEF, "ABORTED COMMAND" },
725         { SSD_KEY_EQUAL, SS_NOP, "EQUAL" },
726         { SSD_KEY_VOLUME_OVERFLOW, SS_FATAL|EIO, "VOLUME OVERFLOW" },
727         { SSD_KEY_MISCOMPARE, SS_NOP, "MISCOMPARE" },
728         { SSD_KEY_COMPLETED, SS_NOP, "COMPLETED" }
729 };
730
731 const int sense_key_table_size =
732     sizeof(sense_key_table)/sizeof(sense_key_table[0]);
733
734 static struct asc_table_entry quantum_fireball_entries[] = {
735         { SST(0x04, 0x0b, SS_START | SSQ_DECREMENT_COUNT | ENXIO, 
736              "Logical unit not ready, initializing cmd. required") }
737 };
738
739 static struct asc_table_entry sony_mo_entries[] = {
740         { SST(0x04, 0x00, SS_START | SSQ_DECREMENT_COUNT | ENXIO,
741              "Logical unit not ready, cause not reportable") }
742 };
743
744 static struct asc_table_entry hgst_entries[] = {
745         { SST(0x04, 0xF0, SS_RDEF,
746             "Vendor Unique - Logical Unit Not Ready") },
747         { SST(0x0A, 0x01, SS_RDEF,
748             "Unrecovered Super Certification Log Write Error") },
749         { SST(0x0A, 0x02, SS_RDEF,
750             "Unrecovered Super Certification Log Read Error") },
751         { SST(0x15, 0x03, SS_RDEF,
752             "Unrecovered Sector Error") },
753         { SST(0x3E, 0x04, SS_RDEF,
754             "Unrecovered Self-Test Hard-Cache Test Fail") },
755         { SST(0x3E, 0x05, SS_RDEF,
756             "Unrecovered Self-Test OTF-Cache Fail") },
757         { SST(0x40, 0x00, SS_RDEF,
758             "Unrecovered SAT No Buffer Overflow Error") },
759         { SST(0x40, 0x01, SS_RDEF,
760             "Unrecovered SAT Buffer Overflow Error") },
761         { SST(0x40, 0x02, SS_RDEF,
762             "Unrecovered SAT No Buffer Overflow With ECS Fault") },
763         { SST(0x40, 0x03, SS_RDEF,
764             "Unrecovered SAT Buffer Overflow With ECS Fault") },
765         { SST(0x40, 0x81, SS_RDEF,
766             "DRAM Failure") },
767         { SST(0x44, 0x0B, SS_RDEF,
768             "Vendor Unique - Internal Target Failure") },
769         { SST(0x44, 0xF2, SS_RDEF,
770             "Vendor Unique - Internal Target Failure") },
771         { SST(0x44, 0xF6, SS_RDEF,
772             "Vendor Unique - Internal Target Failure") },
773         { SST(0x44, 0xF9, SS_RDEF,
774             "Vendor Unique - Internal Target Failure") },
775         { SST(0x44, 0xFA, SS_RDEF,
776             "Vendor Unique - Internal Target Failure") },
777         { SST(0x5D, 0x22, SS_RDEF,
778             "Extreme Over-Temperature Warning") },
779         { SST(0x5D, 0x50, SS_RDEF,
780             "Load/Unload cycle Count Warning") },
781         { SST(0x81, 0x00, SS_RDEF,
782             "Vendor Unique - Internal Logic Error") },
783         { SST(0x85, 0x00, SS_RDEF,
784             "Vendor Unique - Internal Key Seed Error") },
785 };
786
787 static struct asc_table_entry seagate_entries[] = {
788         { SST(0x04, 0xF0, SS_RDEF,
789             "Logical Unit Not Ready, super certify in Progress") },
790         { SST(0x08, 0x86, SS_RDEF,
791             "Write Fault Data Corruption") },
792         { SST(0x09, 0x0D, SS_RDEF,
793             "Tracking Failure") },
794         { SST(0x09, 0x0E, SS_RDEF,
795             "ETF Failure") },
796         { SST(0x0B, 0x5D, SS_RDEF,
797             "Pre-SMART Warning") },
798         { SST(0x0B, 0x85, SS_RDEF,
799             "5V Voltage Warning") },
800         { SST(0x0B, 0x8C, SS_RDEF,
801             "12V Voltage Warning") },
802         { SST(0x0C, 0xFF, SS_RDEF,
803             "Write Error - Too many error recovery revs") },
804         { SST(0x11, 0xFF, SS_RDEF,
805             "Unrecovered Read Error - Too many error recovery revs") },
806         { SST(0x19, 0x0E, SS_RDEF,
807             "Fewer than 1/2 defect list copies") },
808         { SST(0x20, 0xF3, SS_RDEF,
809             "Illegal CDB linked to skip mask cmd") },
810         { SST(0x24, 0xF0, SS_RDEF,
811             "Illegal byte in CDB, LBA not matching") },
812         { SST(0x24, 0xF1, SS_RDEF,
813             "Illegal byte in CDB, LEN not matching") },
814         { SST(0x24, 0xF2, SS_RDEF,
815             "Mask not matching transfer length") },
816         { SST(0x24, 0xF3, SS_RDEF,
817             "Drive formatted without plist") },
818         { SST(0x26, 0x95, SS_RDEF,
819             "Invalid Field Parameter - CAP File") },
820         { SST(0x26, 0x96, SS_RDEF,
821             "Invalid Field Parameter - RAP File") },
822         { SST(0x26, 0x97, SS_RDEF,
823             "Invalid Field Parameter - TMS Firmware Tag") },
824         { SST(0x26, 0x98, SS_RDEF,
825             "Invalid Field Parameter - Check Sum") },
826         { SST(0x26, 0x99, SS_RDEF,
827             "Invalid Field Parameter - Firmware Tag") },
828         { SST(0x29, 0x08, SS_RDEF,
829             "Write Log Dump data") },
830         { SST(0x29, 0x09, SS_RDEF,
831             "Write Log Dump data") },
832         { SST(0x29, 0x0A, SS_RDEF,
833             "Reserved disk space") },
834         { SST(0x29, 0x0B, SS_RDEF,
835             "SDBP") },
836         { SST(0x29, 0x0C, SS_RDEF,
837             "SDBP") },
838         { SST(0x31, 0x91, SS_RDEF,
839             "Format Corrupted World Wide Name (WWN) is Invalid") },
840         { SST(0x32, 0x03, SS_RDEF,
841             "Defect List - Length exceeds Command Allocated Length") },
842         { SST(0x33, 0x00, SS_RDEF,
843             "Flash not ready for access") },
844         { SST(0x3F, 0x70, SS_RDEF,
845             "Invalid RAP block") },
846         { SST(0x3F, 0x71, SS_RDEF,
847             "RAP/ETF mismatch") },
848         { SST(0x3F, 0x90, SS_RDEF,
849             "Invalid CAP block") },
850         { SST(0x3F, 0x91, SS_RDEF,
851             "World Wide Name (WWN) Mismatch") },
852         { SST(0x40, 0x01, SS_RDEF,
853             "DRAM Parity Error") },
854         { SST(0x40, 0x02, SS_RDEF,
855             "DRAM Parity Error") },
856         { SST(0x42, 0x0A, SS_RDEF,
857             "Loopback Test") },
858         { SST(0x42, 0x0B, SS_RDEF,
859             "Loopback Test") },
860         { SST(0x44, 0xF2, SS_RDEF,
861             "Compare error during data integrity check") },
862         { SST(0x44, 0xF6, SS_RDEF,
863             "Unrecoverable error during data integrity check") },
864         { SST(0x47, 0x80, SS_RDEF,
865             "Fibre Channel Sequence Error") },
866         { SST(0x4E, 0x01, SS_RDEF,
867             "Information Unit Too Short") },
868         { SST(0x80, 0x00, SS_RDEF,
869             "General Firmware Error / Command Timeout") },
870         { SST(0x80, 0x01, SS_RDEF,
871             "Command Timeout") },
872         { SST(0x80, 0x02, SS_RDEF,
873             "Command Timeout") },
874         { SST(0x80, 0x80, SS_RDEF,
875             "FC FIFO Error During Read Transfer") },
876         { SST(0x80, 0x81, SS_RDEF,
877             "FC FIFO Error During Write Transfer") },
878         { SST(0x80, 0x82, SS_RDEF,
879             "DISC FIFO Error During Read Transfer") },
880         { SST(0x80, 0x83, SS_RDEF,
881             "DISC FIFO Error During Write Transfer") },
882         { SST(0x80, 0x84, SS_RDEF,
883             "LBA Seeded LRC Error on Read") },
884         { SST(0x80, 0x85, SS_RDEF,
885             "LBA Seeded LRC Error on Write") },
886         { SST(0x80, 0x86, SS_RDEF,
887             "IOEDC Error on Read") },
888         { SST(0x80, 0x87, SS_RDEF,
889             "IOEDC Error on Write") },
890         { SST(0x80, 0x88, SS_RDEF,
891             "Host Parity Check Failed") },
892         { SST(0x80, 0x89, SS_RDEF,
893             "IOEDC error on read detected by formatter") },
894         { SST(0x80, 0x8A, SS_RDEF,
895             "Host Parity Errors / Host FIFO Initialization Failed") },
896         { SST(0x80, 0x8B, SS_RDEF,
897             "Host Parity Errors") },
898         { SST(0x80, 0x8C, SS_RDEF,
899             "Host Parity Errors") },
900         { SST(0x80, 0x8D, SS_RDEF,
901             "Host Parity Errors") },
902         { SST(0x81, 0x00, SS_RDEF,
903             "LA Check Failed") },
904         { SST(0x82, 0x00, SS_RDEF,
905             "Internal client detected insufficient buffer") },
906         { SST(0x84, 0x00, SS_RDEF,
907             "Scheduled Diagnostic And Repair") },
908 };
909
910 static struct scsi_sense_quirk_entry sense_quirk_table[] = {
911         {
912                 /*
913                  * XXX The Quantum Fireball ST and SE like to return 0x04 0x0b
914                  * when they really should return 0x04 0x02.
915                  */
916                 {T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "FIREBALL S*", "*"},
917                 /*num_sense_keys*/0,
918                 sizeof(quantum_fireball_entries)/sizeof(struct asc_table_entry),
919                 /*sense key entries*/NULL,
920                 quantum_fireball_entries
921         },
922         {
923                 /*
924                  * This Sony MO drive likes to return 0x04, 0x00 when it
925                  * isn't spun up.
926                  */
927                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "SONY", "SMO-*", "*"},
928                 /*num_sense_keys*/0,
929                 sizeof(sony_mo_entries)/sizeof(struct asc_table_entry),
930                 /*sense key entries*/NULL,
931                 sony_mo_entries
932         },
933         {
934                 /*
935                  * HGST vendor-specific error codes
936                  */
937                 {T_DIRECT, SIP_MEDIA_FIXED, "HGST", "*", "*"},
938                 /*num_sense_keys*/0,
939                 sizeof(hgst_entries)/sizeof(struct asc_table_entry),
940                 /*sense key entries*/NULL,
941                 hgst_entries
942         },
943         {
944                 /*
945                  * SEAGATE vendor-specific error codes
946                  */
947                 {T_DIRECT, SIP_MEDIA_FIXED, "SEAGATE", "*", "*"},
948                 /*num_sense_keys*/0,
949                 sizeof(seagate_entries)/sizeof(struct asc_table_entry),
950                 /*sense key entries*/NULL,
951                 seagate_entries
952         }
953 };
954
955 const int sense_quirk_table_size =
956     sizeof(sense_quirk_table)/sizeof(sense_quirk_table[0]);
957
958 static struct asc_table_entry asc_table[] = {
959         /*
960          * From: http://www.t10.org/lists/asc-num.txt
961          * Modifications by Jung-uk Kim (jkim@FreeBSD.org)
962          */
963         /*
964          * File: ASC-NUM.TXT
965          *
966          * SCSI ASC/ASCQ Assignments
967          * Numeric Sorted Listing
968          * as of  5/20/12
969          *
970          * D - DIRECT ACCESS DEVICE (SBC-2)                   device column key
971          * .T - SEQUENTIAL ACCESS DEVICE (SSC)               -------------------
972          * . L - PRINTER DEVICE (SSC)                           blank = reserved
973          * .  P - PROCESSOR DEVICE (SPC)                     not blank = allowed
974          * .  .W - WRITE ONCE READ MULTIPLE DEVICE (SBC-2)
975          * .  . R - CD DEVICE (MMC)
976          * .  .  O - OPTICAL MEMORY DEVICE (SBC-2)
977          * .  .  .M - MEDIA CHANGER DEVICE (SMC)
978          * .  .  . A - STORAGE ARRAY DEVICE (SCC)
979          * .  .  .  E - ENCLOSURE SERVICES DEVICE (SES)
980          * .  .  .  .B - SIMPLIFIED DIRECT-ACCESS DEVICE (RBC)
981          * .  .  .  . K - OPTICAL CARD READER/WRITER DEVICE (OCRW)
982          * .  .  .  .  V - AUTOMATION/DRIVE INTERFACE (ADC)
983          * .  .  .  .  .F - OBJECT-BASED STORAGE (OSD)
984          * DTLPWROMAEBKVF
985          * ASC      ASCQ  Action
986          * Description
987          */
988         /* DTLPWROMAEBKVF */
989         { SST(0x00, 0x00, SS_NOP,
990             "No additional sense information") },
991         /*  T             */
992         { SST(0x00, 0x01, SS_RDEF,
993             "Filemark detected") },
994         /*  T             */
995         { SST(0x00, 0x02, SS_RDEF,
996             "End-of-partition/medium detected") },
997         /*  T             */
998         { SST(0x00, 0x03, SS_RDEF,
999             "Setmark detected") },
1000         /*  T             */
1001         { SST(0x00, 0x04, SS_RDEF,
1002             "Beginning-of-partition/medium detected") },
1003         /*  TL            */
1004         { SST(0x00, 0x05, SS_RDEF,
1005             "End-of-data detected") },
1006         /* DTLPWROMAEBKVF */
1007         { SST(0x00, 0x06, SS_RDEF,
1008             "I/O process terminated") },
1009         /*  T             */
1010         { SST(0x00, 0x07, SS_RDEF,      /* XXX TBD */
1011             "Programmable early warning detected") },
1012         /*      R         */
1013         { SST(0x00, 0x11, SS_FATAL | EBUSY,
1014             "Audio play operation in progress") },
1015         /*      R         */
1016         { SST(0x00, 0x12, SS_NOP,
1017             "Audio play operation paused") },
1018         /*      R         */
1019         { SST(0x00, 0x13, SS_NOP,
1020             "Audio play operation successfully completed") },
1021         /*      R         */
1022         { SST(0x00, 0x14, SS_RDEF,
1023             "Audio play operation stopped due to error") },
1024         /*      R         */
1025         { SST(0x00, 0x15, SS_NOP,
1026             "No current audio status to return") },
1027         /* DTLPWROMAEBKVF */
1028         { SST(0x00, 0x16, SS_FATAL | EBUSY,
1029             "Operation in progress") },
1030         /* DTL WROMAEBKVF */
1031         { SST(0x00, 0x17, SS_RDEF,
1032             "Cleaning requested") },
1033         /*  T             */
1034         { SST(0x00, 0x18, SS_RDEF,      /* XXX TBD */
1035             "Erase operation in progress") },
1036         /*  T             */
1037         { SST(0x00, 0x19, SS_RDEF,      /* XXX TBD */
1038             "Locate operation in progress") },
1039         /*  T             */
1040         { SST(0x00, 0x1A, SS_RDEF,      /* XXX TBD */
1041             "Rewind operation in progress") },
1042         /*  T             */
1043         { SST(0x00, 0x1B, SS_RDEF,      /* XXX TBD */
1044             "Set capacity operation in progress") },
1045         /*  T             */
1046         { SST(0x00, 0x1C, SS_RDEF,      /* XXX TBD */
1047             "Verify operation in progress") },
1048         /* DT        B    */
1049         { SST(0x00, 0x1D, SS_RDEF,      /* XXX TBD */
1050             "ATA pass through information available") },
1051         /* DT   R MAEBKV  */
1052         { SST(0x00, 0x1E, SS_RDEF,      /* XXX TBD */
1053             "Conflicting SA creation request") },
1054         /* DT        B    */
1055         { SST(0x00, 0x1F, SS_RDEF,      /* XXX TBD */
1056             "Logical unit transitioning to another power condition") },
1057         /* DT P      B    */
1058         { SST(0x00, 0x20, SS_RDEF,      /* XXX TBD */
1059             "Extended copy information available") },
1060         /* D   W O   BK   */
1061         { SST(0x01, 0x00, SS_RDEF,
1062             "No index/sector signal") },
1063         /* D   WRO   BK   */
1064         { SST(0x02, 0x00, SS_RDEF,
1065             "No seek complete") },
1066         /* DTL W O   BK   */
1067         { SST(0x03, 0x00, SS_RDEF,
1068             "Peripheral device write fault") },
1069         /*  T             */
1070         { SST(0x03, 0x01, SS_RDEF,
1071             "No write current") },
1072         /*  T             */
1073         { SST(0x03, 0x02, SS_RDEF,
1074             "Excessive write errors") },
1075         /* DTLPWROMAEBKVF */
1076         { SST(0x04, 0x00, SS_RDEF,
1077             "Logical unit not ready, cause not reportable") },
1078         /* DTLPWROMAEBKVF */
1079         { SST(0x04, 0x01, SS_TUR | SSQ_MANY | SSQ_DECREMENT_COUNT | EBUSY,
1080             "Logical unit is in process of becoming ready") },
1081         /* DTLPWROMAEBKVF */
1082         { SST(0x04, 0x02, SS_START | SSQ_DECREMENT_COUNT | ENXIO,
1083             "Logical unit not ready, initializing command required") },
1084         /* DTLPWROMAEBKVF */
1085         { SST(0x04, 0x03, SS_FATAL | ENXIO,
1086             "Logical unit not ready, manual intervention required") },
1087         /* DTL  RO   B    */
1088         { SST(0x04, 0x04, SS_FATAL | EBUSY,
1089             "Logical unit not ready, format in progress") },
1090         /* DT  W O A BK F */
1091         { SST(0x04, 0x05, SS_FATAL | EBUSY,
1092             "Logical unit not ready, rebuild in progress") },
1093         /* DT  W O A BK   */
1094         { SST(0x04, 0x06, SS_FATAL | EBUSY,
1095             "Logical unit not ready, recalculation in progress") },
1096         /* DTLPWROMAEBKVF */
1097         { SST(0x04, 0x07, SS_FATAL | EBUSY,
1098             "Logical unit not ready, operation in progress") },
1099         /*      R         */
1100         { SST(0x04, 0x08, SS_FATAL | EBUSY,
1101             "Logical unit not ready, long write in progress") },
1102         /* DTLPWROMAEBKVF */
1103         { SST(0x04, 0x09, SS_RDEF,      /* XXX TBD */
1104             "Logical unit not ready, self-test in progress") },
1105         /* DTLPWROMAEBKVF */
1106         { SST(0x04, 0x0A, SS_RDEF,      /* XXX TBD */
1107             "Logical unit not accessible, asymmetric access state transition")},
1108         /* DTLPWROMAEBKVF */
1109         { SST(0x04, 0x0B, SS_RDEF,      /* XXX TBD */
1110             "Logical unit not accessible, target port in standby state") },
1111         /* DTLPWROMAEBKVF */
1112         { SST(0x04, 0x0C, SS_RDEF,      /* XXX TBD */
1113             "Logical unit not accessible, target port in unavailable state") },
1114         /*              F */
1115         { SST(0x04, 0x0D, SS_RDEF,      /* XXX TBD */
1116             "Logical unit not ready, structure check required") },
1117         /* DT  WROM  B    */
1118         { SST(0x04, 0x10, SS_RDEF,      /* XXX TBD */
1119             "Logical unit not ready, auxiliary memory not accessible") },
1120         /* DT  WRO AEB VF */
1121         { SST(0x04, 0x11, SS_TUR | SSQ_MANY | SSQ_DECREMENT_COUNT | EBUSY,
1122             "Logical unit not ready, notify (enable spinup) required") },
1123         /*        M    V  */
1124         { SST(0x04, 0x12, SS_RDEF,      /* XXX TBD */
1125             "Logical unit not ready, offline") },
1126         /* DT   R MAEBKV  */
1127         { SST(0x04, 0x13, SS_RDEF,      /* XXX TBD */
1128             "Logical unit not ready, SA creation in progress") },
1129         /* D         B    */
1130         { SST(0x04, 0x14, SS_RDEF,      /* XXX TBD */
1131             "Logical unit not ready, space allocation in progress") },
1132         /*        M       */
1133         { SST(0x04, 0x15, SS_RDEF,      /* XXX TBD */
1134             "Logical unit not ready, robotics disabled") },
1135         /*        M       */
1136         { SST(0x04, 0x16, SS_RDEF,      /* XXX TBD */
1137             "Logical unit not ready, configuration required") },
1138         /*        M       */
1139         { SST(0x04, 0x17, SS_RDEF,      /* XXX TBD */
1140             "Logical unit not ready, calibration required") },
1141         /*        M       */
1142         { SST(0x04, 0x18, SS_RDEF,      /* XXX TBD */
1143             "Logical unit not ready, a door is open") },
1144         /*        M       */
1145         { SST(0x04, 0x19, SS_RDEF,      /* XXX TBD */
1146             "Logical unit not ready, operating in sequential mode") },
1147         /* DT        B    */
1148         { SST(0x04, 0x1A, SS_RDEF,      /* XXX TBD */
1149             "Logical unit not ready, START/STOP UNIT command in progress") },
1150         /* D         B    */
1151         { SST(0x04, 0x1B, SS_RDEF,      /* XXX TBD */
1152             "Logical unit not ready, sanitize in progress") },
1153         /* DT     MAEB    */
1154         { SST(0x04, 0x1C, SS_RDEF,      /* XXX TBD */
1155             "Logical unit not ready, additional power use not yet granted") },
1156         /* DTL WROMAEBKVF */
1157         { SST(0x05, 0x00, SS_RDEF,
1158             "Logical unit does not respond to selection") },
1159         /* D   WROM  BK   */
1160         { SST(0x06, 0x00, SS_RDEF,
1161             "No reference position found") },
1162         /* DTL WROM  BK   */
1163         { SST(0x07, 0x00, SS_RDEF,
1164             "Multiple peripheral devices selected") },
1165         /* DTL WROMAEBKVF */
1166         { SST(0x08, 0x00, SS_RDEF,
1167             "Logical unit communication failure") },
1168         /* DTL WROMAEBKVF */
1169         { SST(0x08, 0x01, SS_RDEF,
1170             "Logical unit communication time-out") },
1171         /* DTL WROMAEBKVF */
1172         { SST(0x08, 0x02, SS_RDEF,
1173             "Logical unit communication parity error") },
1174         /* DT   ROM  BK   */
1175         { SST(0x08, 0x03, SS_RDEF,
1176             "Logical unit communication CRC error (Ultra-DMA/32)") },
1177         /* DTLPWRO    K   */
1178         { SST(0x08, 0x04, SS_RDEF,      /* XXX TBD */
1179             "Unreachable copy target") },
1180         /* DT  WRO   B    */
1181         { SST(0x09, 0x00, SS_RDEF,
1182             "Track following error") },
1183         /*     WRO    K   */
1184         { SST(0x09, 0x01, SS_RDEF,
1185             "Tracking servo failure") },
1186         /*     WRO    K   */
1187         { SST(0x09, 0x02, SS_RDEF,
1188             "Focus servo failure") },
1189         /*     WRO        */
1190         { SST(0x09, 0x03, SS_RDEF,
1191             "Spindle servo failure") },
1192         /* DT  WRO   B    */
1193         { SST(0x09, 0x04, SS_RDEF,
1194             "Head select fault") },
1195         /* DTLPWROMAEBKVF */
1196         { SST(0x0A, 0x00, SS_FATAL | ENOSPC,
1197             "Error log overflow") },
1198         /* DTLPWROMAEBKVF */
1199         { SST(0x0B, 0x00, SS_RDEF,
1200             "Warning") },
1201         /* DTLPWROMAEBKVF */
1202         { SST(0x0B, 0x01, SS_RDEF,
1203             "Warning - specified temperature exceeded") },
1204         /* DTLPWROMAEBKVF */
1205         { SST(0x0B, 0x02, SS_RDEF,
1206             "Warning - enclosure degraded") },
1207         /* DTLPWROMAEBKVF */
1208         { SST(0x0B, 0x03, SS_RDEF,      /* XXX TBD */
1209             "Warning - background self-test failed") },
1210         /* DTLPWRO AEBKVF */
1211         { SST(0x0B, 0x04, SS_RDEF,      /* XXX TBD */
1212             "Warning - background pre-scan detected medium error") },
1213         /* DTLPWRO AEBKVF */
1214         { SST(0x0B, 0x05, SS_RDEF,      /* XXX TBD */
1215             "Warning - background medium scan detected medium error") },
1216         /* DTLPWROMAEBKVF */
1217         { SST(0x0B, 0x06, SS_RDEF,      /* XXX TBD */
1218             "Warning - non-volatile cache now volatile") },
1219         /* DTLPWROMAEBKVF */
1220         { SST(0x0B, 0x07, SS_RDEF,      /* XXX TBD */
1221             "Warning - degraded power to non-volatile cache") },
1222         /* DTLPWROMAEBKVF */
1223         { SST(0x0B, 0x08, SS_RDEF,      /* XXX TBD */
1224             "Warning - power loss expected") },
1225         /* D              */
1226         { SST(0x0B, 0x09, SS_RDEF,      /* XXX TBD */
1227             "Warning - device statistics notification available") },
1228         /*  T   R         */
1229         { SST(0x0C, 0x00, SS_RDEF,
1230             "Write error") },
1231         /*            K   */
1232         { SST(0x0C, 0x01, SS_NOP | SSQ_PRINT_SENSE,
1233             "Write error - recovered with auto reallocation") },
1234         /* D   W O   BK   */
1235         { SST(0x0C, 0x02, SS_RDEF,
1236             "Write error - auto reallocation failed") },
1237         /* D   W O   BK   */
1238         { SST(0x0C, 0x03, SS_RDEF,
1239             "Write error - recommend reassignment") },
1240         /* DT  W O   B    */
1241         { SST(0x0C, 0x04, SS_RDEF,
1242             "Compression check miscompare error") },
1243         /* DT  W O   B    */
1244         { SST(0x0C, 0x05, SS_RDEF,
1245             "Data expansion occurred during compression") },
1246         /* DT  W O   B    */
1247         { SST(0x0C, 0x06, SS_RDEF,
1248             "Block not compressible") },
1249         /*      R         */
1250         { SST(0x0C, 0x07, SS_RDEF,
1251             "Write error - recovery needed") },
1252         /*      R         */
1253         { SST(0x0C, 0x08, SS_RDEF,
1254             "Write error - recovery failed") },
1255         /*      R         */
1256         { SST(0x0C, 0x09, SS_RDEF,
1257             "Write error - loss of streaming") },
1258         /*      R         */
1259         { SST(0x0C, 0x0A, SS_RDEF,
1260             "Write error - padding blocks added") },
1261         /* DT  WROM  B    */
1262         { SST(0x0C, 0x0B, SS_RDEF,      /* XXX TBD */
1263             "Auxiliary memory write error") },
1264         /* DTLPWRO AEBKVF */
1265         { SST(0x0C, 0x0C, SS_RDEF,      /* XXX TBD */
1266             "Write error - unexpected unsolicited data") },
1267         /* DTLPWRO AEBKVF */
1268         { SST(0x0C, 0x0D, SS_RDEF,      /* XXX TBD */
1269             "Write error - not enough unsolicited data") },
1270         /* DT  W O   BK   */
1271         { SST(0x0C, 0x0E, SS_RDEF,      /* XXX TBD */
1272             "Multiple write errors") },
1273         /*      R         */
1274         { SST(0x0C, 0x0F, SS_RDEF,      /* XXX TBD */
1275             "Defects in error window") },
1276         /* DTLPWRO A  K   */
1277         { SST(0x0D, 0x00, SS_RDEF,      /* XXX TBD */
1278             "Error detected by third party temporary initiator") },
1279         /* DTLPWRO A  K   */
1280         { SST(0x0D, 0x01, SS_RDEF,      /* XXX TBD */
1281             "Third party device failure") },
1282         /* DTLPWRO A  K   */
1283         { SST(0x0D, 0x02, SS_RDEF,      /* XXX TBD */
1284             "Copy target device not reachable") },
1285         /* DTLPWRO A  K   */
1286         { SST(0x0D, 0x03, SS_RDEF,      /* XXX TBD */
1287             "Incorrect copy target device type") },
1288         /* DTLPWRO A  K   */
1289         { SST(0x0D, 0x04, SS_RDEF,      /* XXX TBD */
1290             "Copy target device data underrun") },
1291         /* DTLPWRO A  K   */
1292         { SST(0x0D, 0x05, SS_RDEF,      /* XXX TBD */
1293             "Copy target device data overrun") },
1294         /* DT PWROMAEBK F */
1295         { SST(0x0E, 0x00, SS_RDEF,      /* XXX TBD */
1296             "Invalid information unit") },
1297         /* DT PWROMAEBK F */
1298         { SST(0x0E, 0x01, SS_RDEF,      /* XXX TBD */
1299             "Information unit too short") },
1300         /* DT PWROMAEBK F */
1301         { SST(0x0E, 0x02, SS_RDEF,      /* XXX TBD */
1302             "Information unit too long") },
1303         /* DT P R MAEBK F */
1304         { SST(0x0E, 0x03, SS_RDEF,      /* XXX TBD */
1305             "Invalid field in command information unit") },
1306         /* D   W O   BK   */
1307         { SST(0x10, 0x00, SS_RDEF,
1308             "ID CRC or ECC error") },
1309         /* DT  W O        */
1310         { SST(0x10, 0x01, SS_RDEF,      /* XXX TBD */
1311             "Logical block guard check failed") },
1312         /* DT  W O        */
1313         { SST(0x10, 0x02, SS_RDEF,      /* XXX TBD */
1314             "Logical block application tag check failed") },
1315         /* DT  W O        */
1316         { SST(0x10, 0x03, SS_RDEF,      /* XXX TBD */
1317             "Logical block reference tag check failed") },
1318         /*  T             */
1319         { SST(0x10, 0x04, SS_RDEF,      /* XXX TBD */
1320             "Logical block protection error on recovered buffer data") },
1321         /*  T             */
1322         { SST(0x10, 0x05, SS_RDEF,      /* XXX TBD */
1323             "Logical block protection method error") },
1324         /* DT  WRO   BK   */
1325         { SST(0x11, 0x00, SS_FATAL|EIO,
1326             "Unrecovered read error") },
1327         /* DT  WRO   BK   */
1328         { SST(0x11, 0x01, SS_FATAL|EIO,
1329             "Read retries exhausted") },
1330         /* DT  WRO   BK   */
1331         { SST(0x11, 0x02, SS_FATAL|EIO,
1332             "Error too long to correct") },
1333         /* DT  W O   BK   */
1334         { SST(0x11, 0x03, SS_FATAL|EIO,
1335             "Multiple read errors") },
1336         /* D   W O   BK   */
1337         { SST(0x11, 0x04, SS_FATAL|EIO,
1338             "Unrecovered read error - auto reallocate failed") },
1339         /*     WRO   B    */
1340         { SST(0x11, 0x05, SS_FATAL|EIO,
1341             "L-EC uncorrectable error") },
1342         /*     WRO   B    */
1343         { SST(0x11, 0x06, SS_FATAL|EIO,
1344             "CIRC unrecovered error") },
1345         /*     W O   B    */
1346         { SST(0x11, 0x07, SS_RDEF,
1347             "Data re-synchronization error") },
1348         /*  T             */
1349         { SST(0x11, 0x08, SS_RDEF,
1350             "Incomplete block read") },
1351         /*  T             */
1352         { SST(0x11, 0x09, SS_RDEF,
1353             "No gap found") },
1354         /* DT    O   BK   */
1355         { SST(0x11, 0x0A, SS_RDEF,
1356             "Miscorrected error") },
1357         /* D   W O   BK   */
1358         { SST(0x11, 0x0B, SS_FATAL|EIO,
1359             "Unrecovered read error - recommend reassignment") },
1360         /* D   W O   BK   */
1361         { SST(0x11, 0x0C, SS_FATAL|EIO,
1362             "Unrecovered read error - recommend rewrite the data") },
1363         /* DT  WRO   B    */
1364         { SST(0x11, 0x0D, SS_RDEF,
1365             "De-compression CRC error") },
1366         /* DT  WRO   B    */
1367         { SST(0x11, 0x0E, SS_RDEF,
1368             "Cannot decompress using declared algorithm") },
1369         /*      R         */
1370         { SST(0x11, 0x0F, SS_RDEF,
1371             "Error reading UPC/EAN number") },
1372         /*      R         */
1373         { SST(0x11, 0x10, SS_RDEF,
1374             "Error reading ISRC number") },
1375         /*      R         */
1376         { SST(0x11, 0x11, SS_RDEF,
1377             "Read error - loss of streaming") },
1378         /* DT  WROM  B    */
1379         { SST(0x11, 0x12, SS_RDEF,      /* XXX TBD */
1380             "Auxiliary memory read error") },
1381         /* DTLPWRO AEBKVF */
1382         { SST(0x11, 0x13, SS_RDEF,      /* XXX TBD */
1383             "Read error - failed retransmission request") },
1384         /* D              */
1385         { SST(0x11, 0x14, SS_RDEF,      /* XXX TBD */
1386             "Read error - LBA marked bad by application client") },
1387         /* D   W O   BK   */
1388         { SST(0x12, 0x00, SS_RDEF,
1389             "Address mark not found for ID field") },
1390         /* D   W O   BK   */
1391         { SST(0x13, 0x00, SS_RDEF,
1392             "Address mark not found for data field") },
1393         /* DTL WRO   BK   */
1394         { SST(0x14, 0x00, SS_RDEF,
1395             "Recorded entity not found") },
1396         /* DT  WRO   BK   */
1397         { SST(0x14, 0x01, SS_RDEF,
1398             "Record not found") },
1399         /*  T             */
1400         { SST(0x14, 0x02, SS_RDEF,
1401             "Filemark or setmark not found") },
1402         /*  T             */
1403         { SST(0x14, 0x03, SS_RDEF,
1404             "End-of-data not found") },
1405         /*  T             */
1406         { SST(0x14, 0x04, SS_RDEF,
1407             "Block sequence error") },
1408         /* DT  W O   BK   */
1409         { SST(0x14, 0x05, SS_RDEF,
1410             "Record not found - recommend reassignment") },
1411         /* DT  W O   BK   */
1412         { SST(0x14, 0x06, SS_RDEF,
1413             "Record not found - data auto-reallocated") },
1414         /*  T             */
1415         { SST(0x14, 0x07, SS_RDEF,      /* XXX TBD */
1416             "Locate operation failure") },
1417         /* DTL WROM  BK   */
1418         { SST(0x15, 0x00, SS_RDEF,
1419             "Random positioning error") },
1420         /* DTL WROM  BK   */
1421         { SST(0x15, 0x01, SS_RDEF,
1422             "Mechanical positioning error") },
1423         /* DT  WRO   BK   */
1424         { SST(0x15, 0x02, SS_RDEF,
1425             "Positioning error detected by read of medium") },
1426         /* D   W O   BK   */
1427         { SST(0x16, 0x00, SS_RDEF,
1428             "Data synchronization mark error") },
1429         /* D   W O   BK   */
1430         { SST(0x16, 0x01, SS_RDEF,
1431             "Data sync error - data rewritten") },
1432         /* D   W O   BK   */
1433         { SST(0x16, 0x02, SS_RDEF,
1434             "Data sync error - recommend rewrite") },
1435         /* D   W O   BK   */
1436         { SST(0x16, 0x03, SS_NOP | SSQ_PRINT_SENSE,
1437             "Data sync error - data auto-reallocated") },
1438         /* D   W O   BK   */
1439         { SST(0x16, 0x04, SS_RDEF,
1440             "Data sync error - recommend reassignment") },
1441         /* DT  WRO   BK   */
1442         { SST(0x17, 0x00, SS_NOP | SSQ_PRINT_SENSE,
1443             "Recovered data with no error correction applied") },
1444         /* DT  WRO   BK   */
1445         { SST(0x17, 0x01, SS_NOP | SSQ_PRINT_SENSE,
1446             "Recovered data with retries") },
1447         /* DT  WRO   BK   */
1448         { SST(0x17, 0x02, SS_NOP | SSQ_PRINT_SENSE,
1449             "Recovered data with positive head offset") },
1450         /* DT  WRO   BK   */
1451         { SST(0x17, 0x03, SS_NOP | SSQ_PRINT_SENSE,
1452             "Recovered data with negative head offset") },
1453         /*     WRO   B    */
1454         { SST(0x17, 0x04, SS_NOP | SSQ_PRINT_SENSE,
1455             "Recovered data with retries and/or CIRC applied") },
1456         /* D   WRO   BK   */
1457         { SST(0x17, 0x05, SS_NOP | SSQ_PRINT_SENSE,
1458             "Recovered data using previous sector ID") },
1459         /* D   W O   BK   */
1460         { SST(0x17, 0x06, SS_NOP | SSQ_PRINT_SENSE,
1461             "Recovered data without ECC - data auto-reallocated") },
1462         /* D   WRO   BK   */
1463         { SST(0x17, 0x07, SS_NOP | SSQ_PRINT_SENSE,
1464             "Recovered data without ECC - recommend reassignment") },
1465         /* D   WRO   BK   */
1466         { SST(0x17, 0x08, SS_NOP | SSQ_PRINT_SENSE,
1467             "Recovered data without ECC - recommend rewrite") },
1468         /* D   WRO   BK   */
1469         { SST(0x17, 0x09, SS_NOP | SSQ_PRINT_SENSE,
1470             "Recovered data without ECC - data rewritten") },
1471         /* DT  WRO   BK   */
1472         { SST(0x18, 0x00, SS_NOP | SSQ_PRINT_SENSE,
1473             "Recovered data with error correction applied") },
1474         /* D   WRO   BK   */
1475         { SST(0x18, 0x01, SS_NOP | SSQ_PRINT_SENSE,
1476             "Recovered data with error corr. & retries applied") },
1477         /* D   WRO   BK   */
1478         { SST(0x18, 0x02, SS_NOP | SSQ_PRINT_SENSE,
1479             "Recovered data - data auto-reallocated") },
1480         /*      R         */
1481         { SST(0x18, 0x03, SS_NOP | SSQ_PRINT_SENSE,
1482             "Recovered data with CIRC") },
1483         /*      R         */
1484         { SST(0x18, 0x04, SS_NOP | SSQ_PRINT_SENSE,
1485             "Recovered data with L-EC") },
1486         /* D   WRO   BK   */
1487         { SST(0x18, 0x05, SS_NOP | SSQ_PRINT_SENSE,
1488             "Recovered data - recommend reassignment") },
1489         /* D   WRO   BK   */
1490         { SST(0x18, 0x06, SS_NOP | SSQ_PRINT_SENSE,
1491             "Recovered data - recommend rewrite") },
1492         /* D   W O   BK   */
1493         { SST(0x18, 0x07, SS_NOP | SSQ_PRINT_SENSE,
1494             "Recovered data with ECC - data rewritten") },
1495         /*      R         */
1496         { SST(0x18, 0x08, SS_RDEF,      /* XXX TBD */
1497             "Recovered data with linking") },
1498         /* D     O    K   */
1499         { SST(0x19, 0x00, SS_RDEF,
1500             "Defect list error") },
1501         /* D     O    K   */
1502         { SST(0x19, 0x01, SS_RDEF,
1503             "Defect list not available") },
1504         /* D     O    K   */
1505         { SST(0x19, 0x02, SS_RDEF,
1506             "Defect list error in primary list") },
1507         /* D     O    K   */
1508         { SST(0x19, 0x03, SS_RDEF,
1509             "Defect list error in grown list") },
1510         /* DTLPWROMAEBKVF */
1511         { SST(0x1A, 0x00, SS_RDEF,
1512             "Parameter list length error") },
1513         /* DTLPWROMAEBKVF */
1514         { SST(0x1B, 0x00, SS_RDEF,
1515             "Synchronous data transfer error") },
1516         /* D     O   BK   */
1517         { SST(0x1C, 0x00, SS_RDEF,
1518             "Defect list not found") },
1519         /* D     O   BK   */
1520         { SST(0x1C, 0x01, SS_RDEF,
1521             "Primary defect list not found") },
1522         /* D     O   BK   */
1523         { SST(0x1C, 0x02, SS_RDEF,
1524             "Grown defect list not found") },
1525         /* DT  WRO   BK   */
1526         { SST(0x1D, 0x00, SS_FATAL,
1527             "Miscompare during verify operation") },
1528         /* D         B    */
1529         { SST(0x1D, 0x01, SS_RDEF,      /* XXX TBD */
1530             "Miscomparable verify of unmapped LBA") },
1531         /* D   W O   BK   */
1532         { SST(0x1E, 0x00, SS_NOP | SSQ_PRINT_SENSE,
1533             "Recovered ID with ECC correction") },
1534         /* D     O    K   */
1535         { SST(0x1F, 0x00, SS_RDEF,
1536             "Partial defect list transfer") },
1537         /* DTLPWROMAEBKVF */
1538         { SST(0x20, 0x00, SS_FATAL | EINVAL,
1539             "Invalid command operation code") },
1540         /* DT PWROMAEBK   */
1541         { SST(0x20, 0x01, SS_RDEF,      /* XXX TBD */
1542             "Access denied - initiator pending-enrolled") },
1543         /* DT PWROMAEBK   */
1544         { SST(0x20, 0x02, SS_RDEF,      /* XXX TBD */
1545             "Access denied - no access rights") },
1546         /* DT PWROMAEBK   */
1547         { SST(0x20, 0x03, SS_RDEF,      /* XXX TBD */
1548             "Access denied - invalid mgmt ID key") },
1549         /*  T             */
1550         { SST(0x20, 0x04, SS_RDEF,      /* XXX TBD */
1551             "Illegal command while in write capable state") },
1552         /*  T             */
1553         { SST(0x20, 0x05, SS_RDEF,      /* XXX TBD */
1554             "Obsolete") },
1555         /*  T             */
1556         { SST(0x20, 0x06, SS_RDEF,      /* XXX TBD */
1557             "Illegal command while in explicit address mode") },
1558         /*  T             */
1559         { SST(0x20, 0x07, SS_RDEF,      /* XXX TBD */
1560             "Illegal command while in implicit address mode") },
1561         /* DT PWROMAEBK   */
1562         { SST(0x20, 0x08, SS_RDEF,      /* XXX TBD */
1563             "Access denied - enrollment conflict") },
1564         /* DT PWROMAEBK   */
1565         { SST(0x20, 0x09, SS_RDEF,      /* XXX TBD */
1566             "Access denied - invalid LU identifier") },
1567         /* DT PWROMAEBK   */
1568         { SST(0x20, 0x0A, SS_RDEF,      /* XXX TBD */
1569             "Access denied - invalid proxy token") },
1570         /* DT PWROMAEBK   */
1571         { SST(0x20, 0x0B, SS_RDEF,      /* XXX TBD */
1572             "Access denied - ACL LUN conflict") },
1573         /*  T             */
1574         { SST(0x20, 0x0C, SS_FATAL | EINVAL,
1575             "Illegal command when not in append-only mode") },
1576         /* DT  WRO   BK   */
1577         { SST(0x21, 0x00, SS_FATAL | EINVAL,
1578             "Logical block address out of range") },
1579         /* DT  WROM  BK   */
1580         { SST(0x21, 0x01, SS_FATAL | EINVAL,
1581             "Invalid element address") },
1582         /*      R         */
1583         { SST(0x21, 0x02, SS_RDEF,      /* XXX TBD */
1584             "Invalid address for write") },
1585         /*      R         */
1586         { SST(0x21, 0x03, SS_RDEF,      /* XXX TBD */
1587             "Invalid write crossing layer jump") },
1588         /* D              */
1589         { SST(0x22, 0x00, SS_FATAL | EINVAL,
1590             "Illegal function (use 20 00, 24 00, or 26 00)") },
1591         /* DT P      B    */
1592         { SST(0x23, 0x00, SS_RDEF,      /* XXX TBD */
1593             "Invalid token operation, cause not reportable") },
1594         /* DT P      B    */
1595         { SST(0x23, 0x01, SS_RDEF,      /* XXX TBD */
1596             "Invalid token operation, unsupported token type") },
1597         /* DT P      B    */
1598         { SST(0x23, 0x02, SS_RDEF,      /* XXX TBD */
1599             "Invalid token operation, remote token usage not supported") },
1600         /* DT P      B    */
1601         { SST(0x23, 0x03, SS_RDEF,      /* XXX TBD */
1602             "Invalid token operation, remote ROD token creation not supported") },
1603         /* DT P      B    */
1604         { SST(0x23, 0x04, SS_RDEF,      /* XXX TBD */
1605             "Invalid token operation, token unknown") },
1606         /* DT P      B    */
1607         { SST(0x23, 0x05, SS_RDEF,      /* XXX TBD */
1608             "Invalid token operation, token corrupt") },
1609         /* DT P      B    */
1610         { SST(0x23, 0x06, SS_RDEF,      /* XXX TBD */
1611             "Invalid token operation, token revoked") },
1612         /* DT P      B    */
1613         { SST(0x23, 0x07, SS_RDEF,      /* XXX TBD */
1614             "Invalid token operation, token expired") },
1615         /* DT P      B    */
1616         { SST(0x23, 0x08, SS_RDEF,      /* XXX TBD */
1617             "Invalid token operation, token cancelled") },
1618         /* DT P      B    */
1619         { SST(0x23, 0x09, SS_RDEF,      /* XXX TBD */
1620             "Invalid token operation, token deleted") },
1621         /* DT P      B    */
1622         { SST(0x23, 0x0A, SS_RDEF,      /* XXX TBD */
1623             "Invalid token operation, invalid token length") },
1624         /* DTLPWROMAEBKVF */
1625         { SST(0x24, 0x00, SS_FATAL | EINVAL,
1626             "Invalid field in CDB") },
1627         /* DTLPWRO AEBKVF */
1628         { SST(0x24, 0x01, SS_RDEF,      /* XXX TBD */
1629             "CDB decryption error") },
1630         /*  T             */
1631         { SST(0x24, 0x02, SS_RDEF,      /* XXX TBD */
1632             "Obsolete") },
1633         /*  T             */
1634         { SST(0x24, 0x03, SS_RDEF,      /* XXX TBD */
1635             "Obsolete") },
1636         /*              F */
1637         { SST(0x24, 0x04, SS_RDEF,      /* XXX TBD */
1638             "Security audit value frozen") },
1639         /*              F */
1640         { SST(0x24, 0x05, SS_RDEF,      /* XXX TBD */
1641             "Security working key frozen") },
1642         /*              F */
1643         { SST(0x24, 0x06, SS_RDEF,      /* XXX TBD */
1644             "NONCE not unique") },
1645         /*              F */
1646         { SST(0x24, 0x07, SS_RDEF,      /* XXX TBD */
1647             "NONCE timestamp out of range") },
1648         /* DT   R MAEBKV  */
1649         { SST(0x24, 0x08, SS_RDEF,      /* XXX TBD */
1650             "Invalid XCDB") },
1651         /* DTLPWROMAEBKVF */
1652         { SST(0x25, 0x00, SS_FATAL | ENXIO | SSQ_LOST,
1653             "Logical unit not supported") },
1654         /* DTLPWROMAEBKVF */
1655         { SST(0x26, 0x00, SS_FATAL | EINVAL,
1656             "Invalid field in parameter list") },
1657         /* DTLPWROMAEBKVF */
1658         { SST(0x26, 0x01, SS_FATAL | EINVAL,
1659             "Parameter not supported") },
1660         /* DTLPWROMAEBKVF */
1661         { SST(0x26, 0x02, SS_FATAL | EINVAL,
1662             "Parameter value invalid") },
1663         /* DTLPWROMAE K   */
1664         { SST(0x26, 0x03, SS_FATAL | EINVAL,
1665             "Threshold parameters not supported") },
1666         /* DTLPWROMAEBKVF */
1667         { SST(0x26, 0x04, SS_FATAL | EINVAL,
1668             "Invalid release of persistent reservation") },
1669         /* DTLPWRO A BK   */
1670         { SST(0x26, 0x05, SS_RDEF,      /* XXX TBD */
1671             "Data decryption error") },
1672         /* DTLPWRO    K   */
1673         { SST(0x26, 0x06, SS_RDEF,      /* XXX TBD */
1674             "Too many target descriptors") },
1675         /* DTLPWRO    K   */
1676         { SST(0x26, 0x07, SS_RDEF,      /* XXX TBD */
1677             "Unsupported target descriptor type code") },
1678         /* DTLPWRO    K   */
1679         { SST(0x26, 0x08, SS_RDEF,      /* XXX TBD */
1680             "Too many segment descriptors") },
1681         /* DTLPWRO    K   */
1682         { SST(0x26, 0x09, SS_RDEF,      /* XXX TBD */
1683             "Unsupported segment descriptor type code") },
1684         /* DTLPWRO    K   */
1685         { SST(0x26, 0x0A, SS_RDEF,      /* XXX TBD */
1686             "Unexpected inexact segment") },
1687         /* DTLPWRO    K   */
1688         { SST(0x26, 0x0B, SS_RDEF,      /* XXX TBD */
1689             "Inline data length exceeded") },
1690         /* DTLPWRO    K   */
1691         { SST(0x26, 0x0C, SS_RDEF,      /* XXX TBD */
1692             "Invalid operation for copy source or destination") },
1693         /* DTLPWRO    K   */
1694         { SST(0x26, 0x0D, SS_RDEF,      /* XXX TBD */
1695             "Copy segment granularity violation") },
1696         /* DT PWROMAEBK   */
1697         { SST(0x26, 0x0E, SS_RDEF,      /* XXX TBD */
1698             "Invalid parameter while port is enabled") },
1699         /*              F */
1700         { SST(0x26, 0x0F, SS_RDEF,      /* XXX TBD */
1701             "Invalid data-out buffer integrity check value") },
1702         /*  T             */
1703         { SST(0x26, 0x10, SS_RDEF,      /* XXX TBD */
1704             "Data decryption key fail limit reached") },
1705         /*  T             */
1706         { SST(0x26, 0x11, SS_RDEF,      /* XXX TBD */
1707             "Incomplete key-associated data set") },
1708         /*  T             */
1709         { SST(0x26, 0x12, SS_RDEF,      /* XXX TBD */
1710             "Vendor specific key reference not found") },
1711         /* DT  WRO   BK   */
1712         { SST(0x27, 0x00, SS_FATAL | EACCES,
1713             "Write protected") },
1714         /* DT  WRO   BK   */
1715         { SST(0x27, 0x01, SS_FATAL | EACCES,
1716             "Hardware write protected") },
1717         /* DT  WRO   BK   */
1718         { SST(0x27, 0x02, SS_FATAL | EACCES,
1719             "Logical unit software write protected") },
1720         /*  T   R         */
1721         { SST(0x27, 0x03, SS_FATAL | EACCES,
1722             "Associated write protect") },
1723         /*  T   R         */
1724         { SST(0x27, 0x04, SS_FATAL | EACCES,
1725             "Persistent write protect") },
1726         /*  T   R         */
1727         { SST(0x27, 0x05, SS_FATAL | EACCES,
1728             "Permanent write protect") },
1729         /*      R       F */
1730         { SST(0x27, 0x06, SS_RDEF,      /* XXX TBD */
1731             "Conditional write protect") },
1732         /* D         B    */
1733         { SST(0x27, 0x07, SS_RDEF,      /* XXX TBD */
1734             "Space allocation failed write protect") },
1735         /* DTLPWROMAEBKVF */
1736         { SST(0x28, 0x00, SS_FATAL | ENXIO,
1737             "Not ready to ready change, medium may have changed") },
1738         /* DT  WROM  B    */
1739         { SST(0x28, 0x01, SS_FATAL | ENXIO,
1740             "Import or export element accessed") },
1741         /*      R         */
1742         { SST(0x28, 0x02, SS_RDEF,      /* XXX TBD */
1743             "Format-layer may have changed") },
1744         /*        M       */
1745         { SST(0x28, 0x03, SS_RDEF,      /* XXX TBD */
1746             "Import/export element accessed, medium changed") },
1747         /*
1748          * XXX JGibbs - All of these should use the same errno, but I don't
1749          * think ENXIO is the correct choice.  Should we borrow from
1750          * the networking errnos?  ECONNRESET anyone?
1751          */
1752         /* DTLPWROMAEBKVF */
1753         { SST(0x29, 0x00, SS_FATAL | ENXIO,
1754             "Power on, reset, or bus device reset occurred") },
1755         /* DTLPWROMAEBKVF */
1756         { SST(0x29, 0x01, SS_RDEF,
1757             "Power on occurred") },
1758         /* DTLPWROMAEBKVF */
1759         { SST(0x29, 0x02, SS_RDEF,
1760             "SCSI bus reset occurred") },
1761         /* DTLPWROMAEBKVF */
1762         { SST(0x29, 0x03, SS_RDEF,
1763             "Bus device reset function occurred") },
1764         /* DTLPWROMAEBKVF */
1765         { SST(0x29, 0x04, SS_RDEF,
1766             "Device internal reset") },
1767         /* DTLPWROMAEBKVF */
1768         { SST(0x29, 0x05, SS_RDEF,
1769             "Transceiver mode changed to single-ended") },
1770         /* DTLPWROMAEBKVF */
1771         { SST(0x29, 0x06, SS_RDEF,
1772             "Transceiver mode changed to LVD") },
1773         /* DTLPWROMAEBKVF */
1774         { SST(0x29, 0x07, SS_RDEF,      /* XXX TBD */
1775             "I_T nexus loss occurred") },
1776         /* DTL WROMAEBKVF */
1777         { SST(0x2A, 0x00, SS_RDEF,
1778             "Parameters changed") },
1779         /* DTL WROMAEBKVF */
1780         { SST(0x2A, 0x01, SS_RDEF,
1781             "Mode parameters changed") },
1782         /* DTL WROMAE K   */
1783         { SST(0x2A, 0x02, SS_RDEF,
1784             "Log parameters changed") },
1785         /* DTLPWROMAE K   */
1786         { SST(0x2A, 0x03, SS_RDEF,
1787             "Reservations preempted") },
1788         /* DTLPWROMAE     */
1789         { SST(0x2A, 0x04, SS_RDEF,      /* XXX TBD */
1790             "Reservations released") },
1791         /* DTLPWROMAE     */
1792         { SST(0x2A, 0x05, SS_RDEF,      /* XXX TBD */
1793             "Registrations preempted") },
1794         /* DTLPWROMAEBKVF */
1795         { SST(0x2A, 0x06, SS_RDEF,      /* XXX TBD */
1796             "Asymmetric access state changed") },
1797         /* DTLPWROMAEBKVF */
1798         { SST(0x2A, 0x07, SS_RDEF,      /* XXX TBD */
1799             "Implicit asymmetric access state transition failed") },
1800         /* DT  WROMAEBKVF */
1801         { SST(0x2A, 0x08, SS_RDEF,      /* XXX TBD */
1802             "Priority changed") },
1803         /* D              */
1804         { SST(0x2A, 0x09, SS_RDEF,      /* XXX TBD */
1805             "Capacity data has changed") },
1806         /* DT             */
1807         { SST(0x2A, 0x0A, SS_RDEF,      /* XXX TBD */
1808             "Error history I_T nexus cleared") },
1809         /* DT             */
1810         { SST(0x2A, 0x0B, SS_RDEF,      /* XXX TBD */
1811             "Error history snapshot released") },
1812         /*              F */
1813         { SST(0x2A, 0x0C, SS_RDEF,      /* XXX TBD */
1814             "Error recovery attributes have changed") },
1815         /*  T             */
1816         { SST(0x2A, 0x0D, SS_RDEF,      /* XXX TBD */
1817             "Data encryption capabilities changed") },
1818         /* DT     M E  V  */
1819         { SST(0x2A, 0x10, SS_RDEF,      /* XXX TBD */
1820             "Timestamp changed") },
1821         /*  T             */
1822         { SST(0x2A, 0x11, SS_RDEF,      /* XXX TBD */
1823             "Data encryption parameters changed by another I_T nexus") },
1824         /*  T             */
1825         { SST(0x2A, 0x12, SS_RDEF,      /* XXX TBD */
1826             "Data encryption parameters changed by vendor specific event") },
1827         /*  T             */
1828         { SST(0x2A, 0x13, SS_RDEF,      /* XXX TBD */
1829             "Data encryption key instance counter has changed") },
1830         /* DT   R MAEBKV  */
1831         { SST(0x2A, 0x14, SS_RDEF,      /* XXX TBD */
1832             "SA creation capabilities data has changed") },
1833         /*  T     M    V  */
1834         { SST(0x2A, 0x15, SS_RDEF,      /* XXX TBD */
1835             "Medium removal prevention preempted") },
1836         /* DTLPWRO    K   */
1837         { SST(0x2B, 0x00, SS_RDEF,
1838             "Copy cannot execute since host cannot disconnect") },
1839         /* DTLPWROMAEBKVF */
1840         { SST(0x2C, 0x00, SS_RDEF,
1841             "Command sequence error") },
1842         /*                */
1843         { SST(0x2C, 0x01, SS_RDEF,
1844             "Too many windows specified") },
1845         /*                */
1846         { SST(0x2C, 0x02, SS_RDEF,
1847             "Invalid combination of windows specified") },
1848         /*      R         */
1849         { SST(0x2C, 0x03, SS_RDEF,
1850             "Current program area is not empty") },
1851         /*      R         */
1852         { SST(0x2C, 0x04, SS_RDEF,
1853             "Current program area is empty") },
1854         /*           B    */
1855         { SST(0x2C, 0x05, SS_RDEF,      /* XXX TBD */
1856             "Illegal power condition request") },
1857         /*      R         */
1858         { SST(0x2C, 0x06, SS_RDEF,      /* XXX TBD */
1859             "Persistent prevent conflict") },
1860         /* DTLPWROMAEBKVF */
1861         { SST(0x2C, 0x07, SS_RDEF,      /* XXX TBD */
1862             "Previous busy status") },
1863         /* DTLPWROMAEBKVF */
1864         { SST(0x2C, 0x08, SS_RDEF,      /* XXX TBD */
1865             "Previous task set full status") },
1866         /* DTLPWROM EBKVF */
1867         { SST(0x2C, 0x09, SS_RDEF,      /* XXX TBD */
1868             "Previous reservation conflict status") },
1869         /*              F */
1870         { SST(0x2C, 0x0A, SS_RDEF,      /* XXX TBD */
1871             "Partition or collection contains user objects") },
1872         /*  T             */
1873         { SST(0x2C, 0x0B, SS_RDEF,      /* XXX TBD */
1874             "Not reserved") },
1875         /* D              */
1876         { SST(0x2C, 0x0C, SS_RDEF,      /* XXX TBD */
1877             "ORWRITE generation does not match") },
1878         /*  T             */
1879         { SST(0x2D, 0x00, SS_RDEF,
1880             "Overwrite error on update in place") },
1881         /*      R         */
1882         { SST(0x2E, 0x00, SS_RDEF,      /* XXX TBD */
1883             "Insufficient time for operation") },
1884         /* DTLPWROMAEBKVF */
1885         { SST(0x2F, 0x00, SS_RDEF,
1886             "Commands cleared by another initiator") },
1887         /* D              */
1888         { SST(0x2F, 0x01, SS_RDEF,      /* XXX TBD */
1889             "Commands cleared by power loss notification") },
1890         /* DTLPWROMAEBKVF */
1891         { SST(0x2F, 0x02, SS_RDEF,      /* XXX TBD */
1892             "Commands cleared by device server") },
1893         /* DT  WROM  BK   */
1894         { SST(0x30, 0x00, SS_RDEF,
1895             "Incompatible medium installed") },
1896         /* DT  WRO   BK   */
1897         { SST(0x30, 0x01, SS_RDEF,
1898             "Cannot read medium - unknown format") },
1899         /* DT  WRO   BK   */
1900         { SST(0x30, 0x02, SS_RDEF,
1901             "Cannot read medium - incompatible format") },
1902         /* DT   R     K   */
1903         { SST(0x30, 0x03, SS_RDEF,
1904             "Cleaning cartridge installed") },
1905         /* DT  WRO   BK   */
1906         { SST(0x30, 0x04, SS_RDEF,
1907             "Cannot write medium - unknown format") },
1908         /* DT  WRO   BK   */
1909         { SST(0x30, 0x05, SS_RDEF,
1910             "Cannot write medium - incompatible format") },
1911         /* DT  WRO   B    */
1912         { SST(0x30, 0x06, SS_RDEF,
1913             "Cannot format medium - incompatible medium") },
1914         /* DTL WROMAEBKVF */
1915         { SST(0x30, 0x07, SS_RDEF,
1916             "Cleaning failure") },
1917         /*      R         */
1918         { SST(0x30, 0x08, SS_RDEF,
1919             "Cannot write - application code mismatch") },
1920         /*      R         */
1921         { SST(0x30, 0x09, SS_RDEF,
1922             "Current session not fixated for append") },
1923         /* DT  WRO AEBK   */
1924         { SST(0x30, 0x0A, SS_RDEF,      /* XXX TBD */
1925             "Cleaning request rejected") },
1926         /*  T             */
1927         { SST(0x30, 0x0C, SS_RDEF,      /* XXX TBD */
1928             "WORM medium - overwrite attempted") },
1929         /*  T             */
1930         { SST(0x30, 0x0D, SS_RDEF,      /* XXX TBD */
1931             "WORM medium - integrity check") },
1932         /*      R         */
1933         { SST(0x30, 0x10, SS_RDEF,      /* XXX TBD */
1934             "Medium not formatted") },
1935         /*        M       */
1936         { SST(0x30, 0x11, SS_RDEF,      /* XXX TBD */
1937             "Incompatible volume type") },
1938         /*        M       */
1939         { SST(0x30, 0x12, SS_RDEF,      /* XXX TBD */
1940             "Incompatible volume qualifier") },
1941         /*        M       */
1942         { SST(0x30, 0x13, SS_RDEF,      /* XXX TBD */
1943             "Cleaning volume expired") },
1944         /* DT  WRO   BK   */
1945         { SST(0x31, 0x00, SS_RDEF,
1946             "Medium format corrupted") },
1947         /* D L  RO   B    */
1948         { SST(0x31, 0x01, SS_RDEF,
1949             "Format command failed") },
1950         /*      R         */
1951         { SST(0x31, 0x02, SS_RDEF,      /* XXX TBD */
1952             "Zoned formatting failed due to spare linking") },
1953         /* D         B    */
1954         { SST(0x31, 0x03, SS_RDEF,      /* XXX TBD */
1955             "SANITIZE command failed") },
1956         /* D   W O   BK   */
1957         { SST(0x32, 0x00, SS_RDEF,
1958             "No defect spare location available") },
1959         /* D   W O   BK   */
1960         { SST(0x32, 0x01, SS_RDEF,
1961             "Defect list update failure") },
1962         /*  T             */
1963         { SST(0x33, 0x00, SS_RDEF,
1964             "Tape length error") },
1965         /* DTLPWROMAEBKVF */
1966         { SST(0x34, 0x00, SS_RDEF,
1967             "Enclosure failure") },
1968         /* DTLPWROMAEBKVF */
1969         { SST(0x35, 0x00, SS_RDEF,
1970             "Enclosure services failure") },
1971         /* DTLPWROMAEBKVF */
1972         { SST(0x35, 0x01, SS_RDEF,
1973             "Unsupported enclosure function") },
1974         /* DTLPWROMAEBKVF */
1975         { SST(0x35, 0x02, SS_RDEF,
1976             "Enclosure services unavailable") },
1977         /* DTLPWROMAEBKVF */
1978         { SST(0x35, 0x03, SS_RDEF,
1979             "Enclosure services transfer failure") },
1980         /* DTLPWROMAEBKVF */
1981         { SST(0x35, 0x04, SS_RDEF,
1982             "Enclosure services transfer refused") },
1983         /* DTL WROMAEBKVF */
1984         { SST(0x35, 0x05, SS_RDEF,      /* XXX TBD */
1985             "Enclosure services checksum error") },
1986         /*   L            */
1987         { SST(0x36, 0x00, SS_RDEF,
1988             "Ribbon, ink, or toner failure") },
1989         /* DTL WROMAEBKVF */
1990         { SST(0x37, 0x00, SS_RDEF,
1991             "Rounded parameter") },
1992         /*           B    */
1993         { SST(0x38, 0x00, SS_RDEF,      /* XXX TBD */
1994             "Event status notification") },
1995         /*           B    */
1996         { SST(0x38, 0x02, SS_RDEF,      /* XXX TBD */
1997             "ESN - power management class event") },
1998         /*           B    */
1999         { SST(0x38, 0x04, SS_RDEF,      /* XXX TBD */
2000             "ESN - media class event") },
2001         /*           B    */
2002         { SST(0x38, 0x06, SS_RDEF,      /* XXX TBD */
2003             "ESN - device busy class event") },
2004         /* D              */
2005         { SST(0x38, 0x07, SS_RDEF,      /* XXX TBD */
2006             "Thin provisioning soft threshold reached") },
2007         /* DTL WROMAE K   */
2008         { SST(0x39, 0x00, SS_RDEF,
2009             "Saving parameters not supported") },
2010         /* DTL WROM  BK   */
2011         { SST(0x3A, 0x00, SS_FATAL | ENXIO,
2012             "Medium not present") },
2013         /* DT  WROM  BK   */
2014         { SST(0x3A, 0x01, SS_FATAL | ENXIO,
2015             "Medium not present - tray closed") },
2016         /* DT  WROM  BK   */
2017         { SST(0x3A, 0x02, SS_FATAL | ENXIO,
2018             "Medium not present - tray open") },
2019         /* DT  WROM  B    */
2020         { SST(0x3A, 0x03, SS_RDEF,      /* XXX TBD */
2021             "Medium not present - loadable") },
2022         /* DT  WRO   B    */
2023         { SST(0x3A, 0x04, SS_RDEF,      /* XXX TBD */
2024             "Medium not present - medium auxiliary memory accessible") },
2025         /*  TL            */
2026         { SST(0x3B, 0x00, SS_RDEF,
2027             "Sequential positioning error") },
2028         /*  T             */
2029         { SST(0x3B, 0x01, SS_RDEF,
2030             "Tape position error at beginning-of-medium") },
2031         /*  T             */
2032         { SST(0x3B, 0x02, SS_RDEF,
2033             "Tape position error at end-of-medium") },
2034         /*   L            */
2035         { SST(0x3B, 0x03, SS_RDEF,
2036             "Tape or electronic vertical forms unit not ready") },
2037         /*   L            */
2038         { SST(0x3B, 0x04, SS_RDEF,
2039             "Slew failure") },
2040         /*   L            */
2041         { SST(0x3B, 0x05, SS_RDEF,
2042             "Paper jam") },
2043         /*   L            */
2044         { SST(0x3B, 0x06, SS_RDEF,
2045             "Failed to sense top-of-form") },
2046         /*   L            */
2047         { SST(0x3B, 0x07, SS_RDEF,
2048             "Failed to sense bottom-of-form") },
2049         /*  T             */
2050         { SST(0x3B, 0x08, SS_RDEF,
2051             "Reposition error") },
2052         /*                */
2053         { SST(0x3B, 0x09, SS_RDEF,
2054             "Read past end of medium") },
2055         /*                */
2056         { SST(0x3B, 0x0A, SS_RDEF,
2057             "Read past beginning of medium") },
2058         /*                */
2059         { SST(0x3B, 0x0B, SS_RDEF,
2060             "Position past end of medium") },
2061         /*  T             */
2062         { SST(0x3B, 0x0C, SS_RDEF,
2063             "Position past beginning of medium") },
2064         /* DT  WROM  BK   */
2065         { SST(0x3B, 0x0D, SS_FATAL | ENOSPC,
2066             "Medium destination element full") },
2067         /* DT  WROM  BK   */
2068         { SST(0x3B, 0x0E, SS_RDEF,
2069             "Medium source element empty") },
2070         /*      R         */
2071         { SST(0x3B, 0x0F, SS_RDEF,
2072             "End of medium reached") },
2073         /* DT  WROM  BK   */
2074         { SST(0x3B, 0x11, SS_RDEF,
2075             "Medium magazine not accessible") },
2076         /* DT  WROM  BK   */
2077         { SST(0x3B, 0x12, SS_RDEF,
2078             "Medium magazine removed") },
2079         /* DT  WROM  BK   */
2080         { SST(0x3B, 0x13, SS_RDEF,
2081             "Medium magazine inserted") },
2082         /* DT  WROM  BK   */
2083         { SST(0x3B, 0x14, SS_RDEF,
2084             "Medium magazine locked") },
2085         /* DT  WROM  BK   */
2086         { SST(0x3B, 0x15, SS_RDEF,
2087             "Medium magazine unlocked") },
2088         /*      R         */
2089         { SST(0x3B, 0x16, SS_RDEF,      /* XXX TBD */
2090             "Mechanical positioning or changer error") },
2091         /*              F */
2092         { SST(0x3B, 0x17, SS_RDEF,      /* XXX TBD */
2093             "Read past end of user object") },
2094         /*        M       */
2095         { SST(0x3B, 0x18, SS_RDEF,      /* XXX TBD */
2096             "Element disabled") },
2097         /*        M       */
2098         { SST(0x3B, 0x19, SS_RDEF,      /* XXX TBD */
2099             "Element enabled") },
2100         /*        M       */
2101         { SST(0x3B, 0x1A, SS_RDEF,      /* XXX TBD */
2102             "Data transfer device removed") },
2103         /*        M       */
2104         { SST(0x3B, 0x1B, SS_RDEF,      /* XXX TBD */
2105             "Data transfer device inserted") },
2106         /*  T             */
2107         { SST(0x3B, 0x1C, SS_RDEF,      /* XXX TBD */
2108             "Too many logical objects on partition to support operation") },
2109         /* DTLPWROMAE K   */
2110         { SST(0x3D, 0x00, SS_RDEF,
2111             "Invalid bits in IDENTIFY message") },
2112         /* DTLPWROMAEBKVF */
2113         { SST(0x3E, 0x00, SS_RDEF,
2114             "Logical unit has not self-configured yet") },
2115         /* DTLPWROMAEBKVF */
2116         { SST(0x3E, 0x01, SS_RDEF,
2117             "Logical unit failure") },
2118         /* DTLPWROMAEBKVF */
2119         { SST(0x3E, 0x02, SS_RDEF,
2120             "Timeout on logical unit") },
2121         /* DTLPWROMAEBKVF */
2122         { SST(0x3E, 0x03, SS_RDEF,      /* XXX TBD */
2123             "Logical unit failed self-test") },
2124         /* DTLPWROMAEBKVF */
2125         { SST(0x3E, 0x04, SS_RDEF,      /* XXX TBD */
2126             "Logical unit unable to update self-test log") },
2127         /* DTLPWROMAEBKVF */
2128         { SST(0x3F, 0x00, SS_RDEF,
2129             "Target operating conditions have changed") },
2130         /* DTLPWROMAEBKVF */
2131         { SST(0x3F, 0x01, SS_RDEF,
2132             "Microcode has been changed") },
2133         /* DTLPWROM  BK   */
2134         { SST(0x3F, 0x02, SS_RDEF,
2135             "Changed operating definition") },
2136         /* DTLPWROMAEBKVF */
2137         { SST(0x3F, 0x03, SS_RDEF,
2138             "INQUIRY data has changed") },
2139         /* DT  WROMAEBK   */
2140         { SST(0x3F, 0x04, SS_RDEF,
2141             "Component device attached") },
2142         /* DT  WROMAEBK   */
2143         { SST(0x3F, 0x05, SS_RDEF,
2144             "Device identifier changed") },
2145         /* DT  WROMAEB    */
2146         { SST(0x3F, 0x06, SS_RDEF,
2147             "Redundancy group created or modified") },
2148         /* DT  WROMAEB    */
2149         { SST(0x3F, 0x07, SS_RDEF,
2150             "Redundancy group deleted") },
2151         /* DT  WROMAEB    */
2152         { SST(0x3F, 0x08, SS_RDEF,
2153             "Spare created or modified") },
2154         /* DT  WROMAEB    */
2155         { SST(0x3F, 0x09, SS_RDEF,
2156             "Spare deleted") },
2157         /* DT  WROMAEBK   */
2158         { SST(0x3F, 0x0A, SS_RDEF,
2159             "Volume set created or modified") },
2160         /* DT  WROMAEBK   */
2161         { SST(0x3F, 0x0B, SS_RDEF,
2162             "Volume set deleted") },
2163         /* DT  WROMAEBK   */
2164         { SST(0x3F, 0x0C, SS_RDEF,
2165             "Volume set deassigned") },
2166         /* DT  WROMAEBK   */
2167         { SST(0x3F, 0x0D, SS_RDEF,
2168             "Volume set reassigned") },
2169         /* DTLPWROMAE     */
2170         { SST(0x3F, 0x0E, SS_RDEF | SSQ_RESCAN ,
2171             "Reported LUNs data has changed") },
2172         /* DTLPWROMAEBKVF */
2173         { SST(0x3F, 0x0F, SS_RDEF,      /* XXX TBD */
2174             "Echo buffer overwritten") },
2175         /* DT  WROM  B    */
2176         { SST(0x3F, 0x10, SS_RDEF,      /* XXX TBD */
2177             "Medium loadable") },
2178         /* DT  WROM  B    */
2179         { SST(0x3F, 0x11, SS_RDEF,      /* XXX TBD */
2180             "Medium auxiliary memory accessible") },
2181         /* DTLPWR MAEBK F */
2182         { SST(0x3F, 0x12, SS_RDEF,      /* XXX TBD */
2183             "iSCSI IP address added") },
2184         /* DTLPWR MAEBK F */
2185         { SST(0x3F, 0x13, SS_RDEF,      /* XXX TBD */
2186             "iSCSI IP address removed") },
2187         /* DTLPWR MAEBK F */
2188         { SST(0x3F, 0x14, SS_RDEF,      /* XXX TBD */
2189             "iSCSI IP address changed") },
2190         /* D              */
2191         { SST(0x40, 0x00, SS_RDEF,
2192             "RAM failure") },           /* deprecated - use 40 NN instead */
2193         /* DTLPWROMAEBKVF */
2194         { SST(0x40, 0x80, SS_RDEF,
2195             "Diagnostic failure: ASCQ = Component ID") },
2196         /* DTLPWROMAEBKVF */
2197         { SST(0x40, 0xFF, SS_RDEF | SSQ_RANGE,
2198             NULL) },                    /* Range 0x80->0xFF */
2199         /* D              */
2200         { SST(0x41, 0x00, SS_RDEF,
2201             "Data path failure") },     /* deprecated - use 40 NN instead */
2202         /* D              */
2203         { SST(0x42, 0x00, SS_RDEF,
2204             "Power-on or self-test failure") },
2205                                         /* deprecated - use 40 NN instead */
2206         /* DTLPWROMAEBKVF */
2207         { SST(0x43, 0x00, SS_RDEF,
2208             "Message error") },
2209         /* DTLPWROMAEBKVF */
2210         { SST(0x44, 0x00, SS_RDEF,
2211             "Internal target failure") },
2212         /* DT P   MAEBKVF */
2213         { SST(0x44, 0x01, SS_RDEF,      /* XXX TBD */
2214             "Persistent reservation information lost") },
2215         /* DT        B    */
2216         { SST(0x44, 0x71, SS_RDEF,      /* XXX TBD */
2217             "ATA device failed set features") },
2218         /* DTLPWROMAEBKVF */
2219         { SST(0x45, 0x00, SS_RDEF,
2220             "Select or reselect failure") },
2221         /* DTLPWROM  BK   */
2222         { SST(0x46, 0x00, SS_RDEF,
2223             "Unsuccessful soft reset") },
2224         /* DTLPWROMAEBKVF */
2225         { SST(0x47, 0x00, SS_RDEF,
2226             "SCSI parity error") },
2227         /* DTLPWROMAEBKVF */
2228         { SST(0x47, 0x01, SS_RDEF,      /* XXX TBD */
2229             "Data phase CRC error detected") },
2230         /* DTLPWROMAEBKVF */
2231         { SST(0x47, 0x02, SS_RDEF,      /* XXX TBD */
2232             "SCSI parity error detected during ST data phase") },
2233         /* DTLPWROMAEBKVF */
2234         { SST(0x47, 0x03, SS_RDEF,      /* XXX TBD */
2235             "Information unit iuCRC error detected") },
2236         /* DTLPWROMAEBKVF */
2237         { SST(0x47, 0x04, SS_RDEF,      /* XXX TBD */
2238             "Asynchronous information protection error detected") },
2239         /* DTLPWROMAEBKVF */
2240         { SST(0x47, 0x05, SS_RDEF,      /* XXX TBD */
2241             "Protocol service CRC error") },
2242         /* DT     MAEBKVF */
2243         { SST(0x47, 0x06, SS_RDEF,      /* XXX TBD */
2244             "PHY test function in progress") },
2245         /* DT PWROMAEBK   */
2246         { SST(0x47, 0x7F, SS_RDEF,      /* XXX TBD */
2247             "Some commands cleared by iSCSI protocol event") },
2248         /* DTLPWROMAEBKVF */
2249         { SST(0x48, 0x00, SS_RDEF,
2250             "Initiator detected error message received") },
2251         /* DTLPWROMAEBKVF */
2252         { SST(0x49, 0x00, SS_RDEF,
2253             "Invalid message error") },
2254         /* DTLPWROMAEBKVF */
2255         { SST(0x4A, 0x00, SS_RDEF,
2256             "Command phase error") },
2257         /* DTLPWROMAEBKVF */
2258         { SST(0x4B, 0x00, SS_RDEF,
2259             "Data phase error") },
2260         /* DT PWROMAEBK   */
2261         { SST(0x4B, 0x01, SS_RDEF,      /* XXX TBD */
2262             "Invalid target port transfer tag received") },
2263         /* DT PWROMAEBK   */
2264         { SST(0x4B, 0x02, SS_RDEF,      /* XXX TBD */
2265             "Too much write data") },
2266         /* DT PWROMAEBK   */
2267         { SST(0x4B, 0x03, SS_RDEF,      /* XXX TBD */
2268             "ACK/NAK timeout") },
2269         /* DT PWROMAEBK   */
2270         { SST(0x4B, 0x04, SS_RDEF,      /* XXX TBD */
2271             "NAK received") },
2272         /* DT PWROMAEBK   */
2273         { SST(0x4B, 0x05, SS_RDEF,      /* XXX TBD */
2274             "Data offset error") },
2275         /* DT PWROMAEBK   */
2276         { SST(0x4B, 0x06, SS_RDEF,      /* XXX TBD */
2277             "Initiator response timeout") },
2278         /* DT PWROMAEBK F */
2279         { SST(0x4B, 0x07, SS_RDEF,      /* XXX TBD */
2280             "Connection lost") },
2281         /* DT PWROMAEBK F */
2282         { SST(0x4B, 0x08, SS_RDEF,      /* XXX TBD */
2283             "Data-in buffer overflow - data buffer size") },
2284         /* DT PWROMAEBK F */
2285         { SST(0x4B, 0x09, SS_RDEF,      /* XXX TBD */
2286             "Data-in buffer overflow - data buffer descriptor area") },
2287         /* DT PWROMAEBK F */
2288         { SST(0x4B, 0x0A, SS_RDEF,      /* XXX TBD */
2289             "Data-in buffer error") },
2290         /* DT PWROMAEBK F */
2291         { SST(0x4B, 0x0B, SS_RDEF,      /* XXX TBD */
2292             "Data-out buffer overflow - data buffer size") },
2293         /* DT PWROMAEBK F */
2294         { SST(0x4B, 0x0C, SS_RDEF,      /* XXX TBD */
2295             "Data-out buffer overflow - data buffer descriptor area") },
2296         /* DT PWROMAEBK F */
2297         { SST(0x4B, 0x0D, SS_RDEF,      /* XXX TBD */
2298             "Data-out buffer error") },
2299         /* DTLPWROMAEBKVF */
2300         { SST(0x4C, 0x00, SS_RDEF,
2301             "Logical unit failed self-configuration") },
2302         /* DTLPWROMAEBKVF */
2303         { SST(0x4D, 0x00, SS_RDEF,
2304             "Tagged overlapped commands: ASCQ = Queue tag ID") },
2305         /* DTLPWROMAEBKVF */
2306         { SST(0x4D, 0xFF, SS_RDEF | SSQ_RANGE,
2307             NULL) },                    /* Range 0x00->0xFF */
2308         /* DTLPWROMAEBKVF */
2309         { SST(0x4E, 0x00, SS_RDEF,
2310             "Overlapped commands attempted") },
2311         /*  T             */
2312         { SST(0x50, 0x00, SS_RDEF,
2313             "Write append error") },
2314         /*  T             */
2315         { SST(0x50, 0x01, SS_RDEF,
2316             "Write append position error") },
2317         /*  T             */
2318         { SST(0x50, 0x02, SS_RDEF,
2319             "Position error related to timing") },
2320         /*  T   RO        */
2321         { SST(0x51, 0x00, SS_RDEF,
2322             "Erase failure") },
2323         /*      R         */
2324         { SST(0x51, 0x01, SS_RDEF,      /* XXX TBD */
2325             "Erase failure - incomplete erase operation detected") },
2326         /*  T             */
2327         { SST(0x52, 0x00, SS_RDEF,
2328             "Cartridge fault") },
2329         /* DTL WROM  BK   */
2330         { SST(0x53, 0x00, SS_RDEF,
2331             "Media load or eject failed") },
2332         /*  T             */
2333         { SST(0x53, 0x01, SS_RDEF,
2334             "Unload tape failure") },
2335         /* DT  WROM  BK   */
2336         { SST(0x53, 0x02, SS_RDEF,
2337             "Medium removal prevented") },
2338         /*        M       */
2339         { SST(0x53, 0x03, SS_RDEF,      /* XXX TBD */
2340             "Medium removal prevented by data transfer element") },
2341         /*  T             */
2342         { SST(0x53, 0x04, SS_RDEF,      /* XXX TBD */
2343             "Medium thread or unthread failure") },
2344         /*        M       */
2345         { SST(0x53, 0x05, SS_RDEF,      /* XXX TBD */
2346             "Volume identifier invalid") },
2347         /*  T             */
2348         { SST(0x53, 0x06, SS_RDEF,      /* XXX TBD */
2349             "Volume identifier missing") },
2350         /*        M       */
2351         { SST(0x53, 0x07, SS_RDEF,      /* XXX TBD */
2352             "Duplicate volume identifier") },
2353         /*        M       */
2354         { SST(0x53, 0x08, SS_RDEF,      /* XXX TBD */
2355             "Element status unknown") },
2356         /*    P           */
2357         { SST(0x54, 0x00, SS_RDEF,
2358             "SCSI to host system interface failure") },
2359         /*    P           */
2360         { SST(0x55, 0x00, SS_RDEF,
2361             "System resource failure") },
2362         /* D     O   BK   */
2363         { SST(0x55, 0x01, SS_FATAL | ENOSPC,
2364             "System buffer full") },
2365         /* DTLPWROMAE K   */
2366         { SST(0x55, 0x02, SS_RDEF,      /* XXX TBD */
2367             "Insufficient reservation resources") },
2368         /* DTLPWROMAE K   */
2369         { SST(0x55, 0x03, SS_RDEF,      /* XXX TBD */
2370             "Insufficient resources") },
2371         /* DTLPWROMAE K   */
2372         { SST(0x55, 0x04, SS_RDEF,      /* XXX TBD */
2373             "Insufficient registration resources") },
2374         /* DT PWROMAEBK   */
2375         { SST(0x55, 0x05, SS_RDEF,      /* XXX TBD */
2376             "Insufficient access control resources") },
2377         /* DT  WROM  B    */
2378         { SST(0x55, 0x06, SS_RDEF,      /* XXX TBD */
2379             "Auxiliary memory out of space") },
2380         /*              F */
2381         { SST(0x55, 0x07, SS_RDEF,      /* XXX TBD */
2382             "Quota error") },
2383         /*  T             */
2384         { SST(0x55, 0x08, SS_RDEF,      /* XXX TBD */
2385             "Maximum number of supplemental decryption keys exceeded") },
2386         /*        M       */
2387         { SST(0x55, 0x09, SS_RDEF,      /* XXX TBD */
2388             "Medium auxiliary memory not accessible") },
2389         /*        M       */
2390         { SST(0x55, 0x0A, SS_RDEF,      /* XXX TBD */
2391             "Data currently unavailable") },
2392         /* DTLPWROMAEBKVF */
2393         { SST(0x55, 0x0B, SS_RDEF,      /* XXX TBD */
2394             "Insufficient power for operation") },
2395         /* DT P      B    */
2396         { SST(0x55, 0x0C, SS_RDEF,      /* XXX TBD */
2397             "Insufficient resources to create ROD") },
2398         /* DT P      B    */
2399         { SST(0x55, 0x0D, SS_RDEF,      /* XXX TBD */
2400             "Insufficient resources to create ROD token") },
2401         /*      R         */
2402         { SST(0x57, 0x00, SS_RDEF,
2403             "Unable to recover table-of-contents") },
2404         /*       O        */
2405         { SST(0x58, 0x00, SS_RDEF,
2406             "Generation does not exist") },
2407         /*       O        */
2408         { SST(0x59, 0x00, SS_RDEF,
2409             "Updated block read") },
2410         /* DTLPWRO   BK   */
2411         { SST(0x5A, 0x00, SS_RDEF,
2412             "Operator request or state change input") },
2413         /* DT  WROM  BK   */
2414         { SST(0x5A, 0x01, SS_RDEF,
2415             "Operator medium removal request") },
2416         /* DT  WRO A BK   */
2417         { SST(0x5A, 0x02, SS_RDEF,
2418             "Operator selected write protect") },
2419         /* DT  WRO A BK   */
2420         { SST(0x5A, 0x03, SS_RDEF,
2421             "Operator selected write permit") },
2422         /* DTLPWROM   K   */
2423         { SST(0x5B, 0x00, SS_RDEF,
2424             "Log exception") },
2425         /* DTLPWROM   K   */
2426         { SST(0x5B, 0x01, SS_RDEF,
2427             "Threshold condition met") },
2428         /* DTLPWROM   K   */
2429         { SST(0x5B, 0x02, SS_RDEF,
2430             "Log counter at maximum") },
2431         /* DTLPWROM   K   */
2432         { SST(0x5B, 0x03, SS_RDEF,
2433             "Log list codes exhausted") },
2434         /* D     O        */
2435         { SST(0x5C, 0x00, SS_RDEF,
2436             "RPL status change") },
2437         /* D     O        */
2438         { SST(0x5C, 0x01, SS_NOP | SSQ_PRINT_SENSE,
2439             "Spindles synchronized") },
2440         /* D     O        */
2441         { SST(0x5C, 0x02, SS_RDEF,
2442             "Spindles not synchronized") },
2443         /* DTLPWROMAEBKVF */
2444         { SST(0x5D, 0x00, SS_RDEF,
2445             "Failure prediction threshold exceeded") },
2446         /*      R    B    */
2447         { SST(0x5D, 0x01, SS_RDEF,      /* XXX TBD */
2448             "Media failure prediction threshold exceeded") },
2449         /*      R         */
2450         { SST(0x5D, 0x02, SS_RDEF,      /* XXX TBD */
2451             "Logical unit failure prediction threshold exceeded") },
2452         /*      R         */
2453         { SST(0x5D, 0x03, SS_RDEF,      /* XXX TBD */
2454             "Spare area exhaustion prediction threshold exceeded") },
2455         /* D         B    */
2456         { SST(0x5D, 0x10, SS_RDEF,      /* XXX TBD */
2457             "Hardware impending failure general hard drive failure") },
2458         /* D         B    */
2459         { SST(0x5D, 0x11, SS_RDEF,      /* XXX TBD */
2460             "Hardware impending failure drive error rate too high") },
2461         /* D         B    */
2462         { SST(0x5D, 0x12, SS_RDEF,      /* XXX TBD */
2463             "Hardware impending failure data error rate too high") },
2464         /* D         B    */
2465         { SST(0x5D, 0x13, SS_RDEF,      /* XXX TBD */
2466             "Hardware impending failure seek error rate too high") },
2467         /* D         B    */
2468         { SST(0x5D, 0x14, SS_RDEF,      /* XXX TBD */
2469             "Hardware impending failure too many block reassigns") },
2470         /* D         B    */
2471         { SST(0x5D, 0x15, SS_RDEF,      /* XXX TBD */
2472             "Hardware impending failure access times too high") },
2473         /* D         B    */
2474         { SST(0x5D, 0x16, SS_RDEF,      /* XXX TBD */
2475             "Hardware impending failure start unit times too high") },
2476         /* D         B    */
2477         { SST(0x5D, 0x17, SS_RDEF,      /* XXX TBD */
2478             "Hardware impending failure channel parametrics") },
2479         /* D         B    */
2480         { SST(0x5D, 0x18, SS_RDEF,      /* XXX TBD */
2481             "Hardware impending failure controller detected") },
2482         /* D         B    */
2483         { SST(0x5D, 0x19, SS_RDEF,      /* XXX TBD */
2484             "Hardware impending failure throughput performance") },
2485         /* D         B    */
2486         { SST(0x5D, 0x1A, SS_RDEF,      /* XXX TBD */
2487             "Hardware impending failure seek time performance") },
2488         /* D         B    */
2489         { SST(0x5D, 0x1B, SS_RDEF,      /* XXX TBD */
2490             "Hardware impending failure spin-up retry count") },
2491         /* D         B    */
2492         { SST(0x5D, 0x1C, SS_RDEF,      /* XXX TBD */
2493             "Hardware impending failure drive calibration retry count") },
2494         /* D         B    */
2495         { SST(0x5D, 0x20, SS_RDEF,      /* XXX TBD */
2496             "Controller impending failure general hard drive failure") },
2497         /* D         B    */
2498         { SST(0x5D, 0x21, SS_RDEF,      /* XXX TBD */
2499             "Controller impending failure drive error rate too high") },
2500         /* D         B    */
2501         { SST(0x5D, 0x22, SS_RDEF,      /* XXX TBD */
2502             "Controller impending failure data error rate too high") },
2503         /* D         B    */
2504         { SST(0x5D, 0x23, SS_RDEF,      /* XXX TBD */
2505             "Controller impending failure seek error rate too high") },
2506         /* D         B    */
2507         { SST(0x5D, 0x24, SS_RDEF,      /* XXX TBD */
2508             "Controller impending failure too many block reassigns") },
2509         /* D         B    */
2510         { SST(0x5D, 0x25, SS_RDEF,      /* XXX TBD */
2511             "Controller impending failure access times too high") },
2512         /* D         B    */
2513         { SST(0x5D, 0x26, SS_RDEF,      /* XXX TBD */
2514             "Controller impending failure start unit times too high") },
2515         /* D         B    */
2516         { SST(0x5D, 0x27, SS_RDEF,      /* XXX TBD */
2517             "Controller impending failure channel parametrics") },
2518         /* D         B    */
2519         { SST(0x5D, 0x28, SS_RDEF,      /* XXX TBD */
2520             "Controller impending failure controller detected") },
2521         /* D         B    */
2522         { SST(0x5D, 0x29, SS_RDEF,      /* XXX TBD */
2523             "Controller impending failure throughput performance") },
2524         /* D         B    */
2525         { SST(0x5D, 0x2A, SS_RDEF,      /* XXX TBD */
2526             "Controller impending failure seek time performance") },
2527         /* D         B    */
2528         { SST(0x5D, 0x2B, SS_RDEF,      /* XXX TBD */
2529             "Controller impending failure spin-up retry count") },
2530         /* D         B    */
2531         { SST(0x5D, 0x2C, SS_RDEF,      /* XXX TBD */
2532             "Controller impending failure drive calibration retry count") },
2533         /* D         B    */
2534         { SST(0x5D, 0x30, SS_RDEF,      /* XXX TBD */
2535             "Data channel impending failure general hard drive failure") },
2536         /* D         B    */
2537         { SST(0x5D, 0x31, SS_RDEF,      /* XXX TBD */
2538             "Data channel impending failure drive error rate too high") },
2539         /* D         B    */
2540         { SST(0x5D, 0x32, SS_RDEF,      /* XXX TBD */
2541             "Data channel impending failure data error rate too high") },
2542         /* D         B    */
2543         { SST(0x5D, 0x33, SS_RDEF,      /* XXX TBD */
2544             "Data channel impending failure seek error rate too high") },
2545         /* D         B    */
2546         { SST(0x5D, 0x34, SS_RDEF,      /* XXX TBD */
2547             "Data channel impending failure too many block reassigns") },
2548         /* D         B    */
2549         { SST(0x5D, 0x35, SS_RDEF,      /* XXX TBD */
2550             "Data channel impending failure access times too high") },
2551         /* D         B    */
2552         { SST(0x5D, 0x36, SS_RDEF,      /* XXX TBD */
2553             "Data channel impending failure start unit times too high") },
2554         /* D         B    */
2555         { SST(0x5D, 0x37, SS_RDEF,      /* XXX TBD */
2556             "Data channel impending failure channel parametrics") },
2557         /* D         B    */
2558         { SST(0x5D, 0x38, SS_RDEF,      /* XXX TBD */
2559             "Data channel impending failure controller detected") },
2560         /* D         B    */
2561         { SST(0x5D, 0x39, SS_RDEF,      /* XXX TBD */
2562             "Data channel impending failure throughput performance") },
2563         /* D         B    */
2564         { SST(0x5D, 0x3A, SS_RDEF,      /* XXX TBD */
2565             "Data channel impending failure seek time performance") },
2566         /* D         B    */
2567         { SST(0x5D, 0x3B, SS_RDEF,      /* XXX TBD */
2568             "Data channel impending failure spin-up retry count") },
2569         /* D         B    */
2570         { SST(0x5D, 0x3C, SS_RDEF,      /* XXX TBD */
2571             "Data channel impending failure drive calibration retry count") },
2572         /* D         B    */
2573         { SST(0x5D, 0x40, SS_RDEF,      /* XXX TBD */
2574             "Servo impending failure general hard drive failure") },
2575         /* D         B    */
2576         { SST(0x5D, 0x41, SS_RDEF,      /* XXX TBD */
2577             "Servo impending failure drive error rate too high") },
2578         /* D         B    */
2579         { SST(0x5D, 0x42, SS_RDEF,      /* XXX TBD */
2580             "Servo impending failure data error rate too high") },
2581         /* D         B    */
2582         { SST(0x5D, 0x43, SS_RDEF,      /* XXX TBD */
2583             "Servo impending failure seek error rate too high") },
2584         /* D         B    */
2585         { SST(0x5D, 0x44, SS_RDEF,      /* XXX TBD */
2586             "Servo impending failure too many block reassigns") },
2587         /* D         B    */
2588         { SST(0x5D, 0x45, SS_RDEF,      /* XXX TBD */
2589             "Servo impending failure access times too high") },
2590         /* D         B    */
2591         { SST(0x5D, 0x46, SS_RDEF,      /* XXX TBD */
2592             "Servo impending failure start unit times too high") },
2593         /* D         B    */
2594         { SST(0x5D, 0x47, SS_RDEF,      /* XXX TBD */
2595             "Servo impending failure channel parametrics") },
2596         /* D         B    */
2597         { SST(0x5D, 0x48, SS_RDEF,      /* XXX TBD */
2598             "Servo impending failure controller detected") },
2599         /* D         B    */
2600         { SST(0x5D, 0x49, SS_RDEF,      /* XXX TBD */
2601             "Servo impending failure throughput performance") },
2602         /* D         B    */
2603         { SST(0x5D, 0x4A, SS_RDEF,      /* XXX TBD */
2604             "Servo impending failure seek time performance") },
2605         /* D         B    */
2606         { SST(0x5D, 0x4B, SS_RDEF,      /* XXX TBD */
2607             "Servo impending failure spin-up retry count") },
2608         /* D         B    */
2609         { SST(0x5D, 0x4C, SS_RDEF,      /* XXX TBD */
2610             "Servo impending failure drive calibration retry count") },
2611         /* D         B    */
2612         { SST(0x5D, 0x50, SS_RDEF,      /* XXX TBD */
2613             "Spindle impending failure general hard drive failure") },
2614         /* D         B    */
2615         { SST(0x5D, 0x51, SS_RDEF,      /* XXX TBD */
2616             "Spindle impending failure drive error rate too high") },
2617         /* D         B    */
2618         { SST(0x5D, 0x52, SS_RDEF,      /* XXX TBD */
2619             "Spindle impending failure data error rate too high") },
2620         /* D         B    */
2621         { SST(0x5D, 0x53, SS_RDEF,      /* XXX TBD */
2622             "Spindle impending failure seek error rate too high") },
2623         /* D         B    */
2624         { SST(0x5D, 0x54, SS_RDEF,      /* XXX TBD */
2625             "Spindle impending failure too many block reassigns") },
2626         /* D         B    */
2627         { SST(0x5D, 0x55, SS_RDEF,      /* XXX TBD */
2628             "Spindle impending failure access times too high") },
2629         /* D         B    */
2630         { SST(0x5D, 0x56, SS_RDEF,      /* XXX TBD */
2631             "Spindle impending failure start unit times too high") },
2632         /* D         B    */
2633         { SST(0x5D, 0x57, SS_RDEF,      /* XXX TBD */
2634             "Spindle impending failure channel parametrics") },
2635         /* D         B    */
2636         { SST(0x5D, 0x58, SS_RDEF,      /* XXX TBD */
2637             "Spindle impending failure controller detected") },
2638         /* D         B    */
2639         { SST(0x5D, 0x59, SS_RDEF,      /* XXX TBD */
2640             "Spindle impending failure throughput performance") },
2641         /* D         B    */
2642         { SST(0x5D, 0x5A, SS_RDEF,      /* XXX TBD */
2643             "Spindle impending failure seek time performance") },
2644         /* D         B    */
2645         { SST(0x5D, 0x5B, SS_RDEF,      /* XXX TBD */
2646             "Spindle impending failure spin-up retry count") },
2647         /* D         B    */
2648         { SST(0x5D, 0x5C, SS_RDEF,      /* XXX TBD */
2649             "Spindle impending failure drive calibration retry count") },
2650         /* D         B    */
2651         { SST(0x5D, 0x60, SS_RDEF,      /* XXX TBD */
2652             "Firmware impending failure general hard drive failure") },
2653         /* D         B    */
2654         { SST(0x5D, 0x61, SS_RDEF,      /* XXX TBD */
2655             "Firmware impending failure drive error rate too high") },
2656         /* D         B    */
2657         { SST(0x5D, 0x62, SS_RDEF,      /* XXX TBD */
2658             "Firmware impending failure data error rate too high") },
2659         /* D         B    */
2660         { SST(0x5D, 0x63, SS_RDEF,      /* XXX TBD */
2661             "Firmware impending failure seek error rate too high") },
2662         /* D         B    */
2663         { SST(0x5D, 0x64, SS_RDEF,      /* XXX TBD */
2664             "Firmware impending failure too many block reassigns") },
2665         /* D         B    */
2666         { SST(0x5D, 0x65, SS_RDEF,      /* XXX TBD */
2667             "Firmware impending failure access times too high") },
2668         /* D         B    */
2669         { SST(0x5D, 0x66, SS_RDEF,      /* XXX TBD */
2670             "Firmware impending failure start unit times too high") },
2671         /* D         B    */
2672         { SST(0x5D, 0x67, SS_RDEF,      /* XXX TBD */
2673             "Firmware impending failure channel parametrics") },
2674         /* D         B    */
2675         { SST(0x5D, 0x68, SS_RDEF,      /* XXX TBD */
2676             "Firmware impending failure controller detected") },
2677         /* D         B    */
2678         { SST(0x5D, 0x69, SS_RDEF,      /* XXX TBD */
2679             "Firmware impending failure throughput performance") },
2680         /* D         B    */
2681         { SST(0x5D, 0x6A, SS_RDEF,      /* XXX TBD */
2682             "Firmware impending failure seek time performance") },
2683         /* D         B    */
2684         { SST(0x5D, 0x6B, SS_RDEF,      /* XXX TBD */
2685             "Firmware impending failure spin-up retry count") },
2686         /* D         B    */
2687         { SST(0x5D, 0x6C, SS_RDEF,      /* XXX TBD */
2688             "Firmware impending failure drive calibration retry count") },
2689         /* DTLPWROMAEBKVF */
2690         { SST(0x5D, 0xFF, SS_RDEF,
2691             "Failure prediction threshold exceeded (false)") },
2692         /* DTLPWRO A  K   */
2693         { SST(0x5E, 0x00, SS_RDEF,
2694             "Low power condition on") },
2695         /* DTLPWRO A  K   */
2696         { SST(0x5E, 0x01, SS_RDEF,
2697             "Idle condition activated by timer") },
2698         /* DTLPWRO A  K   */
2699         { SST(0x5E, 0x02, SS_RDEF,
2700             "Standby condition activated by timer") },
2701         /* DTLPWRO A  K   */
2702         { SST(0x5E, 0x03, SS_RDEF,
2703             "Idle condition activated by command") },
2704         /* DTLPWRO A  K   */
2705         { SST(0x5E, 0x04, SS_RDEF,
2706             "Standby condition activated by command") },
2707         /* DTLPWRO A  K   */
2708         { SST(0x5E, 0x05, SS_RDEF,
2709             "Idle-B condition activated by timer") },
2710         /* DTLPWRO A  K   */
2711         { SST(0x5E, 0x06, SS_RDEF,
2712             "Idle-B condition activated by command") },
2713         /* DTLPWRO A  K   */
2714         { SST(0x5E, 0x07, SS_RDEF,
2715             "Idle-C condition activated by timer") },
2716         /* DTLPWRO A  K   */
2717         { SST(0x5E, 0x08, SS_RDEF,
2718             "Idle-C condition activated by command") },
2719         /* DTLPWRO A  K   */
2720         { SST(0x5E, 0x09, SS_RDEF,
2721             "Standby-Y condition activated by timer") },
2722         /* DTLPWRO A  K   */
2723         { SST(0x5E, 0x0A, SS_RDEF,
2724             "Standby-Y condition activated by command") },
2725         /*           B    */
2726         { SST(0x5E, 0x41, SS_RDEF,      /* XXX TBD */
2727             "Power state change to active") },
2728         /*           B    */
2729         { SST(0x5E, 0x42, SS_RDEF,      /* XXX TBD */
2730             "Power state change to idle") },
2731         /*           B    */
2732         { SST(0x5E, 0x43, SS_RDEF,      /* XXX TBD */
2733             "Power state change to standby") },
2734         /*           B    */
2735         { SST(0x5E, 0x45, SS_RDEF,      /* XXX TBD */
2736             "Power state change to sleep") },
2737         /*           BK   */
2738         { SST(0x5E, 0x47, SS_RDEF,      /* XXX TBD */
2739             "Power state change to device control") },
2740         /*                */
2741         { SST(0x60, 0x00, SS_RDEF,
2742             "Lamp failure") },
2743         /*                */
2744         { SST(0x61, 0x00, SS_RDEF,
2745             "Video acquisition error") },
2746         /*                */
2747         { SST(0x61, 0x01, SS_RDEF,
2748             "Unable to acquire video") },
2749         /*                */
2750         { SST(0x61, 0x02, SS_RDEF,
2751             "Out of focus") },
2752         /*                */
2753         { SST(0x62, 0x00, SS_RDEF,
2754             "Scan head positioning error") },
2755         /*      R         */
2756         { SST(0x63, 0x00, SS_RDEF,
2757             "End of user area encountered on this track") },
2758         /*      R         */
2759         { SST(0x63, 0x01, SS_FATAL | ENOSPC,
2760             "Packet does not fit in available space") },
2761         /*      R         */
2762         { SST(0x64, 0x00, SS_FATAL | ENXIO,
2763             "Illegal mode for this track") },
2764         /*      R         */
2765         { SST(0x64, 0x01, SS_RDEF,
2766             "Invalid packet size") },
2767         /* DTLPWROMAEBKVF */
2768         { SST(0x65, 0x00, SS_RDEF,
2769             "Voltage fault") },
2770         /*                */
2771         { SST(0x66, 0x00, SS_RDEF,
2772             "Automatic document feeder cover up") },
2773         /*                */
2774         { SST(0x66, 0x01, SS_RDEF,
2775             "Automatic document feeder lift up") },
2776         /*                */
2777         { SST(0x66, 0x02, SS_RDEF,
2778             "Document jam in automatic document feeder") },
2779         /*                */
2780         { SST(0x66, 0x03, SS_RDEF,
2781             "Document miss feed automatic in document feeder") },
2782         /*         A      */
2783         { SST(0x67, 0x00, SS_RDEF,
2784             "Configuration failure") },
2785         /*         A      */
2786         { SST(0x67, 0x01, SS_RDEF,
2787             "Configuration of incapable logical units failed") },
2788         /*         A      */
2789         { SST(0x67, 0x02, SS_RDEF,
2790             "Add logical unit failed") },
2791         /*         A      */
2792         { SST(0x67, 0x03, SS_RDEF,
2793             "Modification of logical unit failed") },
2794         /*         A      */
2795         { SST(0x67, 0x04, SS_RDEF,
2796             "Exchange of logical unit failed") },
2797         /*         A      */
2798         { SST(0x67, 0x05, SS_RDEF,
2799             "Remove of logical unit failed") },
2800         /*         A      */
2801         { SST(0x67, 0x06, SS_RDEF,
2802             "Attachment of logical unit failed") },
2803         /*         A      */
2804         { SST(0x67, 0x07, SS_RDEF,
2805             "Creation of logical unit failed") },
2806         /*         A      */
2807         { SST(0x67, 0x08, SS_RDEF,      /* XXX TBD */
2808             "Assign failure occurred") },
2809         /*         A      */
2810         { SST(0x67, 0x09, SS_RDEF,      /* XXX TBD */
2811             "Multiply assigned logical unit") },
2812         /* DTLPWROMAEBKVF */
2813         { SST(0x67, 0x0A, SS_RDEF,      /* XXX TBD */
2814             "Set target port groups command failed") },
2815         /* DT        B    */
2816         { SST(0x67, 0x0B, SS_RDEF,      /* XXX TBD */
2817             "ATA device feature not enabled") },
2818         /*         A      */
2819         { SST(0x68, 0x00, SS_RDEF,
2820             "Logical unit not configured") },
2821         /*         A      */
2822         { SST(0x69, 0x00, SS_RDEF,
2823             "Data loss on logical unit") },
2824         /*         A      */
2825         { SST(0x69, 0x01, SS_RDEF,
2826             "Multiple logical unit failures") },
2827         /*         A      */
2828         { SST(0x69, 0x02, SS_RDEF,
2829             "Parity/data mismatch") },
2830         /*         A      */
2831         { SST(0x6A, 0x00, SS_RDEF,
2832             "Informational, refer to log") },
2833         /*         A      */
2834         { SST(0x6B, 0x00, SS_RDEF,
2835             "State change has occurred") },
2836         /*         A      */
2837         { SST(0x6B, 0x01, SS_RDEF,
2838             "Redundancy level got better") },
2839         /*         A      */
2840         { SST(0x6B, 0x02, SS_RDEF,
2841             "Redundancy level got worse") },
2842         /*         A      */
2843         { SST(0x6C, 0x00, SS_RDEF,
2844             "Rebuild failure occurred") },
2845         /*         A      */
2846         { SST(0x6D, 0x00, SS_RDEF,
2847             "Recalculate failure occurred") },
2848         /*         A      */
2849         { SST(0x6E, 0x00, SS_RDEF,
2850             "Command to logical unit failed") },
2851         /*      R         */
2852         { SST(0x6F, 0x00, SS_RDEF,      /* XXX TBD */
2853             "Copy protection key exchange failure - authentication failure") },
2854         /*      R         */
2855         { SST(0x6F, 0x01, SS_RDEF,      /* XXX TBD */
2856             "Copy protection key exchange failure - key not present") },
2857         /*      R         */
2858         { SST(0x6F, 0x02, SS_RDEF,      /* XXX TBD */
2859             "Copy protection key exchange failure - key not established") },
2860         /*      R         */
2861         { SST(0x6F, 0x03, SS_RDEF,      /* XXX TBD */
2862             "Read of scrambled sector without authentication") },
2863         /*      R         */
2864         { SST(0x6F, 0x04, SS_RDEF,      /* XXX TBD */
2865             "Media region code is mismatched to logical unit region") },
2866         /*      R         */
2867         { SST(0x6F, 0x05, SS_RDEF,      /* XXX TBD */
2868             "Drive region must be permanent/region reset count error") },
2869         /*      R         */
2870         { SST(0x6F, 0x06, SS_RDEF,      /* XXX TBD */
2871             "Insufficient block count for binding NONCE recording") },
2872         /*      R         */
2873         { SST(0x6F, 0x07, SS_RDEF,      /* XXX TBD */
2874             "Conflict in binding NONCE recording") },
2875         /*  T             */
2876         { SST(0x70, 0x00, SS_RDEF,
2877             "Decompression exception short: ASCQ = Algorithm ID") },
2878         /*  T             */
2879         { SST(0x70, 0xFF, SS_RDEF | SSQ_RANGE,
2880             NULL) },                    /* Range 0x00 -> 0xFF */
2881         /*  T             */
2882         { SST(0x71, 0x00, SS_RDEF,
2883             "Decompression exception long: ASCQ = Algorithm ID") },
2884         /*  T             */
2885         { SST(0x71, 0xFF, SS_RDEF | SSQ_RANGE,
2886             NULL) },                    /* Range 0x00 -> 0xFF */
2887         /*      R         */
2888         { SST(0x72, 0x00, SS_RDEF,
2889             "Session fixation error") },
2890         /*      R         */
2891         { SST(0x72, 0x01, SS_RDEF,
2892             "Session fixation error writing lead-in") },
2893         /*      R         */
2894         { SST(0x72, 0x02, SS_RDEF,
2895             "Session fixation error writing lead-out") },
2896         /*      R         */
2897         { SST(0x72, 0x03, SS_RDEF,
2898             "Session fixation error - incomplete track in session") },
2899         /*      R         */
2900         { SST(0x72, 0x04, SS_RDEF,
2901             "Empty or partially written reserved track") },
2902         /*      R         */
2903         { SST(0x72, 0x05, SS_RDEF,      /* XXX TBD */
2904             "No more track reservations allowed") },
2905         /*      R         */
2906         { SST(0x72, 0x06, SS_RDEF,      /* XXX TBD */
2907             "RMZ extension is not allowed") },
2908         /*      R         */
2909         { SST(0x72, 0x07, SS_RDEF,      /* XXX TBD */
2910             "No more test zone extensions are allowed") },
2911         /*      R         */
2912         { SST(0x73, 0x00, SS_RDEF,
2913             "CD control error") },
2914         /*      R         */
2915         { SST(0x73, 0x01, SS_RDEF,
2916             "Power calibration area almost full") },
2917         /*      R         */
2918         { SST(0x73, 0x02, SS_FATAL | ENOSPC,
2919             "Power calibration area is full") },
2920         /*      R         */
2921         { SST(0x73, 0x03, SS_RDEF,
2922             "Power calibration area error") },
2923         /*      R         */
2924         { SST(0x73, 0x04, SS_RDEF,
2925             "Program memory area update failure") },
2926         /*      R         */
2927         { SST(0x73, 0x05, SS_RDEF,
2928             "Program memory area is full") },
2929         /*      R         */
2930         { SST(0x73, 0x06, SS_RDEF,      /* XXX TBD */
2931             "RMA/PMA is almost full") },
2932         /*      R         */
2933         { SST(0x73, 0x10, SS_RDEF,      /* XXX TBD */
2934             "Current power calibration area almost full") },
2935         /*      R         */
2936         { SST(0x73, 0x11, SS_RDEF,      /* XXX TBD */
2937             "Current power calibration area is full") },
2938         /*      R         */
2939         { SST(0x73, 0x17, SS_RDEF,      /* XXX TBD */
2940             "RDZ is full") },
2941         /*  T             */
2942         { SST(0x74, 0x00, SS_RDEF,      /* XXX TBD */
2943             "Security error") },
2944         /*  T             */
2945         { SST(0x74, 0x01, SS_RDEF,      /* XXX TBD */
2946             "Unable to decrypt data") },
2947         /*  T             */
2948         { SST(0x74, 0x02, SS_RDEF,      /* XXX TBD */
2949             "Unencrypted data encountered while decrypting") },
2950         /*  T             */
2951         { SST(0x74, 0x03, SS_RDEF,      /* XXX TBD */
2952             "Incorrect data encryption key") },
2953         /*  T             */
2954         { SST(0x74, 0x04, SS_RDEF,      /* XXX TBD */
2955             "Cryptographic integrity validation failed") },
2956         /*  T             */
2957         { SST(0x74, 0x05, SS_RDEF,      /* XXX TBD */
2958             "Error decrypting data") },
2959         /*  T             */
2960         { SST(0x74, 0x06, SS_RDEF,      /* XXX TBD */
2961             "Unknown signature verification key") },
2962         /*  T             */
2963         { SST(0x74, 0x07, SS_RDEF,      /* XXX TBD */
2964             "Encryption parameters not useable") },
2965         /* DT   R M E  VF */
2966         { SST(0x74, 0x08, SS_RDEF,      /* XXX TBD */
2967             "Digital signature validation failure") },
2968         /*  T             */
2969         { SST(0x74, 0x09, SS_RDEF,      /* XXX TBD */
2970             "Encryption mode mismatch on read") },
2971         /*  T             */
2972         { SST(0x74, 0x0A, SS_RDEF,      /* XXX TBD */
2973             "Encrypted block not raw read enabled") },
2974         /*  T             */
2975         { SST(0x74, 0x0B, SS_RDEF,      /* XXX TBD */
2976             "Incorrect encryption parameters") },
2977         /* DT   R MAEBKV  */
2978         { SST(0x74, 0x0C, SS_RDEF,      /* XXX TBD */
2979             "Unable to decrypt parameter list") },
2980         /*  T             */
2981         { SST(0x74, 0x0D, SS_RDEF,      /* XXX TBD */
2982             "Encryption algorithm disabled") },
2983         /* DT   R MAEBKV  */
2984         { SST(0x74, 0x10, SS_RDEF,      /* XXX TBD */
2985             "SA creation parameter value invalid") },
2986         /* DT   R MAEBKV  */
2987         { SST(0x74, 0x11, SS_RDEF,      /* XXX TBD */
2988             "SA creation parameter value rejected") },
2989         /* DT   R MAEBKV  */
2990         { SST(0x74, 0x12, SS_RDEF,      /* XXX TBD */
2991             "Invalid SA usage") },
2992         /*  T             */
2993         { SST(0x74, 0x21, SS_RDEF,      /* XXX TBD */
2994             "Data encryption configuration prevented") },
2995         /* DT   R MAEBKV  */
2996         { SST(0x74, 0x30, SS_RDEF,      /* XXX TBD */
2997             "SA creation parameter not supported") },
2998         /* DT   R MAEBKV  */
2999         { SST(0x74, 0x40, SS_RDEF,      /* XXX TBD */
3000             "Authentication failed") },
3001         /*             V  */
3002         { SST(0x74, 0x61, SS_RDEF,      /* XXX TBD */
3003             "External data encryption key manager access error") },
3004         /*             V  */
3005         { SST(0x74, 0x62, SS_RDEF,      /* XXX TBD */
3006             "External data encryption key manager error") },
3007         /*             V  */
3008         { SST(0x74, 0x63, SS_RDEF,      /* XXX TBD */
3009             "External data encryption key not found") },
3010         /*             V  */
3011         { SST(0x74, 0x64, SS_RDEF,      /* XXX TBD */
3012             "External data encryption request not authorized") },
3013         /*  T             */
3014         { SST(0x74, 0x6E, SS_RDEF,      /* XXX TBD */
3015             "External data encryption control timeout") },
3016         /*  T             */
3017         { SST(0x74, 0x6F, SS_RDEF,      /* XXX TBD */
3018             "External data encryption control error") },
3019         /* DT   R M E  V  */
3020         { SST(0x74, 0x71, SS_RDEF,      /* XXX TBD */
3021             "Logical unit access not authorized") },
3022         /* D              */
3023         { SST(0x74, 0x79, SS_RDEF,      /* XXX TBD */
3024             "Security conflict in translated device") }
3025 };
3026
3027 const int asc_table_size = sizeof(asc_table)/sizeof(asc_table[0]);
3028
3029 struct asc_key
3030 {
3031         int asc;
3032         int ascq;
3033 };
3034
3035 static int
3036 ascentrycomp(const void *key, const void *member)
3037 {
3038         int asc;
3039         int ascq;
3040         const struct asc_table_entry *table_entry;
3041
3042         asc = ((const struct asc_key *)key)->asc;
3043         ascq = ((const struct asc_key *)key)->ascq;
3044         table_entry = (const struct asc_table_entry *)member;
3045
3046         if (asc >= table_entry->asc) {
3047
3048                 if (asc > table_entry->asc)
3049                         return (1);
3050
3051                 if (ascq <= table_entry->ascq) {
3052                         /* Check for ranges */
3053                         if (ascq == table_entry->ascq
3054                          || ((table_entry->action & SSQ_RANGE) != 0
3055                            && ascq >= (table_entry - 1)->ascq))
3056                                 return (0);
3057                         return (-1);
3058                 }
3059                 return (1);
3060         }
3061         return (-1);
3062 }
3063
3064 static int
3065 senseentrycomp(const void *key, const void *member)
3066 {
3067         int sense_key;
3068         const struct sense_key_table_entry *table_entry;
3069
3070         sense_key = *((const int *)key);
3071         table_entry = (const struct sense_key_table_entry *)member;
3072
3073         if (sense_key >= table_entry->sense_key) {
3074                 if (sense_key == table_entry->sense_key)
3075                         return (0);
3076                 return (1);
3077         }
3078         return (-1);
3079 }
3080
3081 static void
3082 fetchtableentries(int sense_key, int asc, int ascq,
3083                   struct scsi_inquiry_data *inq_data,
3084                   const struct sense_key_table_entry **sense_entry,
3085                   const struct asc_table_entry **asc_entry)
3086 {
3087         caddr_t match;
3088         const struct asc_table_entry *asc_tables[2];
3089         const struct sense_key_table_entry *sense_tables[2];
3090         struct asc_key asc_ascq;
3091         size_t asc_tables_size[2];
3092         size_t sense_tables_size[2];
3093         int num_asc_tables;
3094         int num_sense_tables;
3095         int i;
3096
3097         /* Default to failure */
3098         *sense_entry = NULL;
3099         *asc_entry = NULL;
3100         match = NULL;
3101         if (inq_data != NULL)
3102                 match = cam_quirkmatch((caddr_t)inq_data,
3103                                        (caddr_t)sense_quirk_table,
3104                                        sense_quirk_table_size,
3105                                        sizeof(*sense_quirk_table),
3106                                        scsi_inquiry_match);
3107
3108         if (match != NULL) {
3109                 struct scsi_sense_quirk_entry *quirk;
3110
3111                 quirk = (struct scsi_sense_quirk_entry *)match;
3112                 asc_tables[0] = quirk->asc_info;
3113                 asc_tables_size[0] = quirk->num_ascs;
3114                 asc_tables[1] = asc_table;
3115                 asc_tables_size[1] = asc_table_size;
3116                 num_asc_tables = 2;
3117                 sense_tables[0] = quirk->sense_key_info;
3118                 sense_tables_size[0] = quirk->num_sense_keys;
3119                 sense_tables[1] = sense_key_table;
3120                 sense_tables_size[1] = sense_key_table_size;
3121                 num_sense_tables = 2;
3122         } else {
3123                 asc_tables[0] = asc_table;
3124                 asc_tables_size[0] = asc_table_size;
3125                 num_asc_tables = 1;
3126                 sense_tables[0] = sense_key_table;
3127                 sense_tables_size[0] = sense_key_table_size;
3128                 num_sense_tables = 1;
3129         }
3130
3131         asc_ascq.asc = asc;
3132         asc_ascq.ascq = ascq;
3133         for (i = 0; i < num_asc_tables; i++) {
3134                 void *found_entry;
3135
3136                 found_entry = bsearch(&asc_ascq, asc_tables[i],
3137                                       asc_tables_size[i],
3138                                       sizeof(**asc_tables),
3139                                       ascentrycomp);
3140
3141                 if (found_entry) {
3142                         *asc_entry = (struct asc_table_entry *)found_entry;
3143                         break;
3144                 }
3145         }
3146
3147         for (i = 0; i < num_sense_tables; i++) {
3148                 void *found_entry;
3149
3150                 found_entry = bsearch(&sense_key, sense_tables[i],
3151                                       sense_tables_size[i],
3152                                       sizeof(**sense_tables),
3153                                       senseentrycomp);
3154
3155                 if (found_entry) {
3156                         *sense_entry =
3157                             (struct sense_key_table_entry *)found_entry;
3158                         break;
3159                 }
3160         }
3161 }
3162
3163 void
3164 scsi_sense_desc(int sense_key, int asc, int ascq,
3165                 struct scsi_inquiry_data *inq_data,
3166                 const char **sense_key_desc, const char **asc_desc)
3167 {
3168         const struct asc_table_entry *asc_entry;
3169         const struct sense_key_table_entry *sense_entry;
3170
3171         fetchtableentries(sense_key, asc, ascq,
3172                           inq_data,
3173                           &sense_entry,
3174                           &asc_entry);
3175
3176         if (sense_entry != NULL)
3177                 *sense_key_desc = sense_entry->desc;
3178         else
3179                 *sense_key_desc = "Invalid Sense Key";
3180
3181         if (asc_entry != NULL)
3182                 *asc_desc = asc_entry->desc;
3183         else if (asc >= 0x80 && asc <= 0xff)
3184                 *asc_desc = "Vendor Specific ASC";
3185         else if (ascq >= 0x80 && ascq <= 0xff)
3186                 *asc_desc = "Vendor Specific ASCQ";
3187         else
3188                 *asc_desc = "Reserved ASC/ASCQ pair";
3189 }
3190
3191 /*
3192  * Given sense and device type information, return the appropriate action.
3193  * If we do not understand the specific error as identified by the ASC/ASCQ
3194  * pair, fall back on the more generic actions derived from the sense key.
3195  */
3196 scsi_sense_action
3197 scsi_error_action(struct ccb_scsiio *csio, struct scsi_inquiry_data *inq_data,
3198                   u_int32_t sense_flags)
3199 {
3200         const struct asc_table_entry *asc_entry;
3201         const struct sense_key_table_entry *sense_entry;
3202         int error_code, sense_key, asc, ascq;
3203         scsi_sense_action action;
3204
3205         if (!scsi_extract_sense_ccb((union ccb *)csio,
3206             &error_code, &sense_key, &asc, &ascq)) {
3207                 action = SS_RETRY | SSQ_DECREMENT_COUNT | SSQ_PRINT_SENSE | EIO;
3208         } else if ((error_code == SSD_DEFERRED_ERROR)
3209          || (error_code == SSD_DESC_DEFERRED_ERROR)) {
3210                 /*
3211                  * XXX dufault@FreeBSD.org
3212                  * This error doesn't relate to the command associated
3213                  * with this request sense.  A deferred error is an error
3214                  * for a command that has already returned GOOD status
3215                  * (see SCSI2 8.2.14.2).
3216                  *
3217                  * By my reading of that section, it looks like the current
3218                  * command has been cancelled, we should now clean things up
3219                  * (hopefully recovering any lost data) and then retry the
3220                  * current command.  There are two easy choices, both wrong:
3221                  *
3222                  * 1. Drop through (like we had been doing), thus treating
3223                  *    this as if the error were for the current command and
3224                  *    return and stop the current command.
3225                  * 
3226                  * 2. Issue a retry (like I made it do) thus hopefully
3227                  *    recovering the current transfer, and ignoring the
3228                  *    fact that we've dropped a command.
3229                  *
3230                  * These should probably be handled in a device specific
3231                  * sense handler or punted back up to a user mode daemon
3232                  */
3233                 action = SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE;
3234         } else {
3235                 fetchtableentries(sense_key, asc, ascq,
3236                                   inq_data,
3237                                   &sense_entry,
3238                                   &asc_entry);
3239
3240                 /*
3241                  * Override the 'No additional Sense' entry (0,0)
3242                  * with the error action of the sense key.
3243                  */
3244                 if (asc_entry != NULL
3245                  && (asc != 0 || ascq != 0))
3246                         action = asc_entry->action;
3247                 else if (sense_entry != NULL)
3248                         action = sense_entry->action;
3249                 else
3250                         action = SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE; 
3251
3252                 if (sense_key == SSD_KEY_RECOVERED_ERROR) {
3253                         /*
3254                          * The action succeeded but the device wants
3255                          * the user to know that some recovery action
3256                          * was required.
3257                          */
3258                         action &= ~(SS_MASK|SSQ_MASK|SS_ERRMASK);
3259                         action |= SS_NOP|SSQ_PRINT_SENSE;
3260                 } else if (sense_key == SSD_KEY_ILLEGAL_REQUEST) {
3261                         if ((sense_flags & SF_QUIET_IR) != 0)
3262                                 action &= ~SSQ_PRINT_SENSE;
3263                 } else if (sense_key == SSD_KEY_UNIT_ATTENTION) {
3264                         if ((sense_flags & SF_RETRY_UA) != 0
3265                          && (action & SS_MASK) == SS_FAIL) {
3266                                 action &= ~(SS_MASK|SSQ_MASK);
3267                                 action |= SS_RETRY|SSQ_DECREMENT_COUNT|
3268                                           SSQ_PRINT_SENSE;
3269                         }
3270                         action |= SSQ_UA;
3271                 }
3272         }
3273         if ((action & SS_MASK) >= SS_START &&
3274             (sense_flags & SF_NO_RECOVERY)) {
3275                 action &= ~SS_MASK;
3276                 action |= SS_FAIL;
3277         } else if ((action & SS_MASK) == SS_RETRY &&
3278             (sense_flags & SF_NO_RETRY)) {
3279                 action &= ~SS_MASK;
3280                 action |= SS_FAIL;
3281         }
3282         if ((sense_flags & SF_PRINT_ALWAYS) != 0)
3283                 action |= SSQ_PRINT_SENSE;
3284         else if ((sense_flags & SF_NO_PRINT) != 0)
3285                 action &= ~SSQ_PRINT_SENSE;
3286
3287         return (action);
3288 }
3289
3290 char *
3291 scsi_cdb_string(u_int8_t *cdb_ptr, char *cdb_string, size_t len)
3292 {
3293         u_int8_t cdb_len;
3294         int i;
3295
3296         if (cdb_ptr == NULL)
3297                 return("");
3298
3299         /* Silence warnings */
3300         cdb_len = 0;
3301
3302         /*
3303          * This is taken from the SCSI-3 draft spec.
3304          * (T10/1157D revision 0.3)
3305          * The top 3 bits of an opcode are the group code.  The next 5 bits
3306          * are the command code.
3307          * Group 0:  six byte commands
3308          * Group 1:  ten byte commands
3309          * Group 2:  ten byte commands
3310          * Group 3:  reserved
3311          * Group 4:  sixteen byte commands
3312          * Group 5:  twelve byte commands
3313          * Group 6:  vendor specific
3314          * Group 7:  vendor specific
3315          */
3316         switch((*cdb_ptr >> 5) & 0x7) {
3317                 case 0:
3318                         cdb_len = 6;
3319                         break;
3320                 case 1:
3321                 case 2:
3322                         cdb_len = 10;
3323                         break;
3324                 case 3:
3325                 case 6:
3326                 case 7:
3327                         /* in this case, just print out the opcode */
3328                         cdb_len = 1;
3329                         break;
3330                 case 4:
3331                         cdb_len = 16;
3332                         break;
3333                 case 5:
3334                         cdb_len = 12;
3335                         break;
3336         }
3337         *cdb_string = '\0';
3338         for (i = 0; i < cdb_len; i++)
3339                 snprintf(cdb_string + strlen(cdb_string),
3340                          len - strlen(cdb_string), "%02hhx ", cdb_ptr[i]);
3341
3342         return(cdb_string);
3343 }
3344
3345 const char *
3346 scsi_status_string(struct ccb_scsiio *csio)
3347 {
3348         switch(csio->scsi_status) {
3349         case SCSI_STATUS_OK:
3350                 return("OK");
3351         case SCSI_STATUS_CHECK_COND:
3352                 return("Check Condition");
3353         case SCSI_STATUS_BUSY:
3354                 return("Busy");
3355         case SCSI_STATUS_INTERMED:
3356                 return("Intermediate");
3357         case SCSI_STATUS_INTERMED_COND_MET:
3358                 return("Intermediate-Condition Met");
3359         case SCSI_STATUS_RESERV_CONFLICT:
3360                 return("Reservation Conflict");
3361         case SCSI_STATUS_CMD_TERMINATED:
3362                 return("Command Terminated");
3363         case SCSI_STATUS_QUEUE_FULL:
3364                 return("Queue Full");
3365         case SCSI_STATUS_ACA_ACTIVE:
3366                 return("ACA Active");
3367         case SCSI_STATUS_TASK_ABORTED:
3368                 return("Task Aborted");
3369         default: {
3370                 static char unkstr[64];
3371                 snprintf(unkstr, sizeof(unkstr), "Unknown %#x",
3372                          csio->scsi_status);
3373                 return(unkstr);
3374         }
3375         }
3376 }
3377
3378 /*
3379  * scsi_command_string() returns 0 for success and -1 for failure.
3380  */
3381 #ifdef _KERNEL
3382 int
3383 scsi_command_string(struct ccb_scsiio *csio, struct sbuf *sb)
3384 #else /* !_KERNEL */
3385 int
3386 scsi_command_string(struct cam_device *device, struct ccb_scsiio *csio, 
3387                     struct sbuf *sb)
3388 #endif /* _KERNEL/!_KERNEL */
3389 {
3390         struct scsi_inquiry_data *inq_data;
3391         char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
3392 #ifdef _KERNEL
3393         struct    ccb_getdev *cgd;
3394 #endif /* _KERNEL */
3395
3396 #ifdef _KERNEL
3397         if ((cgd = (struct ccb_getdev*)xpt_alloc_ccb_nowait()) == NULL)
3398                 return(-1);
3399         /*
3400          * Get the device information.
3401          */
3402         xpt_setup_ccb(&cgd->ccb_h,
3403                       csio->ccb_h.path,
3404                       CAM_PRIORITY_NORMAL);
3405         cgd->ccb_h.func_code = XPT_GDEV_TYPE;
3406         xpt_action((union ccb *)cgd);
3407
3408         /*
3409          * If the device is unconfigured, just pretend that it is a hard
3410          * drive.  scsi_op_desc() needs this.
3411          */
3412         if (cgd->ccb_h.status == CAM_DEV_NOT_THERE)
3413                 cgd->inq_data.device = T_DIRECT;
3414
3415         inq_data = &cgd->inq_data;
3416
3417 #else /* !_KERNEL */
3418
3419         inq_data = &device->inq_data;
3420
3421 #endif /* _KERNEL/!_KERNEL */
3422
3423         if ((csio->ccb_h.flags & CAM_CDB_POINTER) != 0) {
3424                 sbuf_printf(sb, "%s. CDB: %s", 
3425                             scsi_op_desc(csio->cdb_io.cdb_ptr[0], inq_data),
3426                             scsi_cdb_string(csio->cdb_io.cdb_ptr, cdb_str,
3427                                             sizeof(cdb_str)));
3428         } else {
3429                 sbuf_printf(sb, "%s. CDB: %s",
3430                             scsi_op_desc(csio->cdb_io.cdb_bytes[0], inq_data),
3431                             scsi_cdb_string(csio->cdb_io.cdb_bytes, cdb_str,
3432                                             sizeof(cdb_str)));
3433         }
3434
3435 #ifdef _KERNEL
3436         xpt_free_ccb((union ccb *)cgd);
3437 #endif
3438
3439         return(0);
3440 }
3441
3442 /*
3443  * Iterate over sense descriptors.  Each descriptor is passed into iter_func(). 
3444  * If iter_func() returns 0, list traversal continues.  If iter_func()
3445  * returns non-zero, list traversal is stopped.
3446  */
3447 void
3448 scsi_desc_iterate(struct scsi_sense_data_desc *sense, u_int sense_len,
3449                   int (*iter_func)(struct scsi_sense_data_desc *sense,
3450                                    u_int, struct scsi_sense_desc_header *,
3451                                    void *), void *arg)
3452 {
3453         int cur_pos;
3454         int desc_len;
3455
3456         /*
3457          * First make sure the extra length field is present.
3458          */
3459         if (SSD_DESC_IS_PRESENT(sense, sense_len, extra_len) == 0)
3460                 return;
3461
3462         /*
3463          * The length of data actually returned may be different than the
3464          * extra_len recorded in the sturcture.
3465          */
3466         desc_len = sense_len -offsetof(struct scsi_sense_data_desc, sense_desc);
3467
3468         /*
3469          * Limit this further by the extra length reported, and the maximum
3470          * allowed extra length.
3471          */
3472         desc_len = MIN(desc_len, MIN(sense->extra_len, SSD_EXTRA_MAX));
3473
3474         /*
3475          * Subtract the size of the header from the descriptor length.
3476          * This is to ensure that we have at least the header left, so we
3477          * don't have to check that inside the loop.  This can wind up
3478          * being a negative value.
3479          */
3480         desc_len -= sizeof(struct scsi_sense_desc_header);
3481
3482         for (cur_pos = 0; cur_pos < desc_len;) {
3483                 struct scsi_sense_desc_header *header;
3484
3485                 header = (struct scsi_sense_desc_header *)
3486                         &sense->sense_desc[cur_pos];
3487
3488                 /*
3489                  * Check to make sure we have the entire descriptor.  We
3490                  * don't call iter_func() unless we do.
3491                  *
3492                  * Note that although cur_pos is at the beginning of the
3493                  * descriptor, desc_len already has the header length
3494                  * subtracted.  So the comparison of the length in the
3495                  * header (which does not include the header itself) to
3496                  * desc_len - cur_pos is correct.
3497                  */
3498                 if (header->length > (desc_len - cur_pos)) 
3499                         break;
3500
3501                 if (iter_func(sense, sense_len, header, arg) != 0)
3502                         break;
3503
3504                 cur_pos += sizeof(*header) + header->length;
3505         }
3506 }
3507
3508 struct scsi_find_desc_info {
3509         uint8_t desc_type;
3510         struct scsi_sense_desc_header *header;
3511 };
3512
3513 static int
3514 scsi_find_desc_func(struct scsi_sense_data_desc *sense, u_int sense_len,
3515                     struct scsi_sense_desc_header *header, void *arg)
3516 {
3517         struct scsi_find_desc_info *desc_info;
3518
3519         desc_info = (struct scsi_find_desc_info *)arg;
3520
3521         if (header->desc_type == desc_info->desc_type) {
3522                 desc_info->header = header;
3523
3524                 /* We found the descriptor, tell the iterator to stop. */
3525                 return (1);
3526         } else
3527                 return (0);
3528 }
3529
3530 /*
3531  * Given a descriptor type, return a pointer to it if it is in the sense
3532  * data and not truncated.  Avoiding truncating sense data will simplify
3533  * things significantly for the caller.
3534  */
3535 uint8_t *
3536 scsi_find_desc(struct scsi_sense_data_desc *sense, u_int sense_len,
3537                uint8_t desc_type)
3538 {
3539         struct scsi_find_desc_info desc_info;
3540
3541         desc_info.desc_type = desc_type;
3542         desc_info.header = NULL;
3543
3544         scsi_desc_iterate(sense, sense_len, scsi_find_desc_func, &desc_info);
3545
3546         return ((uint8_t *)desc_info.header);
3547 }
3548
3549 /*
3550  * Fill in SCSI sense data with the specified parameters.  This routine can
3551  * fill in either fixed or descriptor type sense data.
3552  */
3553 void
3554 scsi_set_sense_data_va(struct scsi_sense_data *sense_data,
3555                       scsi_sense_data_type sense_format, int current_error,
3556                       int sense_key, int asc, int ascq, va_list ap) 
3557 {
3558         int descriptor_sense;
3559         scsi_sense_elem_type elem_type;
3560
3561         /*
3562          * Determine whether to return fixed or descriptor format sense
3563          * data.  If the user specifies SSD_TYPE_NONE for some reason,
3564          * they'll just get fixed sense data.
3565          */
3566         if (sense_format == SSD_TYPE_DESC)
3567                 descriptor_sense = 1;
3568         else
3569                 descriptor_sense = 0;
3570
3571         /*
3572          * Zero the sense data, so that we don't pass back any garbage data
3573          * to the user.
3574          */
3575         memset(sense_data, 0, sizeof(*sense_data));
3576
3577         if (descriptor_sense != 0) {
3578                 struct scsi_sense_data_desc *sense;
3579
3580                 sense = (struct scsi_sense_data_desc *)sense_data;
3581                 /*
3582                  * The descriptor sense format eliminates the use of the
3583                  * valid bit.
3584                  */
3585                 if (current_error != 0)
3586                         sense->error_code = SSD_DESC_CURRENT_ERROR;
3587                 else
3588                         sense->error_code = SSD_DESC_DEFERRED_ERROR;
3589                 sense->sense_key = sense_key;
3590                 sense->add_sense_code = asc;
3591                 sense->add_sense_code_qual = ascq;
3592                 /*
3593                  * Start off with no extra length, since the above data
3594                  * fits in the standard descriptor sense information.
3595                  */
3596                 sense->extra_len = 0;
3597                 while ((elem_type = (scsi_sense_elem_type)va_arg(ap,
3598                         scsi_sense_elem_type)) != SSD_ELEM_NONE) {
3599                         int sense_len, len_to_copy;
3600                         uint8_t *data;
3601
3602                         if (elem_type >= SSD_ELEM_MAX) {
3603                                 printf("%s: invalid sense type %d\n", __func__,
3604                                        elem_type);
3605                                 break;
3606                         }
3607
3608                         sense_len = (int)va_arg(ap, int);
3609                         len_to_copy = MIN(sense_len, SSD_EXTRA_MAX -
3610                                           sense->extra_len);
3611                         data = (uint8_t *)va_arg(ap, uint8_t *);
3612
3613                         /*
3614                          * We've already consumed the arguments for this one.
3615                          */
3616                         if (elem_type == SSD_ELEM_SKIP)
3617                                 continue;
3618
3619                         switch (elem_type) {
3620                         case SSD_ELEM_DESC: {
3621
3622                                 /*
3623                                  * This is a straight descriptor.  All we
3624                                  * need to do is copy the data in.
3625                                  */
3626                                 bcopy(data, &sense->sense_desc[
3627                                       sense->extra_len], len_to_copy);
3628                                 sense->extra_len += len_to_copy;
3629                                 break;
3630                         }
3631                         case SSD_ELEM_SKS: {
3632                                 struct scsi_sense_sks sks;
3633
3634                                 bzero(&sks, sizeof(sks));
3635
3636                                 /*
3637                                  * This is already-formatted sense key
3638                                  * specific data.  We just need to fill out
3639                                  * the header and copy everything in.
3640                                  */
3641                                 bcopy(data, &sks.sense_key_spec,
3642                                       MIN(len_to_copy,
3643                                           sizeof(sks.sense_key_spec)));
3644
3645                                 sks.desc_type = SSD_DESC_SKS;
3646                                 sks.length = sizeof(sks) -
3647                                     offsetof(struct scsi_sense_sks, reserved1);
3648                                 bcopy(&sks,&sense->sense_desc[sense->extra_len],
3649                                       sizeof(sks));
3650                                 sense->extra_len += sizeof(sks);
3651                                 break;
3652                         }
3653                         case SSD_ELEM_INFO:
3654                         case SSD_ELEM_COMMAND: {
3655                                 struct scsi_sense_command cmd;
3656                                 struct scsi_sense_info info;
3657                                 uint8_t *data_dest;
3658                                 uint8_t *descriptor;
3659                                 int descriptor_size, i, copy_len;
3660
3661                                 bzero(&cmd, sizeof(cmd));
3662                                 bzero(&info, sizeof(info));
3663
3664                                 /*
3665                                  * Command or information data.  The
3666                                  * operate in pretty much the same way.
3667                                  */
3668                                 if (elem_type == SSD_ELEM_COMMAND) {
3669                                         len_to_copy = MIN(len_to_copy,
3670                                             sizeof(cmd.command_info));
3671                                         descriptor = (uint8_t *)&cmd;
3672                                         descriptor_size  = sizeof(cmd);
3673                                         data_dest =(uint8_t *)&cmd.command_info;
3674                                         cmd.desc_type = SSD_DESC_COMMAND;
3675                                         cmd.length = sizeof(cmd) -
3676                                             offsetof(struct scsi_sense_command,
3677                                                      reserved);
3678                                 } else {
3679                                         len_to_copy = MIN(len_to_copy,
3680                                             sizeof(info.info));
3681                                         descriptor = (uint8_t *)&info;
3682                                         descriptor_size = sizeof(cmd);
3683                                         data_dest = (uint8_t *)&info.info;
3684                                         info.desc_type = SSD_DESC_INFO;
3685                                         info.byte2 = SSD_INFO_VALID;
3686                                         info.length = sizeof(info) -
3687                                             offsetof(struct scsi_sense_info,
3688                                                      byte2);
3689                                 }
3690
3691                                 /*
3692                                  * Copy this in reverse because the spec
3693                                  * (SPC-4) says that when 4 byte quantities
3694                                  * are stored in this 8 byte field, the
3695                                  * first four bytes shall be 0.
3696                                  *
3697                                  * So we fill the bytes in from the end, and
3698                                  * if we have less than 8 bytes to copy,
3699                                  * the initial, most significant bytes will
3700                                  * be 0.
3701                                  */
3702                                 for (i = sense_len - 1; i >= 0 &&
3703                                      len_to_copy > 0; i--, len_to_copy--)
3704                                         data_dest[len_to_copy - 1] = data[i];
3705
3706                                 /*
3707                                  * This calculation looks much like the
3708                                  * initial len_to_copy calculation, but
3709                                  * we have to do it again here, because
3710                                  * we're looking at a larger amount that
3711                                  * may or may not fit.  It's not only the
3712                                  * data the user passed in, but also the
3713                                  * rest of the descriptor.
3714                                  */
3715                                 copy_len = MIN(descriptor_size,
3716                                     SSD_EXTRA_MAX - sense->extra_len);
3717                                 bcopy(descriptor, &sense->sense_desc[
3718                                       sense->extra_len], copy_len);
3719                                 sense->extra_len += copy_len;
3720                                 break;
3721                         }
3722                         case SSD_ELEM_FRU: {
3723                                 struct scsi_sense_fru fru;
3724                                 int copy_len;
3725
3726                                 bzero(&fru, sizeof(fru));
3727
3728                                 fru.desc_type = SSD_DESC_FRU;
3729                                 fru.length = sizeof(fru) -
3730                                     offsetof(struct scsi_sense_fru, reserved);
3731                                 fru.fru = *data;
3732
3733                                 copy_len = MIN(sizeof(fru), SSD_EXTRA_MAX -
3734                                                sense->extra_len);
3735                                 bcopy(&fru, &sense->sense_desc[
3736                                       sense->extra_len], copy_len);
3737                                 sense->extra_len += copy_len;
3738                                 break;
3739                         }
3740                         case SSD_ELEM_STREAM: {
3741                                 struct scsi_sense_stream stream_sense;
3742                                 int copy_len;
3743
3744                                 bzero(&stream_sense, sizeof(stream_sense));
3745                                 stream_sense.desc_type = SSD_DESC_STREAM;
3746                                 stream_sense.length = sizeof(stream_sense) -
3747                                    offsetof(struct scsi_sense_stream, reserved);
3748                                 stream_sense.byte3 = *data;
3749
3750                                 copy_len = MIN(sizeof(stream_sense),
3751                                     SSD_EXTRA_MAX - sense->extra_len);
3752                                 bcopy(&stream_sense, &sense->sense_desc[
3753                                       sense->extra_len], copy_len);
3754                                 sense->extra_len += copy_len;
3755                                 break;
3756                         }
3757                         default:
3758                                 /*
3759                                  * We shouldn't get here, but if we do, do
3760                                  * nothing.  We've already consumed the
3761                                  * arguments above.
3762                                  */
3763                                 break;
3764                         }
3765                 }
3766         } else {
3767                 struct scsi_sense_data_fixed *sense;
3768
3769                 sense = (struct scsi_sense_data_fixed *)sense_data;
3770
3771                 if (current_error != 0)
3772                         sense->error_code = SSD_CURRENT_ERROR;
3773                 else
3774                         sense->error_code = SSD_DEFERRED_ERROR;
3775
3776                 sense->flags = sense_key;
3777                 sense->add_sense_code = asc;
3778                 sense->add_sense_code_qual = ascq;
3779                 /*
3780                  * We've set the ASC and ASCQ, so we have 6 more bytes of
3781                  * valid data.  If we wind up setting any of the other
3782                  * fields, we'll bump this to 10 extra bytes.
3783                  */
3784                 sense->extra_len = 6;
3785
3786                 while ((elem_type = (scsi_sense_elem_type)va_arg(ap,
3787                         scsi_sense_elem_type)) != SSD_ELEM_NONE) {
3788                         int sense_len, len_to_copy;
3789                         uint8_t *data;
3790
3791                         if (elem_type >= SSD_ELEM_MAX) {
3792                                 printf("%s: invalid sense type %d\n", __func__,
3793                                        elem_type);
3794                                 break;
3795                         }
3796                         /*
3797                          * If we get in here, just bump the extra length to
3798                          * 10 bytes.  That will encompass anything we're
3799                          * going to set here.
3800                          */
3801                         sense->extra_len = 10;
3802                         sense_len = (int)va_arg(ap, int);
3803                         len_to_copy = MIN(sense_len, SSD_EXTRA_MAX -
3804                                           sense->extra_len);
3805                         data = (uint8_t *)va_arg(ap, uint8_t *);
3806
3807                         switch (elem_type) {
3808                         case SSD_ELEM_SKS:
3809                                 /*
3810                                  * The user passed in pre-formatted sense
3811                                  * key specific data.
3812                                  */
3813                                 bcopy(data, &sense->sense_key_spec[0],
3814                                       MIN(sizeof(sense->sense_key_spec),
3815                                       sense_len));
3816                                 break;
3817                         case SSD_ELEM_INFO:
3818                         case SSD_ELEM_COMMAND: {
3819                                 uint8_t *data_dest;
3820                                 int i;
3821
3822                                 if (elem_type == SSD_ELEM_COMMAND)
3823                                         data_dest = &sense->cmd_spec_info[0];
3824                                 else {
3825                                         data_dest = &sense->info[0];
3826                                         /*
3827                                          * We're setting the info field, so
3828                                          * set the valid bit.
3829                                          */
3830                                         sense->error_code |= SSD_ERRCODE_VALID;
3831                                 }
3832
3833                                 /*
3834                                  * Copy this in reverse so that if we have
3835                                  * less than 4 bytes to fill, the least
3836                                  * significant bytes will be at the end.
3837                                  * If we have more than 4 bytes, only the
3838                                  * least significant bytes will be included.
3839                                  */
3840                                 for (i = sense_len - 1; i >= 0 &&
3841                                      len_to_copy > 0; i--, len_to_copy--)
3842                                         data_dest[len_to_copy - 1] = data[i];
3843
3844                                 break;
3845                         }
3846                         case SSD_ELEM_FRU:
3847                                 sense->fru = *data;
3848                                 break;
3849                         case SSD_ELEM_STREAM:
3850                                 sense->flags |= *data;
3851                                 break;
3852                         case SSD_ELEM_DESC:
3853                         default:
3854
3855                                 /*
3856                                  * If the user passes in descriptor sense,
3857                                  * we can't handle that in fixed format.
3858                                  * So just skip it, and any unknown argument
3859                                  * types.
3860                                  */
3861                                 break;
3862                         }
3863                 }
3864         }
3865 }
3866
3867 void
3868 scsi_set_sense_data(struct scsi_sense_data *sense_data, 
3869                     scsi_sense_data_type sense_format, int current_error,
3870                     int sense_key, int asc, int ascq, ...) 
3871 {
3872         va_list ap;
3873
3874         va_start(ap, ascq);
3875         scsi_set_sense_data_va(sense_data, sense_format, current_error,
3876                                sense_key, asc, ascq, ap);
3877         va_end(ap);
3878 }
3879
3880 /*
3881  * Get sense information for three similar sense data types.
3882  */
3883 int
3884 scsi_get_sense_info(struct scsi_sense_data *sense_data, u_int sense_len,
3885                     uint8_t info_type, uint64_t *info, int64_t *signed_info)
3886 {
3887         scsi_sense_data_type sense_type;
3888
3889         if (sense_len == 0)
3890                 goto bailout;
3891
3892         sense_type = scsi_sense_type(sense_data);
3893
3894         switch (sense_type) {
3895         case SSD_TYPE_DESC: {
3896                 struct scsi_sense_data_desc *sense;
3897                 uint8_t *desc;
3898
3899                 sense = (struct scsi_sense_data_desc *)sense_data;
3900
3901                 desc = scsi_find_desc(sense, sense_len, info_type);
3902                 if (desc == NULL)
3903                         goto bailout;
3904
3905                 switch (info_type) {
3906                 case SSD_DESC_INFO: {
3907                         struct scsi_sense_info *info_desc;
3908
3909                         info_desc = (struct scsi_sense_info *)desc;
3910                         *info = scsi_8btou64(info_desc->info);
3911                         if (signed_info != NULL)
3912                                 *signed_info = *info;
3913                         break;
3914                 }
3915                 case SSD_DESC_COMMAND: {
3916                         struct scsi_sense_command *cmd_desc;
3917
3918                         cmd_desc = (struct scsi_sense_command *)desc;
3919
3920                         *info = scsi_8btou64(cmd_desc->command_info);
3921                         if (signed_info != NULL)
3922                                 *signed_info = *info;
3923                         break;
3924                 }
3925                 case SSD_DESC_FRU: {
3926                         struct scsi_sense_fru *fru_desc;
3927
3928                         fru_desc = (struct scsi_sense_fru *)desc;
3929
3930                         *info = fru_desc->fru;
3931                         if (signed_info != NULL)
3932                                 *signed_info = (int8_t)fru_desc->fru;
3933                         break;
3934                 }
3935                 default:
3936                         goto bailout;
3937                         break;
3938                 }
3939                 break;
3940         }
3941         case SSD_TYPE_FIXED: {
3942                 struct scsi_sense_data_fixed *sense;
3943
3944                 sense = (struct scsi_sense_data_fixed *)sense_data;
3945
3946                 switch (info_type) {
3947                 case SSD_DESC_INFO: {
3948                         uint32_t info_val;
3949
3950                         if ((sense->error_code & SSD_ERRCODE_VALID) == 0)
3951                                 goto bailout;
3952
3953                         if (SSD_FIXED_IS_PRESENT(sense, sense_len, info) == 0)
3954                                 goto bailout;
3955
3956                         info_val = scsi_4btoul(sense->info);
3957
3958                         *info = info_val;
3959                         if (signed_info != NULL)
3960                                 *signed_info = (int32_t)info_val;
3961                         break;
3962                 }
3963                 case SSD_DESC_COMMAND: {
3964                         uint32_t cmd_val;
3965
3966                         if ((SSD_FIXED_IS_PRESENT(sense, sense_len,
3967                              cmd_spec_info) == 0)
3968                          || (SSD_FIXED_IS_FILLED(sense, cmd_spec_info) == 0)) 
3969                                 goto bailout;
3970
3971                         cmd_val = scsi_4btoul(sense->cmd_spec_info);
3972                         if (cmd_val == 0)
3973                                 goto bailout;
3974
3975                         *info = cmd_val;
3976                         if (signed_info != NULL)
3977                                 *signed_info = (int32_t)cmd_val;
3978                         break;
3979                 }
3980                 case SSD_DESC_FRU:
3981                         if ((SSD_FIXED_IS_PRESENT(sense, sense_len, fru) == 0)
3982                          || (SSD_FIXED_IS_FILLED(sense, fru) == 0))
3983                                 goto bailout;
3984
3985                         if (sense->fru == 0)
3986                                 goto bailout;
3987
3988                         *info = sense->fru;
3989                         if (signed_info != NULL)
3990                                 *signed_info = (int8_t)sense->fru;
3991                         break;
3992                 default:
3993                         goto bailout;
3994                         break;
3995                 }
3996                 break;
3997         }
3998         default: 
3999                 goto bailout;
4000                 break;
4001         }
4002
4003         return (0);
4004 bailout:
4005         return (1);
4006 }
4007
4008 int
4009 scsi_get_sks(struct scsi_sense_data *sense_data, u_int sense_len, uint8_t *sks)
4010 {
4011         scsi_sense_data_type sense_type;
4012
4013         if (sense_len == 0)
4014                 goto bailout;
4015
4016         sense_type = scsi_sense_type(sense_data);
4017
4018         switch (sense_type) {
4019         case SSD_TYPE_DESC: {
4020                 struct scsi_sense_data_desc *sense;
4021                 struct scsi_sense_sks *desc;
4022
4023                 sense = (struct scsi_sense_data_desc *)sense_data;
4024
4025                 desc = (struct scsi_sense_sks *)scsi_find_desc(sense, sense_len,
4026                                                                SSD_DESC_SKS);
4027                 if (desc == NULL)
4028                         goto bailout;
4029
4030                 /*
4031                  * No need to check the SKS valid bit for descriptor sense.
4032                  * If the descriptor is present, it is valid.
4033                  */
4034                 bcopy(desc->sense_key_spec, sks, sizeof(desc->sense_key_spec));
4035                 break;
4036         }
4037         case SSD_TYPE_FIXED: {
4038                 struct scsi_sense_data_fixed *sense;
4039
4040                 sense = (struct scsi_sense_data_fixed *)sense_data;
4041
4042                 if ((SSD_FIXED_IS_PRESENT(sense, sense_len, sense_key_spec)== 0)
4043                  || (SSD_FIXED_IS_FILLED(sense, sense_key_spec) == 0))
4044                         goto bailout;
4045
4046                 if ((sense->sense_key_spec[0] & SSD_SCS_VALID) == 0)
4047                         goto bailout;
4048
4049                 bcopy(sense->sense_key_spec, sks,sizeof(sense->sense_key_spec));
4050                 break;
4051         }
4052         default:
4053                 goto bailout;
4054                 break;
4055         }
4056         return (0);
4057 bailout:
4058         return (1);
4059 }
4060
4061 /*
4062  * Provide a common interface for fixed and descriptor sense to detect
4063  * whether we have block-specific sense information.  It is clear by the
4064  * presence of the block descriptor in descriptor mode, but we have to
4065  * infer from the inquiry data and ILI bit in fixed mode.
4066  */
4067 int
4068 scsi_get_block_info(struct scsi_sense_data *sense_data, u_int sense_len,
4069                     struct scsi_inquiry_data *inq_data, uint8_t *block_bits)
4070 {
4071         scsi_sense_data_type sense_type;
4072
4073         if (inq_data != NULL) {
4074                 switch (SID_TYPE(inq_data)) {
4075                 case T_DIRECT:
4076                 case T_RBC:
4077                         break;
4078                 default:
4079                         goto bailout;
4080                         break;
4081                 }
4082         }
4083
4084         sense_type = scsi_sense_type(sense_data);
4085
4086         switch (sense_type) {
4087         case SSD_TYPE_DESC: {
4088                 struct scsi_sense_data_desc *sense;
4089                 struct scsi_sense_block *block;
4090
4091                 sense = (struct scsi_sense_data_desc *)sense_data;
4092
4093                 block = (struct scsi_sense_block *)scsi_find_desc(sense,
4094                     sense_len, SSD_DESC_BLOCK);
4095                 if (block == NULL)
4096                         goto bailout;
4097
4098                 *block_bits = block->byte3;
4099                 break;
4100         }
4101         case SSD_TYPE_FIXED: {
4102                 struct scsi_sense_data_fixed *sense;
4103
4104                 sense = (struct scsi_sense_data_fixed *)sense_data;
4105
4106                 if (SSD_FIXED_IS_PRESENT(sense, sense_len, flags) == 0)
4107                         goto bailout;
4108
4109                 if ((sense->flags & SSD_ILI) == 0)
4110                         goto bailout;
4111
4112                 *block_bits = sense->flags & SSD_ILI;
4113                 break;
4114         }
4115         default:
4116                 goto bailout;
4117                 break;
4118         }
4119         return (0);
4120 bailout:
4121         return (1);
4122 }
4123
4124 int
4125 scsi_get_stream_info(struct scsi_sense_data *sense_data, u_int sense_len,
4126                      struct scsi_inquiry_data *inq_data, uint8_t *stream_bits)
4127 {
4128         scsi_sense_data_type sense_type;
4129
4130         if (inq_data != NULL) {
4131                 switch (SID_TYPE(inq_data)) {
4132                 case T_SEQUENTIAL:
4133                         break;
4134                 default:
4135                         goto bailout;
4136                         break;
4137                 }
4138         }
4139
4140         sense_type = scsi_sense_type(sense_data);
4141
4142         switch (sense_type) {
4143         case SSD_TYPE_DESC: {
4144                 struct scsi_sense_data_desc *sense;
4145                 struct scsi_sense_stream *stream;
4146
4147                 sense = (struct scsi_sense_data_desc *)sense_data;
4148
4149                 stream = (struct scsi_sense_stream *)scsi_find_desc(sense,
4150                     sense_len, SSD_DESC_STREAM);
4151                 if (stream == NULL)
4152                         goto bailout;
4153
4154                 *stream_bits = stream->byte3;
4155                 break;
4156         }
4157         case SSD_TYPE_FIXED: {
4158                 struct scsi_sense_data_fixed *sense;
4159
4160                 sense = (struct scsi_sense_data_fixed *)sense_data;
4161
4162                 if (SSD_FIXED_IS_PRESENT(sense, sense_len, flags) == 0)
4163                         goto bailout;
4164
4165                 if ((sense->flags & (SSD_ILI|SSD_EOM|SSD_FILEMARK)) == 0)
4166                         goto bailout;
4167
4168                 *stream_bits = sense->flags & (SSD_ILI|SSD_EOM|SSD_FILEMARK);
4169                 break;
4170         }
4171         default:
4172                 goto bailout;
4173                 break;
4174         }
4175         return (0);
4176 bailout:
4177         return (1);
4178 }
4179
4180 void
4181 scsi_info_sbuf(struct sbuf *sb, uint8_t *cdb, int cdb_len,
4182                struct scsi_inquiry_data *inq_data, uint64_t info)
4183 {
4184         sbuf_printf(sb, "Info: %#jx", info);
4185 }
4186
4187 void
4188 scsi_command_sbuf(struct sbuf *sb, uint8_t *cdb, int cdb_len,
4189                   struct scsi_inquiry_data *inq_data, uint64_t csi)
4190 {
4191         sbuf_printf(sb, "Command Specific Info: %#jx", csi);
4192 }
4193
4194
4195 void
4196 scsi_progress_sbuf(struct sbuf *sb, uint16_t progress)
4197 {
4198         sbuf_printf(sb, "Progress: %d%% (%d/%d) complete",
4199                     (progress * 100) / SSD_SKS_PROGRESS_DENOM,
4200                     progress, SSD_SKS_PROGRESS_DENOM);
4201 }
4202
4203 /*
4204  * Returns 1 for failure (i.e. SKS isn't valid) and 0 for success.
4205  */
4206 int
4207 scsi_sks_sbuf(struct sbuf *sb, int sense_key, uint8_t *sks)
4208 {
4209         if ((sks[0] & SSD_SKS_VALID) == 0)
4210                 return (1);
4211
4212         switch (sense_key) {
4213         case SSD_KEY_ILLEGAL_REQUEST: {
4214                 struct scsi_sense_sks_field *field;
4215                 int bad_command;
4216                 char tmpstr[40];
4217
4218                 /*Field Pointer*/
4219                 field = (struct scsi_sense_sks_field *)sks;
4220
4221                 if (field->byte0 & SSD_SKS_FIELD_CMD)
4222                         bad_command = 1;
4223                 else
4224                         bad_command = 0;
4225
4226                 tmpstr[0] = '\0';
4227
4228                 /* Bit pointer is valid */
4229                 if (field->byte0 & SSD_SKS_BPV)
4230                         snprintf(tmpstr, sizeof(tmpstr), "bit %d ",
4231                                  field->byte0 & SSD_SKS_BIT_VALUE);
4232
4233                 sbuf_printf(sb, "%s byte %d %sis invalid",
4234                             bad_command ? "Command" : "Data",
4235                             scsi_2btoul(field->field), tmpstr);
4236                 break;
4237         }
4238         case SSD_KEY_UNIT_ATTENTION: {
4239                 struct scsi_sense_sks_overflow *overflow;
4240
4241                 overflow = (struct scsi_sense_sks_overflow *)sks;
4242
4243                 /*UA Condition Queue Overflow*/
4244                 sbuf_printf(sb, "Unit Attention Condition Queue %s",
4245                             (overflow->byte0 & SSD_SKS_OVERFLOW_SET) ?
4246                             "Overflowed" : "Did Not Overflow??");
4247                 break;
4248         }
4249         case SSD_KEY_RECOVERED_ERROR:
4250         case SSD_KEY_HARDWARE_ERROR:
4251         case SSD_KEY_MEDIUM_ERROR: {
4252                 struct scsi_sense_sks_retry *retry;
4253
4254                 /*Actual Retry Count*/
4255                 retry = (struct scsi_sense_sks_retry *)sks;
4256
4257                 sbuf_printf(sb, "Actual Retry Count: %d",
4258                             scsi_2btoul(retry->actual_retry_count));
4259                 break;
4260         }
4261         case SSD_KEY_NO_SENSE:
4262         case SSD_KEY_NOT_READY: {
4263                 struct scsi_sense_sks_progress *progress;
4264                 int progress_val;
4265
4266                 /*Progress Indication*/
4267                 progress = (struct scsi_sense_sks_progress *)sks;
4268                 progress_val = scsi_2btoul(progress->progress);
4269
4270                 scsi_progress_sbuf(sb, progress_val);
4271                 break;
4272         }
4273         case SSD_KEY_COPY_ABORTED: {
4274                 struct scsi_sense_sks_segment *segment;
4275                 char tmpstr[40];
4276
4277                 /*Segment Pointer*/
4278                 segment = (struct scsi_sense_sks_segment *)sks;
4279
4280                 tmpstr[0] = '\0';
4281
4282                 if (segment->byte0 & SSD_SKS_SEGMENT_BPV)
4283                         snprintf(tmpstr, sizeof(tmpstr), "bit %d ",
4284                                  segment->byte0 & SSD_SKS_SEGMENT_BITPTR);
4285
4286                 sbuf_printf(sb, "%s byte %d %sis invalid", (segment->byte0 &
4287                             SSD_SKS_SEGMENT_SD) ? "Segment" : "Data",
4288                             scsi_2btoul(segment->field), tmpstr);
4289                 break;
4290         }
4291         default:
4292                 sbuf_printf(sb, "Sense Key Specific: %#x,%#x", sks[0],
4293                             scsi_2btoul(&sks[1]));
4294                 break;
4295         }
4296
4297         return (0);
4298 }
4299
4300 void
4301 scsi_fru_sbuf(struct sbuf *sb, uint64_t fru)
4302 {
4303         sbuf_printf(sb, "Field Replaceable Unit: %d", (int)fru);
4304 }
4305
4306 void
4307 scsi_stream_sbuf(struct sbuf *sb, uint8_t stream_bits, uint64_t info)
4308 {
4309         int need_comma;
4310
4311         need_comma = 0;
4312         /*
4313          * XXX KDM this needs more descriptive decoding.
4314          */
4315         if (stream_bits & SSD_DESC_STREAM_FM) {
4316                 sbuf_printf(sb, "Filemark");
4317                 need_comma = 1;
4318         }
4319
4320         if (stream_bits & SSD_DESC_STREAM_EOM) {
4321                 sbuf_printf(sb, "%sEOM", (need_comma) ? "," : "");
4322                 need_comma = 1;
4323         }
4324
4325         if (stream_bits & SSD_DESC_STREAM_ILI)
4326                 sbuf_printf(sb, "%sILI", (need_comma) ? "," : "");
4327
4328         sbuf_printf(sb, ": Info: %#jx", (uintmax_t) info);
4329 }
4330
4331 void
4332 scsi_block_sbuf(struct sbuf *sb, uint8_t block_bits, uint64_t info)
4333 {
4334         if (block_bits & SSD_DESC_BLOCK_ILI)
4335                 sbuf_printf(sb, "ILI: residue %#jx", (uintmax_t) info);
4336 }
4337
4338 void
4339 scsi_sense_info_sbuf(struct sbuf *sb, struct scsi_sense_data *sense,
4340                      u_int sense_len, uint8_t *cdb, int cdb_len,
4341                      struct scsi_inquiry_data *inq_data,
4342                      struct scsi_sense_desc_header *header)
4343 {
4344         struct scsi_sense_info *info;
4345
4346         info = (struct scsi_sense_info *)header;
4347
4348         scsi_info_sbuf(sb, cdb, cdb_len, inq_data, scsi_8btou64(info->info));
4349 }
4350
4351 void
4352 scsi_sense_command_sbuf(struct sbuf *sb, struct scsi_sense_data *sense,
4353                         u_int sense_len, uint8_t *cdb, int cdb_len,
4354                         struct scsi_inquiry_data *inq_data,
4355                         struct scsi_sense_desc_header *header)
4356 {
4357         struct scsi_sense_command *command;
4358
4359         command = (struct scsi_sense_command *)header;
4360
4361         scsi_command_sbuf(sb, cdb, cdb_len, inq_data,
4362                           scsi_8btou64(command->command_info));
4363 }
4364
4365 void
4366 scsi_sense_sks_sbuf(struct sbuf *sb, struct scsi_sense_data *sense,
4367                     u_int sense_len, uint8_t *cdb, int cdb_len,
4368                     struct scsi_inquiry_data *inq_data,
4369                     struct scsi_sense_desc_header *header)
4370 {
4371         struct scsi_sense_sks *sks;
4372         int error_code, sense_key, asc, ascq;
4373
4374         sks = (struct scsi_sense_sks *)header;
4375
4376         scsi_extract_sense_len(sense, sense_len, &error_code, &sense_key,
4377                                &asc, &ascq, /*show_errors*/ 1);
4378
4379         scsi_sks_sbuf(sb, sense_key, sks->sense_key_spec);
4380 }
4381
4382 void
4383 scsi_sense_fru_sbuf(struct sbuf *sb, struct scsi_sense_data *sense,
4384                     u_int sense_len, uint8_t *cdb, int cdb_len,
4385                     struct scsi_inquiry_data *inq_data,
4386                     struct scsi_sense_desc_header *header)
4387 {
4388         struct scsi_sense_fru *fru;
4389
4390         fru = (struct scsi_sense_fru *)header;
4391
4392         scsi_fru_sbuf(sb, (uint64_t)fru->fru);
4393 }
4394
4395 void
4396 scsi_sense_stream_sbuf(struct sbuf *sb, struct scsi_sense_data *sense,
4397                        u_int sense_len, uint8_t *cdb, int cdb_len,
4398                        struct scsi_inquiry_data *inq_data,
4399                        struct scsi_sense_desc_header *header)
4400 {
4401         struct scsi_sense_stream *stream;
4402         uint64_t info;
4403
4404         stream = (struct scsi_sense_stream *)header;
4405         info = 0;
4406
4407         scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO, &info, NULL);
4408
4409         scsi_stream_sbuf(sb, stream->byte3, info);
4410 }
4411
4412 void
4413 scsi_sense_block_sbuf(struct sbuf *sb, struct scsi_sense_data *sense,
4414                       u_int sense_len, uint8_t *cdb, int cdb_len,
4415                       struct scsi_inquiry_data *inq_data,
4416                       struct scsi_sense_desc_header *header)
4417 {
4418         struct scsi_sense_block *block;
4419         uint64_t info;
4420
4421         block = (struct scsi_sense_block *)header;
4422         info = 0;
4423
4424         scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO, &info, NULL);
4425
4426         scsi_block_sbuf(sb, block->byte3, info);
4427 }
4428
4429 void
4430 scsi_sense_progress_sbuf(struct sbuf *sb, struct scsi_sense_data *sense,
4431                          u_int sense_len, uint8_t *cdb, int cdb_len,
4432                          struct scsi_inquiry_data *inq_data,
4433                          struct scsi_sense_desc_header *header)
4434 {
4435         struct scsi_sense_progress *progress;
4436         const char *sense_key_desc;
4437         const char *asc_desc;
4438         int progress_val;
4439
4440         progress = (struct scsi_sense_progress *)header;
4441
4442         /*
4443          * Get descriptions for the sense key, ASC, and ASCQ in the
4444          * progress descriptor.  These could be different than the values
4445          * in the overall sense data.
4446          */
4447         scsi_sense_desc(progress->sense_key, progress->add_sense_code,
4448                         progress->add_sense_code_qual, inq_data,
4449                         &sense_key_desc, &asc_desc);
4450
4451         progress_val = scsi_2btoul(progress->progress);
4452
4453         /*
4454          * The progress indicator is for the operation described by the
4455          * sense key, ASC, and ASCQ in the descriptor.
4456          */
4457         sbuf_cat(sb, sense_key_desc);
4458         sbuf_printf(sb, " asc:%x,%x (%s): ", progress->add_sense_code, 
4459                     progress->add_sense_code_qual, asc_desc);
4460         scsi_progress_sbuf(sb, progress_val);
4461 }
4462
4463 /*
4464  * Generic sense descriptor printing routine.  This is used when we have
4465  * not yet implemented a specific printing routine for this descriptor.
4466  */
4467 void
4468 scsi_sense_generic_sbuf(struct sbuf *sb, struct scsi_sense_data *sense,
4469                         u_int sense_len, uint8_t *cdb, int cdb_len,
4470                         struct scsi_inquiry_data *inq_data,
4471                         struct scsi_sense_desc_header *header)
4472 {
4473         int i;
4474         uint8_t *buf_ptr;
4475
4476         sbuf_printf(sb, "Descriptor %#x:", header->desc_type);
4477
4478         buf_ptr = (uint8_t *)&header[1];
4479
4480         for (i = 0; i < header->length; i++, buf_ptr++)
4481                 sbuf_printf(sb, " %02x", *buf_ptr);
4482 }
4483
4484 /*
4485  * Keep this list in numeric order.  This speeds the array traversal.
4486  */
4487 struct scsi_sense_desc_printer {
4488         uint8_t desc_type;
4489         /*
4490          * The function arguments here are the superset of what is needed
4491          * to print out various different descriptors.  Command and
4492          * information descriptors need inquiry data and command type.
4493          * Sense key specific descriptors need the sense key.
4494          *
4495          * The sense, cdb, and inquiry data arguments may be NULL, but the
4496          * information printed may not be fully decoded as a result.
4497          */
4498         void (*print_func)(struct sbuf *sb, struct scsi_sense_data *sense,
4499                            u_int sense_len, uint8_t *cdb, int cdb_len,
4500                            struct scsi_inquiry_data *inq_data,
4501                            struct scsi_sense_desc_header *header);
4502 } scsi_sense_printers[] = {
4503         {SSD_DESC_INFO, scsi_sense_info_sbuf},
4504         {SSD_DESC_COMMAND, scsi_sense_command_sbuf},
4505         {SSD_DESC_SKS, scsi_sense_sks_sbuf},
4506         {SSD_DESC_FRU, scsi_sense_fru_sbuf},
4507         {SSD_DESC_STREAM, scsi_sense_stream_sbuf},
4508         {SSD_DESC_BLOCK, scsi_sense_block_sbuf},
4509         {SSD_DESC_PROGRESS, scsi_sense_progress_sbuf}
4510 };
4511
4512 void
4513 scsi_sense_desc_sbuf(struct sbuf *sb, struct scsi_sense_data *sense,
4514                      u_int sense_len, uint8_t *cdb, int cdb_len,
4515                      struct scsi_inquiry_data *inq_data,
4516                      struct scsi_sense_desc_header *header)
4517 {
4518         int i;
4519
4520         for (i = 0; i < (sizeof(scsi_sense_printers) /
4521              sizeof(scsi_sense_printers[0])); i++) {
4522                 struct scsi_sense_desc_printer *printer;
4523
4524                 printer = &scsi_sense_printers[i];
4525
4526                 /*
4527                  * The list is sorted, so quit if we've passed our
4528                  * descriptor number.
4529                  */
4530                 if (printer->desc_type > header->desc_type)
4531                         break;
4532
4533                 if (printer->desc_type != header->desc_type)
4534                         continue;
4535
4536                 printer->print_func(sb, sense, sense_len, cdb, cdb_len,
4537                                     inq_data, header);
4538
4539                 return;
4540         }
4541
4542         /*
4543          * No specific printing routine, so use the generic routine.
4544          */
4545         scsi_sense_generic_sbuf(sb, sense, sense_len, cdb, cdb_len,
4546                                 inq_data, header);
4547 }
4548
4549 scsi_sense_data_type
4550 scsi_sense_type(struct scsi_sense_data *sense_data)
4551 {
4552         switch (sense_data->error_code & SSD_ERRCODE) {
4553         case SSD_DESC_CURRENT_ERROR:
4554         case SSD_DESC_DEFERRED_ERROR:
4555                 return (SSD_TYPE_DESC);
4556                 break;
4557         case SSD_CURRENT_ERROR:
4558         case SSD_DEFERRED_ERROR:
4559                 return (SSD_TYPE_FIXED);
4560                 break;
4561         default:
4562                 break;
4563         }
4564
4565         return (SSD_TYPE_NONE);
4566 }
4567
4568 struct scsi_print_sense_info {
4569         struct sbuf *sb;
4570         char *path_str;
4571         uint8_t *cdb;
4572         int cdb_len;
4573         struct scsi_inquiry_data *inq_data;
4574 };
4575
4576 static int
4577 scsi_print_desc_func(struct scsi_sense_data_desc *sense, u_int sense_len,
4578                      struct scsi_sense_desc_header *header, void *arg)
4579 {
4580         struct scsi_print_sense_info *print_info;
4581
4582         print_info = (struct scsi_print_sense_info *)arg;
4583
4584         switch (header->desc_type) {
4585         case SSD_DESC_INFO:
4586         case SSD_DESC_FRU:
4587         case SSD_DESC_COMMAND:
4588         case SSD_DESC_SKS:
4589         case SSD_DESC_BLOCK:
4590         case SSD_DESC_STREAM:
4591                 /*
4592                  * We have already printed these descriptors, if they are
4593                  * present.
4594                  */
4595                 break;
4596         default: {
4597                 sbuf_printf(print_info->sb, "%s", print_info->path_str);
4598                 scsi_sense_desc_sbuf(print_info->sb,
4599                                      (struct scsi_sense_data *)sense, sense_len,
4600                                      print_info->cdb, print_info->cdb_len,
4601                                      print_info->inq_data, header);
4602                 sbuf_printf(print_info->sb, "\n");
4603                 break;
4604         }
4605         }
4606
4607         /*
4608          * Tell the iterator that we want to see more descriptors if they
4609          * are present.
4610          */
4611         return (0);
4612 }
4613
4614 void
4615 scsi_sense_only_sbuf(struct scsi_sense_data *sense, u_int sense_len,
4616                      struct sbuf *sb, char *path_str,
4617                      struct scsi_inquiry_data *inq_data, uint8_t *cdb,
4618                      int cdb_len)
4619 {
4620         int error_code, sense_key, asc, ascq;
4621
4622         sbuf_cat(sb, path_str);
4623
4624         scsi_extract_sense_len(sense, sense_len, &error_code, &sense_key,
4625                                &asc, &ascq, /*show_errors*/ 1);
4626
4627         sbuf_printf(sb, "SCSI sense: ");
4628         switch (error_code) {
4629         case SSD_DEFERRED_ERROR:
4630         case SSD_DESC_DEFERRED_ERROR:
4631                 sbuf_printf(sb, "Deferred error: ");
4632
4633                 /* FALLTHROUGH */
4634         case SSD_CURRENT_ERROR:
4635         case SSD_DESC_CURRENT_ERROR:
4636         {
4637                 struct scsi_sense_data_desc *desc_sense;
4638                 struct scsi_print_sense_info print_info;
4639                 const char *sense_key_desc;
4640                 const char *asc_desc;
4641                 uint8_t sks[3];
4642                 uint64_t val;
4643                 int info_valid;
4644
4645                 /*
4646                  * Get descriptions for the sense key, ASC, and ASCQ.  If
4647                  * these aren't present in the sense data (i.e. the sense
4648                  * data isn't long enough), the -1 values that
4649                  * scsi_extract_sense_len() returns will yield default
4650                  * or error descriptions.
4651                  */
4652                 scsi_sense_desc(sense_key, asc, ascq, inq_data,
4653                                 &sense_key_desc, &asc_desc);
4654
4655                 /*
4656                  * We first print the sense key and ASC/ASCQ.
4657                  */
4658                 sbuf_cat(sb, sense_key_desc);
4659                 sbuf_printf(sb, " asc:%x,%x (%s)\n", asc, ascq, asc_desc);
4660
4661                 /*
4662                  * Get the info field if it is valid.
4663                  */
4664                 if (scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO,
4665                                         &val, NULL) == 0)
4666                         info_valid = 1;
4667                 else
4668                         info_valid = 0;
4669
4670                 if (info_valid != 0) {
4671                         uint8_t bits;
4672
4673                         /*
4674                          * Determine whether we have any block or stream
4675                          * device-specific information.
4676                          */
4677                         if (scsi_get_block_info(sense, sense_len, inq_data,
4678                                                 &bits) == 0) {
4679                                 sbuf_cat(sb, path_str);
4680                                 scsi_block_sbuf(sb, bits, val);
4681                                 sbuf_printf(sb, "\n");
4682                         } else if (scsi_get_stream_info(sense, sense_len,
4683                                                         inq_data, &bits) == 0) {
4684                                 sbuf_cat(sb, path_str);
4685                                 scsi_stream_sbuf(sb, bits, val);
4686                                 sbuf_printf(sb, "\n");
4687                         } else if (val != 0) {
4688                                 /*
4689                                  * The information field can be valid but 0.
4690                                  * If the block or stream bits aren't set,
4691                                  * and this is 0, it isn't terribly useful
4692                                  * to print it out.
4693                                  */
4694                                 sbuf_cat(sb, path_str);
4695                                 scsi_info_sbuf(sb, cdb, cdb_len, inq_data, val);
4696                                 sbuf_printf(sb, "\n");
4697                         }
4698                 }
4699
4700                 /* 
4701                  * Print the FRU.
4702                  */
4703                 if (scsi_get_sense_info(sense, sense_len, SSD_DESC_FRU,
4704                                         &val, NULL) == 0) {
4705                         sbuf_cat(sb, path_str);
4706                         scsi_fru_sbuf(sb, val);
4707                         sbuf_printf(sb, "\n");
4708                 }
4709
4710                 /*
4711                  * Print any command-specific information.
4712                  */
4713                 if (scsi_get_sense_info(sense, sense_len, SSD_DESC_COMMAND,
4714                                         &val, NULL) == 0) {
4715                         sbuf_cat(sb, path_str);
4716                         scsi_command_sbuf(sb, cdb, cdb_len, inq_data, val);
4717                         sbuf_printf(sb, "\n");
4718                 }
4719
4720                 /*
4721                  * Print out any sense-key-specific information.
4722                  */
4723                 if (scsi_get_sks(sense, sense_len, sks) == 0) {
4724                         sbuf_cat(sb, path_str);
4725                         scsi_sks_sbuf(sb, sense_key, sks);
4726                         sbuf_printf(sb, "\n");
4727                 }
4728
4729                 /*
4730                  * If this is fixed sense, we're done.  If we have
4731                  * descriptor sense, we might have more information
4732                  * available.
4733                  */
4734                 if (scsi_sense_type(sense) != SSD_TYPE_DESC)
4735                         break;
4736
4737                 desc_sense = (struct scsi_sense_data_desc *)sense;
4738
4739                 print_info.sb = sb;
4740                 print_info.path_str = path_str;
4741                 print_info.cdb = cdb;
4742                 print_info.cdb_len = cdb_len;
4743                 print_info.inq_data = inq_data;
4744
4745                 /*
4746                  * Print any sense descriptors that we have not already printed.
4747                  */
4748                 scsi_desc_iterate(desc_sense, sense_len, scsi_print_desc_func,
4749                                   &print_info);
4750                 break;
4751
4752         }
4753         case -1:
4754                 /*
4755                  * scsi_extract_sense_len() sets values to -1 if the
4756                  * show_errors flag is set and they aren't present in the
4757                  * sense data.  This means that sense_len is 0.
4758                  */
4759                 sbuf_printf(sb, "No sense data present\n");
4760                 break;
4761         default: {
4762                 sbuf_printf(sb, "Error code 0x%x", error_code);
4763                 if (sense->error_code & SSD_ERRCODE_VALID) {
4764                         struct scsi_sense_data_fixed *fixed_sense;
4765
4766                         fixed_sense = (struct scsi_sense_data_fixed *)sense;
4767
4768                         if (SSD_FIXED_IS_PRESENT(fixed_sense, sense_len, info)){
4769                                 uint32_t info;
4770
4771                                 info = scsi_4btoul(fixed_sense->info);
4772
4773                                 sbuf_printf(sb, " at block no. %d (decimal)",
4774                                             info);
4775                         }
4776                 }
4777                 sbuf_printf(sb, "\n");
4778                 break;
4779         }
4780         }
4781 }
4782
4783 /*
4784  * scsi_sense_sbuf() returns 0 for success and -1 for failure.
4785  */
4786 #ifdef _KERNEL
4787 int
4788 scsi_sense_sbuf(struct ccb_scsiio *csio, struct sbuf *sb,
4789                 scsi_sense_string_flags flags)
4790 #else /* !_KERNEL */
4791 int
4792 scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio, 
4793                 struct sbuf *sb, scsi_sense_string_flags flags)
4794 #endif /* _KERNEL/!_KERNEL */
4795 {
4796         struct    scsi_sense_data *sense;
4797         struct    scsi_inquiry_data *inq_data;
4798 #ifdef _KERNEL
4799         struct    ccb_getdev *cgd;
4800 #endif /* _KERNEL */
4801         char      path_str[64];
4802         uint8_t   *cdb;
4803
4804 #ifndef _KERNEL
4805         if (device == NULL)
4806                 return(-1);
4807 #endif /* !_KERNEL */
4808         if ((csio == NULL) || (sb == NULL))
4809                 return(-1);
4810
4811         /*
4812          * If the CDB is a physical address, we can't deal with it..
4813          */
4814         if ((csio->ccb_h.flags & CAM_CDB_PHYS) != 0)
4815                 flags &= ~SSS_FLAG_PRINT_COMMAND;
4816
4817 #ifdef _KERNEL
4818         xpt_path_string(csio->ccb_h.path, path_str, sizeof(path_str));
4819 #else /* !_KERNEL */
4820         cam_path_string(device, path_str, sizeof(path_str));
4821 #endif /* _KERNEL/!_KERNEL */
4822
4823 #ifdef _KERNEL
4824         if ((cgd = (struct ccb_getdev*)xpt_alloc_ccb_nowait()) == NULL)
4825                 return(-1);
4826         /*
4827          * Get the device information.
4828          */
4829         xpt_setup_ccb(&cgd->ccb_h,
4830                       csio->ccb_h.path,
4831                       CAM_PRIORITY_NORMAL);
4832         cgd->ccb_h.func_code = XPT_GDEV_TYPE;
4833         xpt_action((union ccb *)cgd);
4834
4835         /*
4836          * If the device is unconfigured, just pretend that it is a hard
4837          * drive.  scsi_op_desc() needs this.
4838          */
4839         if (cgd->ccb_h.status == CAM_DEV_NOT_THERE)
4840                 cgd->inq_data.device = T_DIRECT;
4841
4842         inq_data = &cgd->inq_data;
4843
4844 #else /* !_KERNEL */
4845
4846         inq_data = &device->inq_data;
4847
4848 #endif /* _KERNEL/!_KERNEL */
4849
4850         sense = NULL;
4851
4852         if (flags & SSS_FLAG_PRINT_COMMAND) {
4853
4854                 sbuf_cat(sb, path_str);
4855
4856 #ifdef _KERNEL
4857                 scsi_command_string(csio, sb);
4858 #else /* !_KERNEL */
4859                 scsi_command_string(device, csio, sb);
4860 #endif /* _KERNEL/!_KERNEL */
4861                 sbuf_printf(sb, "\n");
4862         }
4863
4864         /*
4865          * If the sense data is a physical pointer, forget it.
4866          */
4867         if (csio->ccb_h.flags & CAM_SENSE_PTR) {
4868                 if (csio->ccb_h.flags & CAM_SENSE_PHYS) {
4869 #ifdef _KERNEL
4870                         xpt_free_ccb((union ccb*)cgd);
4871 #endif /* _KERNEL/!_KERNEL */
4872                         return(-1);
4873                 } else {
4874                         /* 
4875                          * bcopy the pointer to avoid unaligned access
4876                          * errors on finicky architectures.  We don't
4877                          * ensure that the sense data is pointer aligned.
4878                          */
4879                         bcopy(&csio->sense_data, &sense, 
4880                               sizeof(struct scsi_sense_data *));
4881                 }
4882         } else {
4883                 /*
4884                  * If the physical sense flag is set, but the sense pointer
4885                  * is not also set, we assume that the user is an idiot and
4886                  * return.  (Well, okay, it could be that somehow, the
4887                  * entire csio is physical, but we would have probably core
4888                  * dumped on one of the bogus pointer deferences above
4889                  * already.)
4890                  */
4891                 if (csio->ccb_h.flags & CAM_SENSE_PHYS) {
4892 #ifdef _KERNEL
4893                         xpt_free_ccb((union ccb*)cgd);
4894 #endif /* _KERNEL/!_KERNEL */
4895                         return(-1);
4896                 } else
4897                         sense = &csio->sense_data;
4898         }
4899
4900         if (csio->ccb_h.flags & CAM_CDB_POINTER)
4901                 cdb = csio->cdb_io.cdb_ptr;
4902         else
4903                 cdb = csio->cdb_io.cdb_bytes;
4904
4905         scsi_sense_only_sbuf(sense, csio->sense_len - csio->sense_resid, sb,
4906                              path_str, inq_data, cdb, csio->cdb_len);
4907                          
4908 #ifdef _KERNEL
4909         xpt_free_ccb((union ccb*)cgd);
4910 #endif /* _KERNEL/!_KERNEL */
4911         return(0);
4912 }
4913
4914
4915
4916 #ifdef _KERNEL
4917 char *
4918 scsi_sense_string(struct ccb_scsiio *csio, char *str, int str_len)
4919 #else /* !_KERNEL */
4920 char *
4921 scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
4922                   char *str, int str_len)
4923 #endif /* _KERNEL/!_KERNEL */
4924 {
4925         struct sbuf sb;
4926
4927         sbuf_new(&sb, str, str_len, 0);
4928
4929 #ifdef _KERNEL
4930         scsi_sense_sbuf(csio, &sb, SSS_FLAG_PRINT_COMMAND);
4931 #else /* !_KERNEL */
4932         scsi_sense_sbuf(device, csio, &sb, SSS_FLAG_PRINT_COMMAND);
4933 #endif /* _KERNEL/!_KERNEL */
4934
4935         sbuf_finish(&sb);
4936
4937         return(sbuf_data(&sb));
4938 }
4939
4940 #ifdef _KERNEL
4941 void 
4942 scsi_sense_print(struct ccb_scsiio *csio)
4943 {
4944         struct sbuf sb;
4945         char str[512];
4946
4947         sbuf_new(&sb, str, sizeof(str), 0);
4948
4949         scsi_sense_sbuf(csio, &sb, SSS_FLAG_PRINT_COMMAND);
4950
4951         sbuf_finish(&sb);
4952
4953         printf("%s", sbuf_data(&sb));
4954 }
4955
4956 #else /* !_KERNEL */
4957 void
4958 scsi_sense_print(struct cam_device *device, struct ccb_scsiio *csio, 
4959                  FILE *ofile)
4960 {
4961         struct sbuf sb;
4962         char str[512];
4963
4964         if ((device == NULL) || (csio == NULL) || (ofile == NULL))
4965                 return;
4966
4967         sbuf_new(&sb, str, sizeof(str), 0);
4968
4969         scsi_sense_sbuf(device, csio, &sb, SSS_FLAG_PRINT_COMMAND);
4970
4971         sbuf_finish(&sb);
4972
4973         fprintf(ofile, "%s", sbuf_data(&sb));
4974 }
4975
4976 #endif /* _KERNEL/!_KERNEL */
4977
4978 /*
4979  * Extract basic sense information.  This is backward-compatible with the
4980  * previous implementation.  For new implementations,
4981  * scsi_extract_sense_len() is recommended.
4982  */
4983 void
4984 scsi_extract_sense(struct scsi_sense_data *sense_data, int *error_code,
4985                    int *sense_key, int *asc, int *ascq)
4986 {
4987         scsi_extract_sense_len(sense_data, sizeof(*sense_data), error_code,
4988                                sense_key, asc, ascq, /*show_errors*/ 0);
4989 }
4990
4991 /*
4992  * Extract basic sense information from SCSI I/O CCB structure.
4993  */
4994 int
4995 scsi_extract_sense_ccb(union ccb *ccb,
4996     int *error_code, int *sense_key, int *asc, int *ascq)
4997 {
4998         struct scsi_sense_data *sense_data;
4999
5000         /* Make sure there are some sense data we can access. */
5001         if (ccb->ccb_h.func_code != XPT_SCSI_IO ||
5002             (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_SCSI_STATUS_ERROR ||
5003             (ccb->csio.scsi_status != SCSI_STATUS_CHECK_COND) ||
5004             (ccb->ccb_h.status & CAM_AUTOSNS_VALID) == 0 ||
5005             (ccb->ccb_h.flags & CAM_SENSE_PHYS))
5006                 return (0);
5007
5008         if (ccb->ccb_h.flags & CAM_SENSE_PTR)
5009                 bcopy(&ccb->csio.sense_data, &sense_data,
5010                     sizeof(struct scsi_sense_data *));
5011         else
5012                 sense_data = &ccb->csio.sense_data;
5013         scsi_extract_sense_len(sense_data,
5014             ccb->csio.sense_len - ccb->csio.sense_resid,
5015             error_code, sense_key, asc, ascq, 1);
5016         if (*error_code == -1)
5017                 return (0);
5018         return (1);
5019 }
5020
5021 /*
5022  * Extract basic sense information.  If show_errors is set, sense values
5023  * will be set to -1 if they are not present.
5024  */
5025 void
5026 scsi_extract_sense_len(struct scsi_sense_data *sense_data, u_int sense_len,
5027                        int *error_code, int *sense_key, int *asc, int *ascq,
5028                        int show_errors)
5029 {
5030         /*
5031          * If we have no length, we have no sense.
5032          */
5033         if (sense_len == 0) {
5034                 if (show_errors == 0) {
5035                         *error_code = 0;
5036                         *sense_key = 0;
5037                         *asc = 0;
5038                         *ascq = 0;
5039                 } else {
5040                         *error_code = -1;
5041                         *sense_key = -1;
5042                         *asc = -1;
5043                         *ascq = -1;
5044                 }
5045                 return;
5046         }
5047
5048         *error_code = sense_data->error_code & SSD_ERRCODE;
5049
5050         switch (*error_code) {
5051         case SSD_DESC_CURRENT_ERROR:
5052         case SSD_DESC_DEFERRED_ERROR: {
5053                 struct scsi_sense_data_desc *sense;
5054
5055                 sense = (struct scsi_sense_data_desc *)sense_data;
5056
5057                 if (SSD_DESC_IS_PRESENT(sense, sense_len, sense_key))
5058                         *sense_key = sense->sense_key & SSD_KEY;
5059                 else
5060                         *sense_key = (show_errors) ? -1 : 0;
5061
5062                 if (SSD_DESC_IS_PRESENT(sense, sense_len, add_sense_code))
5063                         *asc = sense->add_sense_code;
5064                 else
5065                         *asc = (show_errors) ? -1 : 0;
5066
5067                 if (SSD_DESC_IS_PRESENT(sense, sense_len, add_sense_code_qual))
5068                         *ascq = sense->add_sense_code_qual;
5069                 else
5070                         *ascq = (show_errors) ? -1 : 0;
5071                 break;
5072         }
5073         case SSD_CURRENT_ERROR:
5074         case SSD_DEFERRED_ERROR:
5075         default: {
5076                 struct scsi_sense_data_fixed *sense;
5077
5078                 sense = (struct scsi_sense_data_fixed *)sense_data;
5079
5080                 if (SSD_FIXED_IS_PRESENT(sense, sense_len, flags))
5081                         *sense_key = sense->flags & SSD_KEY;
5082                 else
5083                         *sense_key = (show_errors) ? -1 : 0;
5084
5085                 if ((SSD_FIXED_IS_PRESENT(sense, sense_len, add_sense_code))
5086                  && (SSD_FIXED_IS_FILLED(sense, add_sense_code)))
5087                         *asc = sense->add_sense_code;
5088                 else
5089                         *asc = (show_errors) ? -1 : 0;
5090
5091                 if ((SSD_FIXED_IS_PRESENT(sense, sense_len,add_sense_code_qual))
5092                  && (SSD_FIXED_IS_FILLED(sense, add_sense_code_qual)))
5093                         *ascq = sense->add_sense_code_qual;
5094                 else
5095                         *ascq = (show_errors) ? -1 : 0;
5096                 break;
5097         }
5098         }
5099 }
5100
5101 int
5102 scsi_get_sense_key(struct scsi_sense_data *sense_data, u_int sense_len,
5103                    int show_errors)
5104 {
5105         int error_code, sense_key, asc, ascq;
5106
5107         scsi_extract_sense_len(sense_data, sense_len, &error_code,
5108                                &sense_key, &asc, &ascq, show_errors);
5109
5110         return (sense_key);
5111 }
5112
5113 int
5114 scsi_get_asc(struct scsi_sense_data *sense_data, u_int sense_len,
5115              int show_errors)
5116 {
5117         int error_code, sense_key, asc, ascq;
5118
5119         scsi_extract_sense_len(sense_data, sense_len, &error_code,
5120                                &sense_key, &asc, &ascq, show_errors);
5121
5122         return (asc);
5123 }
5124
5125 int
5126 scsi_get_ascq(struct scsi_sense_data *sense_data, u_int sense_len,
5127               int show_errors)
5128 {
5129         int error_code, sense_key, asc, ascq;
5130
5131         scsi_extract_sense_len(sense_data, sense_len, &error_code,
5132                                &sense_key, &asc, &ascq, show_errors);
5133
5134         return (ascq);
5135 }
5136
5137 /*
5138  * This function currently requires at least 36 bytes, or
5139  * SHORT_INQUIRY_LENGTH, worth of data to function properly.  If this
5140  * function needs more or less data in the future, another length should be
5141  * defined in scsi_all.h to indicate the minimum amount of data necessary
5142  * for this routine to function properly.
5143  */
5144 void
5145 scsi_print_inquiry(struct scsi_inquiry_data *inq_data)
5146 {
5147         u_int8_t type;
5148         char *dtype, *qtype;
5149         char vendor[16], product[48], revision[16], rstr[4];
5150
5151         type = SID_TYPE(inq_data);
5152
5153         /*
5154          * Figure out basic device type and qualifier.
5155          */
5156         if (SID_QUAL_IS_VENDOR_UNIQUE(inq_data)) {
5157                 qtype = "(vendor-unique qualifier)";
5158         } else {
5159                 switch (SID_QUAL(inq_data)) {
5160                 case SID_QUAL_LU_CONNECTED:
5161                         qtype = "";
5162                         break;
5163
5164                 case SID_QUAL_LU_OFFLINE:
5165                         qtype = "(offline)";
5166                         break;
5167
5168                 case SID_QUAL_RSVD:
5169                         qtype = "(reserved qualifier)";
5170                         break;
5171                 default:
5172                 case SID_QUAL_BAD_LU:
5173                         qtype = "(LUN not supported)";
5174                         break;
5175                 }
5176         }
5177
5178         switch (type) {
5179         case T_DIRECT:
5180                 dtype = "Direct Access";
5181                 break;
5182         case T_SEQUENTIAL:
5183                 dtype = "Sequential Access";
5184                 break;
5185         case T_PRINTER:
5186                 dtype = "Printer";
5187                 break;
5188         case T_PROCESSOR:
5189                 dtype = "Processor";
5190                 break;
5191         case T_WORM:
5192                 dtype = "WORM";
5193                 break;
5194         case T_CDROM:
5195                 dtype = "CD-ROM";
5196                 break;
5197         case T_SCANNER:
5198                 dtype = "Scanner";
5199                 break;
5200         case T_OPTICAL:
5201                 dtype = "Optical";
5202                 break;
5203         case T_CHANGER:
5204                 dtype = "Changer";
5205                 break;
5206         case T_COMM:
5207                 dtype = "Communication";
5208                 break;
5209         case T_STORARRAY:
5210                 dtype = "Storage Array";
5211                 break;
5212         case T_ENCLOSURE:
5213                 dtype = "Enclosure Services";
5214                 break;
5215         case T_RBC:
5216                 dtype = "Simplified Direct Access";
5217                 break;
5218         case T_OCRW:
5219                 dtype = "Optical Card Read/Write";
5220                 break;
5221         case T_OSD:
5222                 dtype = "Object-Based Storage";
5223                 break;
5224         case T_ADC:
5225                 dtype = "Automation/Drive Interface";
5226                 break;
5227         case T_NODEVICE:
5228                 dtype = "Uninstalled";
5229                 break;
5230         default:
5231                 dtype = "unknown";
5232                 break;
5233         }
5234
5235         cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor),
5236                    sizeof(vendor));
5237         cam_strvis(product, inq_data->product, sizeof(inq_data->product),
5238                    sizeof(product));
5239         cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision),
5240                    sizeof(revision));
5241
5242         if (SID_ANSI_REV(inq_data) == SCSI_REV_CCS)
5243                 bcopy("CCS", rstr, 4);
5244         else
5245                 snprintf(rstr, sizeof (rstr), "%d", SID_ANSI_REV(inq_data));
5246         printf("<%s %s %s> %s %s SCSI-%s device %s\n",
5247                vendor, product, revision,
5248                SID_IS_REMOVABLE(inq_data) ? "Removable" : "Fixed",
5249                dtype, rstr, qtype);
5250 }
5251
5252 /*
5253  * Table of syncrates that don't follow the "divisible by 4"
5254  * rule. This table will be expanded in future SCSI specs.
5255  */
5256 static struct {
5257         u_int period_factor;
5258         u_int period;   /* in 100ths of ns */
5259 } scsi_syncrates[] = {
5260         { 0x08, 625 },  /* FAST-160 */
5261         { 0x09, 1250 }, /* FAST-80 */
5262         { 0x0a, 2500 }, /* FAST-40 40MHz */
5263         { 0x0b, 3030 }, /* FAST-40 33MHz */
5264         { 0x0c, 5000 }  /* FAST-20 */
5265 };
5266
5267 /*
5268  * Return the frequency in kHz corresponding to the given
5269  * sync period factor.
5270  */
5271 u_int
5272 scsi_calc_syncsrate(u_int period_factor)
5273 {
5274         int i;
5275         int num_syncrates;
5276
5277         /*
5278          * It's a bug if period is zero, but if it is anyway, don't
5279          * die with a divide fault- instead return something which
5280          * 'approximates' async
5281          */
5282         if (period_factor == 0) {
5283                 return (3300);
5284         }
5285
5286         num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
5287         /* See if the period is in the "exception" table */
5288         for (i = 0; i < num_syncrates; i++) {
5289
5290                 if (period_factor == scsi_syncrates[i].period_factor) {
5291                         /* Period in kHz */
5292                         return (100000000 / scsi_syncrates[i].period);
5293                 }
5294         }
5295
5296         /*
5297          * Wasn't in the table, so use the standard
5298          * 4 times conversion.
5299          */
5300         return (10000000 / (period_factor * 4 * 10));
5301 }
5302
5303 /*
5304  * Return the SCSI sync parameter that corresponsd to
5305  * the passed in period in 10ths of ns.
5306  */
5307 u_int
5308 scsi_calc_syncparam(u_int period)
5309 {
5310         int i;
5311         int num_syncrates;
5312
5313         if (period == 0)
5314                 return (~0);    /* Async */
5315
5316         /* Adjust for exception table being in 100ths. */
5317         period *= 10;
5318         num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
5319         /* See if the period is in the "exception" table */
5320         for (i = 0; i < num_syncrates; i++) {
5321
5322                 if (period <= scsi_syncrates[i].period) {
5323                         /* Period in 100ths of ns */
5324                         return (scsi_syncrates[i].period_factor);
5325                 }
5326         }
5327
5328         /*
5329          * Wasn't in the table, so use the standard
5330          * 1/4 period in ns conversion.
5331          */
5332         return (period/400);
5333 }
5334
5335 int
5336 scsi_devid_is_naa_ieee_reg(uint8_t *bufp)
5337 {
5338         struct scsi_vpd_id_descriptor *descr;
5339         struct scsi_vpd_id_naa_basic *naa;
5340
5341         descr = (struct scsi_vpd_id_descriptor *)bufp;
5342         naa = (struct scsi_vpd_id_naa_basic *)descr->identifier;
5343         if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_NAA)
5344                 return 0;
5345         if (descr->length < sizeof(struct scsi_vpd_id_naa_ieee_reg))
5346                 return 0;
5347         if ((naa->naa >> SVPD_ID_NAA_NAA_SHIFT) != SVPD_ID_NAA_IEEE_REG)
5348                 return 0;
5349         return 1;
5350 }
5351
5352 int
5353 scsi_devid_is_sas_target(uint8_t *bufp)
5354 {
5355         struct scsi_vpd_id_descriptor *descr;
5356
5357         descr = (struct scsi_vpd_id_descriptor *)bufp;
5358         if (!scsi_devid_is_naa_ieee_reg(bufp))
5359                 return 0;
5360         if ((descr->id_type & SVPD_ID_PIV) == 0) /* proto field reserved */
5361                 return 0;
5362         if ((descr->proto_codeset >> SVPD_ID_PROTO_SHIFT) != SCSI_PROTO_SAS)
5363                 return 0;
5364         return 1;
5365 }
5366
5367 int
5368 scsi_devid_is_lun_eui64(uint8_t *bufp)
5369 {
5370         struct scsi_vpd_id_descriptor *descr;
5371
5372         descr = (struct scsi_vpd_id_descriptor *)bufp;
5373         if ((descr->id_type & SVPD_ID_ASSOC_MASK) != SVPD_ID_ASSOC_LUN)
5374                 return 0;
5375         if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_EUI64)
5376                 return 0;
5377         return 1;
5378 }
5379
5380 int
5381 scsi_devid_is_lun_naa(uint8_t *bufp)
5382 {
5383         struct scsi_vpd_id_descriptor *descr;
5384
5385         descr = (struct scsi_vpd_id_descriptor *)bufp;
5386         if ((descr->id_type & SVPD_ID_ASSOC_MASK) != SVPD_ID_ASSOC_LUN)
5387                 return 0;
5388         if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_NAA)
5389                 return 0;
5390         return 1;
5391 }
5392
5393 int
5394 scsi_devid_is_lun_t10(uint8_t *bufp)
5395 {
5396         struct scsi_vpd_id_descriptor *descr;
5397
5398         descr = (struct scsi_vpd_id_descriptor *)bufp;
5399         if ((descr->id_type & SVPD_ID_ASSOC_MASK) != SVPD_ID_ASSOC_LUN)
5400                 return 0;
5401         if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_T10)
5402                 return 0;
5403         return 1;
5404 }
5405
5406 int
5407 scsi_devid_is_lun_name(uint8_t *bufp)
5408 {
5409         struct scsi_vpd_id_descriptor *descr;
5410
5411         descr = (struct scsi_vpd_id_descriptor *)bufp;
5412         if ((descr->id_type & SVPD_ID_ASSOC_MASK) != SVPD_ID_ASSOC_LUN)
5413                 return 0;
5414         if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_SCSI_NAME)
5415                 return 0;
5416         return 1;
5417 }
5418
5419 struct scsi_vpd_id_descriptor *
5420 scsi_get_devid(struct scsi_vpd_device_id *id, uint32_t page_len,
5421     scsi_devid_checkfn_t ck_fn)
5422 {
5423         struct scsi_vpd_id_descriptor *desc;
5424         uint8_t *page_end;
5425         uint8_t *desc_buf_end;
5426
5427         page_end = (uint8_t *)id + page_len;
5428         if (page_end < id->desc_list)
5429                 return (NULL);
5430
5431         desc_buf_end = MIN(id->desc_list + scsi_2btoul(id->length), page_end);
5432
5433         for (desc = (struct scsi_vpd_id_descriptor *)id->desc_list;
5434              desc->identifier <= desc_buf_end
5435           && desc->identifier + desc->length <= desc_buf_end;
5436              desc = (struct scsi_vpd_id_descriptor *)(desc->identifier
5437                                                     + desc->length)) {
5438
5439                 if (ck_fn == NULL || ck_fn((uint8_t *)desc) != 0)
5440                         return (desc);
5441         }
5442
5443         return (NULL);
5444 }
5445
5446 void
5447 scsi_test_unit_ready(struct ccb_scsiio *csio, u_int32_t retries,
5448                      void (*cbfcnp)(struct cam_periph *, union ccb *),
5449                      u_int8_t tag_action, u_int8_t sense_len, u_int32_t timeout)
5450 {
5451         struct scsi_test_unit_ready *scsi_cmd;
5452
5453         cam_fill_csio(csio,
5454                       retries,
5455                       cbfcnp,
5456                       CAM_DIR_NONE,
5457                       tag_action,
5458                       /*data_ptr*/NULL,
5459                       /*dxfer_len*/0,
5460                       sense_len,
5461                       sizeof(*scsi_cmd),
5462                       timeout);
5463
5464         scsi_cmd = (struct scsi_test_unit_ready *)&csio->cdb_io.cdb_bytes;
5465         bzero(scsi_cmd, sizeof(*scsi_cmd));
5466         scsi_cmd->opcode = TEST_UNIT_READY;
5467 }
5468
5469 void
5470 scsi_request_sense(struct ccb_scsiio *csio, u_int32_t retries,
5471                    void (*cbfcnp)(struct cam_periph *, union ccb *),
5472                    void *data_ptr, u_int8_t dxfer_len, u_int8_t tag_action,
5473                    u_int8_t sense_len, u_int32_t timeout)
5474 {
5475         struct scsi_request_sense *scsi_cmd;
5476
5477         cam_fill_csio(csio,
5478                       retries,
5479                       cbfcnp,
5480                       CAM_DIR_IN,
5481                       tag_action,
5482                       data_ptr,
5483                       dxfer_len,
5484                       sense_len,
5485                       sizeof(*scsi_cmd),
5486                       timeout);
5487
5488         scsi_cmd = (struct scsi_request_sense *)&csio->cdb_io.cdb_bytes;
5489         bzero(scsi_cmd, sizeof(*scsi_cmd));
5490         scsi_cmd->opcode = REQUEST_SENSE;
5491         scsi_cmd->length = dxfer_len;
5492 }
5493
5494 void
5495 scsi_inquiry(struct ccb_scsiio *csio, u_int32_t retries,
5496              void (*cbfcnp)(struct cam_periph *, union ccb *),
5497              u_int8_t tag_action, u_int8_t *inq_buf, u_int32_t inq_len,
5498              int evpd, u_int8_t page_code, u_int8_t sense_len,
5499              u_int32_t timeout)
5500 {
5501         struct scsi_inquiry *scsi_cmd;
5502
5503         cam_fill_csio(csio,
5504                       retries,
5505                       cbfcnp,
5506                       /*flags*/CAM_DIR_IN,
5507                       tag_action,
5508                       /*data_ptr*/inq_buf,
5509                       /*dxfer_len*/inq_len,
5510                       sense_len,
5511                       sizeof(*scsi_cmd),
5512                       timeout);
5513
5514         scsi_cmd = (struct scsi_inquiry *)&csio->cdb_io.cdb_bytes;
5515         bzero(scsi_cmd, sizeof(*scsi_cmd));
5516         scsi_cmd->opcode = INQUIRY;
5517         if (evpd) {
5518                 scsi_cmd->byte2 |= SI_EVPD;
5519                 scsi_cmd->page_code = page_code;                
5520         }
5521         scsi_ulto2b(inq_len, scsi_cmd->length);
5522 }
5523
5524 void
5525 scsi_mode_sense(struct ccb_scsiio *csio, u_int32_t retries,
5526                 void (*cbfcnp)(struct cam_periph *, union ccb *),
5527                 u_int8_t tag_action, int dbd, u_int8_t page_code,
5528                 u_int8_t page, u_int8_t *param_buf, u_int32_t param_len,
5529                 u_int8_t sense_len, u_int32_t timeout)
5530 {
5531
5532         scsi_mode_sense_len(csio, retries, cbfcnp, tag_action, dbd,
5533                             page_code, page, param_buf, param_len, 0,
5534                             sense_len, timeout);
5535 }
5536
5537 void
5538 scsi_mode_sense_len(struct ccb_scsiio *csio, u_int32_t retries,
5539                     void (*cbfcnp)(struct cam_periph *, union ccb *),
5540                     u_int8_t tag_action, int dbd, u_int8_t page_code,
5541                     u_int8_t page, u_int8_t *param_buf, u_int32_t param_len,
5542                     int minimum_cmd_size, u_int8_t sense_len, u_int32_t timeout)
5543 {
5544         u_int8_t cdb_len;
5545
5546         /*
5547          * Use the smallest possible command to perform the operation.
5548          */
5549         if ((param_len < 256)
5550          && (minimum_cmd_size < 10)) {
5551                 /*
5552                  * We can fit in a 6 byte cdb.
5553                  */
5554                 struct scsi_mode_sense_6 *scsi_cmd;
5555
5556                 scsi_cmd = (struct scsi_mode_sense_6 *)&csio->cdb_io.cdb_bytes;
5557                 bzero(scsi_cmd, sizeof(*scsi_cmd));
5558                 scsi_cmd->opcode = MODE_SENSE_6;
5559                 if (dbd != 0)
5560                         scsi_cmd->byte2 |= SMS_DBD;
5561                 scsi_cmd->page = page_code | page;
5562                 scsi_cmd->length = param_len;
5563                 cdb_len = sizeof(*scsi_cmd);
5564         } else {
5565                 /*
5566                  * Need a 10 byte cdb.
5567                  */
5568                 struct scsi_mode_sense_10 *scsi_cmd;
5569
5570                 scsi_cmd = (struct scsi_mode_sense_10 *)&csio->cdb_io.cdb_bytes;
5571                 bzero(scsi_cmd, sizeof(*scsi_cmd));
5572                 scsi_cmd->opcode = MODE_SENSE_10;
5573                 if (dbd != 0)
5574                         scsi_cmd->byte2 |= SMS_DBD;
5575                 scsi_cmd->page = page_code | page;
5576                 scsi_ulto2b(param_len, scsi_cmd->length);
5577                 cdb_len = sizeof(*scsi_cmd);
5578         }
5579         cam_fill_csio(csio,
5580                       retries,
5581                       cbfcnp,
5582                       CAM_DIR_IN,
5583                       tag_action,
5584                       param_buf,
5585                       param_len,
5586                       sense_len,
5587                       cdb_len,
5588                       timeout);
5589 }
5590
5591 void
5592 scsi_mode_select(struct ccb_scsiio *csio, u_int32_t retries,
5593                  void (*cbfcnp)(struct cam_periph *, union ccb *),
5594                  u_int8_t tag_action, int scsi_page_fmt, int save_pages,
5595                  u_int8_t *param_buf, u_int32_t param_len, u_int8_t sense_len,
5596                  u_int32_t timeout)
5597 {
5598         scsi_mode_select_len(csio, retries, cbfcnp, tag_action,
5599                              scsi_page_fmt, save_pages, param_buf,
5600                              param_len, 0, sense_len, timeout);
5601 }
5602
5603 void
5604 scsi_mode_select_len(struct ccb_scsiio *csio, u_int32_t retries,
5605                      void (*cbfcnp)(struct cam_periph *, union ccb *),
5606                      u_int8_t tag_action, int scsi_page_fmt, int save_pages,
5607                      u_int8_t *param_buf, u_int32_t param_len,
5608                      int minimum_cmd_size, u_int8_t sense_len,
5609                      u_int32_t timeout)
5610 {
5611         u_int8_t cdb_len;
5612
5613         /*
5614          * Use the smallest possible command to perform the operation.
5615          */
5616         if ((param_len < 256)
5617          && (minimum_cmd_size < 10)) {
5618                 /*
5619                  * We can fit in a 6 byte cdb.
5620                  */
5621                 struct scsi_mode_select_6 *scsi_cmd;
5622
5623                 scsi_cmd = (struct scsi_mode_select_6 *)&csio->cdb_io.cdb_bytes;
5624                 bzero(scsi_cmd, sizeof(*scsi_cmd));
5625                 scsi_cmd->opcode = MODE_SELECT_6;
5626                 if (scsi_page_fmt != 0)
5627                         scsi_cmd->byte2 |= SMS_PF;
5628                 if (save_pages != 0)
5629                         scsi_cmd->byte2 |= SMS_SP;
5630                 scsi_cmd->length = param_len;
5631                 cdb_len = sizeof(*scsi_cmd);
5632         } else {
5633                 /*
5634                  * Need a 10 byte cdb.
5635                  */
5636                 struct scsi_mode_select_10 *scsi_cmd;
5637
5638                 scsi_cmd =
5639                     (struct scsi_mode_select_10 *)&csio->cdb_io.cdb_bytes;
5640                 bzero(scsi_cmd, sizeof(*scsi_cmd));
5641                 scsi_cmd->opcode = MODE_SELECT_10;
5642                 if (scsi_page_fmt != 0)
5643                         scsi_cmd->byte2 |= SMS_PF;
5644                 if (save_pages != 0)
5645                         scsi_cmd->byte2 |= SMS_SP;
5646                 scsi_ulto2b(param_len, scsi_cmd->length);
5647                 cdb_len = sizeof(*scsi_cmd);
5648         }
5649         cam_fill_csio(csio,
5650                       retries,
5651                       cbfcnp,
5652                       CAM_DIR_OUT,
5653                       tag_action,
5654                       param_buf,
5655                       param_len,
5656                       sense_len,
5657                       cdb_len,
5658                       timeout);
5659 }
5660
5661 void
5662 scsi_log_sense(struct ccb_scsiio *csio, u_int32_t retries,
5663                void (*cbfcnp)(struct cam_periph *, union ccb *),
5664                u_int8_t tag_action, u_int8_t page_code, u_int8_t page,
5665                int save_pages, int ppc, u_int32_t paramptr,
5666                u_int8_t *param_buf, u_int32_t param_len, u_int8_t sense_len,
5667                u_int32_t timeout)
5668 {
5669         struct scsi_log_sense *scsi_cmd;
5670         u_int8_t cdb_len;
5671
5672         scsi_cmd = (struct scsi_log_sense *)&csio->cdb_io.cdb_bytes;
5673         bzero(scsi_cmd, sizeof(*scsi_cmd));
5674         scsi_cmd->opcode = LOG_SENSE;
5675         scsi_cmd->page = page_code | page;
5676         if (save_pages != 0)
5677                 scsi_cmd->byte2 |= SLS_SP;
5678         if (ppc != 0)
5679                 scsi_cmd->byte2 |= SLS_PPC;
5680         scsi_ulto2b(paramptr, scsi_cmd->paramptr);
5681         scsi_ulto2b(param_len, scsi_cmd->length);
5682         cdb_len = sizeof(*scsi_cmd);
5683
5684         cam_fill_csio(csio,
5685                       retries,
5686                       cbfcnp,
5687                       /*flags*/CAM_DIR_IN,
5688                       tag_action,
5689                       /*data_ptr*/param_buf,
5690                       /*dxfer_len*/param_len,
5691                       sense_len,
5692                       cdb_len,
5693                       timeout);
5694 }
5695
5696 void
5697 scsi_log_select(struct ccb_scsiio *csio, u_int32_t retries,
5698                 void (*cbfcnp)(struct cam_periph *, union ccb *),
5699                 u_int8_t tag_action, u_int8_t page_code, int save_pages,
5700                 int pc_reset, u_int8_t *param_buf, u_int32_t param_len,
5701                 u_int8_t sense_len, u_int32_t timeout)
5702 {
5703         struct scsi_log_select *scsi_cmd;
5704         u_int8_t cdb_len;
5705
5706         scsi_cmd = (struct scsi_log_select *)&csio->cdb_io.cdb_bytes;
5707         bzero(scsi_cmd, sizeof(*scsi_cmd));
5708         scsi_cmd->opcode = LOG_SELECT;
5709         scsi_cmd->page = page_code & SLS_PAGE_CODE;
5710         if (save_pages != 0)
5711                 scsi_cmd->byte2 |= SLS_SP;
5712         if (pc_reset != 0)
5713                 scsi_cmd->byte2 |= SLS_PCR;
5714         scsi_ulto2b(param_len, scsi_cmd->length);
5715         cdb_len = sizeof(*scsi_cmd);
5716
5717         cam_fill_csio(csio,
5718                       retries,
5719                       cbfcnp,
5720                       /*flags*/CAM_DIR_OUT,
5721                       tag_action,
5722                       /*data_ptr*/param_buf,
5723                       /*dxfer_len*/param_len,
5724                       sense_len,
5725                       cdb_len,
5726                       timeout);
5727 }
5728
5729 /*
5730  * Prevent or allow the user to remove the media
5731  */
5732 void
5733 scsi_prevent(struct ccb_scsiio *csio, u_int32_t retries,
5734              void (*cbfcnp)(struct cam_periph *, union ccb *),
5735              u_int8_t tag_action, u_int8_t action,
5736              u_int8_t sense_len, u_int32_t timeout)
5737 {
5738         struct scsi_prevent *scsi_cmd;
5739
5740         cam_fill_csio(csio,
5741                       retries,
5742                       cbfcnp,
5743                       /*flags*/CAM_DIR_NONE,
5744                       tag_action,
5745                       /*data_ptr*/NULL,
5746                       /*dxfer_len*/0,
5747                       sense_len,
5748                       sizeof(*scsi_cmd),
5749                       timeout);
5750
5751         scsi_cmd = (struct scsi_prevent *)&csio->cdb_io.cdb_bytes;
5752         bzero(scsi_cmd, sizeof(*scsi_cmd));
5753         scsi_cmd->opcode = PREVENT_ALLOW;
5754         scsi_cmd->how = action;
5755 }
5756
5757 /* XXX allow specification of address and PMI bit and LBA */
5758 void
5759 scsi_read_capacity(struct ccb_scsiio *csio, u_int32_t retries,
5760                    void (*cbfcnp)(struct cam_periph *, union ccb *),
5761                    u_int8_t tag_action,
5762                    struct scsi_read_capacity_data *rcap_buf,
5763                    u_int8_t sense_len, u_int32_t timeout)
5764 {
5765         struct scsi_read_capacity *scsi_cmd;
5766
5767         cam_fill_csio(csio,
5768                       retries,
5769                       cbfcnp,
5770                       /*flags*/CAM_DIR_IN,
5771                       tag_action,
5772                       /*data_ptr*/(u_int8_t *)rcap_buf,
5773                       /*dxfer_len*/sizeof(*rcap_buf),
5774                       sense_len,
5775                       sizeof(*scsi_cmd),
5776                       timeout);
5777
5778         scsi_cmd = (struct scsi_read_capacity *)&csio->cdb_io.cdb_bytes;
5779         bzero(scsi_cmd, sizeof(*scsi_cmd));
5780         scsi_cmd->opcode = READ_CAPACITY;
5781 }
5782
5783 void
5784 scsi_read_capacity_16(struct ccb_scsiio *csio, uint32_t retries,
5785                       void (*cbfcnp)(struct cam_periph *, union ccb *),
5786                       uint8_t tag_action, uint64_t lba, int reladr, int pmi,
5787                       uint8_t *rcap_buf, int rcap_buf_len, uint8_t sense_len,
5788                       uint32_t timeout)
5789 {
5790         struct scsi_read_capacity_16 *scsi_cmd;
5791
5792         
5793         cam_fill_csio(csio,
5794                       retries,
5795                       cbfcnp,
5796                       /*flags*/CAM_DIR_IN,
5797                       tag_action,
5798                       /*data_ptr*/(u_int8_t *)rcap_buf,
5799                       /*dxfer_len*/rcap_buf_len,
5800                       sense_len,
5801                       sizeof(*scsi_cmd),
5802                       timeout);
5803         scsi_cmd = (struct scsi_read_capacity_16 *)&csio->cdb_io.cdb_bytes;
5804         bzero(scsi_cmd, sizeof(*scsi_cmd));
5805         scsi_cmd->opcode = SERVICE_ACTION_IN;
5806         scsi_cmd->service_action = SRC16_SERVICE_ACTION;
5807         scsi_u64to8b(lba, scsi_cmd->addr);
5808         scsi_ulto4b(rcap_buf_len, scsi_cmd->alloc_len);
5809         if (pmi)
5810                 reladr |= SRC16_PMI;
5811         if (reladr)
5812                 reladr |= SRC16_RELADR;
5813 }
5814
5815 void
5816 scsi_report_luns(struct ccb_scsiio *csio, u_int32_t retries,
5817                  void (*cbfcnp)(struct cam_periph *, union ccb *),
5818                  u_int8_t tag_action, u_int8_t select_report,
5819                  struct scsi_report_luns_data *rpl_buf, u_int32_t alloc_len,
5820                  u_int8_t sense_len, u_int32_t timeout)
5821 {
5822         struct scsi_report_luns *scsi_cmd;
5823
5824         cam_fill_csio(csio,
5825                       retries,
5826                       cbfcnp,
5827                       /*flags*/CAM_DIR_IN,
5828                       tag_action,
5829                       /*data_ptr*/(u_int8_t *)rpl_buf,
5830                       /*dxfer_len*/alloc_len,
5831                       sense_len,
5832                       sizeof(*scsi_cmd),
5833                       timeout);
5834         scsi_cmd = (struct scsi_report_luns *)&csio->cdb_io.cdb_bytes;
5835         bzero(scsi_cmd, sizeof(*scsi_cmd));
5836         scsi_cmd->opcode = REPORT_LUNS;
5837         scsi_cmd->select_report = select_report;
5838         scsi_ulto4b(alloc_len, scsi_cmd->length);
5839 }
5840
5841 void
5842 scsi_report_target_group(struct ccb_scsiio *csio, u_int32_t retries,
5843                  void (*cbfcnp)(struct cam_periph *, union ccb *),
5844                  u_int8_t tag_action, u_int8_t pdf,
5845                  void *buf, u_int32_t alloc_len,
5846                  u_int8_t sense_len, u_int32_t timeout)
5847 {
5848         struct scsi_target_group *scsi_cmd;
5849
5850         cam_fill_csio(csio,
5851                       retries,
5852                       cbfcnp,
5853                       /*flags*/CAM_DIR_IN,
5854                       tag_action,
5855                       /*data_ptr*/(u_int8_t *)buf,
5856                       /*dxfer_len*/alloc_len,
5857                       sense_len,
5858                       sizeof(*scsi_cmd),
5859                       timeout);
5860         scsi_cmd = (struct scsi_target_group *)&csio->cdb_io.cdb_bytes;
5861         bzero(scsi_cmd, sizeof(*scsi_cmd));
5862         scsi_cmd->opcode = MAINTENANCE_IN;
5863         scsi_cmd->service_action = REPORT_TARGET_PORT_GROUPS | pdf;
5864         scsi_ulto4b(alloc_len, scsi_cmd->length);
5865 }
5866
5867 void
5868 scsi_set_target_group(struct ccb_scsiio *csio, u_int32_t retries,
5869                  void (*cbfcnp)(struct cam_periph *, union ccb *),
5870                  u_int8_t tag_action, void *buf, u_int32_t alloc_len,
5871                  u_int8_t sense_len, u_int32_t timeout)
5872 {
5873         struct scsi_target_group *scsi_cmd;
5874
5875         cam_fill_csio(csio,
5876                       retries,
5877                       cbfcnp,
5878                       /*flags*/CAM_DIR_OUT,
5879                       tag_action,
5880                       /*data_ptr*/(u_int8_t *)buf,
5881                       /*dxfer_len*/alloc_len,
5882                       sense_len,
5883                       sizeof(*scsi_cmd),
5884                       timeout);
5885         scsi_cmd = (struct scsi_target_group *)&csio->cdb_io.cdb_bytes;
5886         bzero(scsi_cmd, sizeof(*scsi_cmd));
5887         scsi_cmd->opcode = MAINTENANCE_OUT;
5888         scsi_cmd->service_action = SET_TARGET_PORT_GROUPS;
5889         scsi_ulto4b(alloc_len, scsi_cmd->length);
5890 }
5891
5892 /*
5893  * Syncronize the media to the contents of the cache for
5894  * the given lba/count pair.  Specifying 0/0 means sync
5895  * the whole cache.
5896  */
5897 void
5898 scsi_synchronize_cache(struct ccb_scsiio *csio, u_int32_t retries,
5899                        void (*cbfcnp)(struct cam_periph *, union ccb *),
5900                        u_int8_t tag_action, u_int32_t begin_lba,
5901                        u_int16_t lb_count, u_int8_t sense_len,
5902                        u_int32_t timeout)
5903 {
5904         struct scsi_sync_cache *scsi_cmd;
5905
5906         cam_fill_csio(csio,
5907                       retries,
5908                       cbfcnp,
5909                       /*flags*/CAM_DIR_NONE,
5910                       tag_action,
5911                       /*data_ptr*/NULL,
5912                       /*dxfer_len*/0,
5913                       sense_len,
5914                       sizeof(*scsi_cmd),
5915                       timeout);
5916
5917         scsi_cmd = (struct scsi_sync_cache *)&csio->cdb_io.cdb_bytes;
5918         bzero(scsi_cmd, sizeof(*scsi_cmd));
5919         scsi_cmd->opcode = SYNCHRONIZE_CACHE;
5920         scsi_ulto4b(begin_lba, scsi_cmd->begin_lba);
5921         scsi_ulto2b(lb_count, scsi_cmd->lb_count);
5922 }
5923
5924 void
5925 scsi_read_write(struct ccb_scsiio *csio, u_int32_t retries,
5926                 void (*cbfcnp)(struct cam_periph *, union ccb *),
5927                 u_int8_t tag_action, int readop, u_int8_t byte2,
5928                 int minimum_cmd_size, u_int64_t lba, u_int32_t block_count,
5929                 u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
5930                 u_int32_t timeout)
5931 {
5932         int read;
5933         u_int8_t cdb_len;
5934
5935         read = (readop & SCSI_RW_DIRMASK) == SCSI_RW_READ;
5936
5937         /*
5938          * Use the smallest possible command to perform the operation
5939          * as some legacy hardware does not support the 10 byte commands.
5940          * If any of the bits in byte2 is set, we have to go with a larger
5941          * command.
5942          */
5943         if ((minimum_cmd_size < 10)
5944          && ((lba & 0x1fffff) == lba)
5945          && ((block_count & 0xff) == block_count)
5946          && (byte2 == 0)) {
5947                 /*
5948                  * We can fit in a 6 byte cdb.
5949                  */
5950                 struct scsi_rw_6 *scsi_cmd;
5951
5952                 scsi_cmd = (struct scsi_rw_6 *)&csio->cdb_io.cdb_bytes;
5953                 scsi_cmd->opcode = read ? READ_6 : WRITE_6;
5954                 scsi_ulto3b(lba, scsi_cmd->addr);
5955                 scsi_cmd->length = block_count & 0xff;
5956                 scsi_cmd->control = 0;
5957                 cdb_len = sizeof(*scsi_cmd);
5958
5959                 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE,
5960                           ("6byte: %x%x%x:%d:%d\n", scsi_cmd->addr[0],
5961                            scsi_cmd->addr[1], scsi_cmd->addr[2],
5962                            scsi_cmd->length, dxfer_len));
5963         } else if ((minimum_cmd_size < 12)
5964                 && ((block_count & 0xffff) == block_count)
5965                 && ((lba & 0xffffffff) == lba)) {
5966                 /*
5967                  * Need a 10 byte cdb.
5968                  */
5969                 struct scsi_rw_10 *scsi_cmd;
5970
5971                 scsi_cmd = (struct scsi_rw_10 *)&csio->cdb_io.cdb_bytes;
5972                 scsi_cmd->opcode = read ? READ_10 : WRITE_10;
5973                 scsi_cmd->byte2 = byte2;
5974                 scsi_ulto4b(lba, scsi_cmd->addr);
5975                 scsi_cmd->reserved = 0;
5976                 scsi_ulto2b(block_count, scsi_cmd->length);
5977                 scsi_cmd->control = 0;
5978                 cdb_len = sizeof(*scsi_cmd);
5979
5980                 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE,
5981                           ("10byte: %x%x%x%x:%x%x: %d\n", scsi_cmd->addr[0],
5982                            scsi_cmd->addr[1], scsi_cmd->addr[2],
5983                            scsi_cmd->addr[3], scsi_cmd->length[0],
5984                            scsi_cmd->length[1], dxfer_len));
5985         } else if ((minimum_cmd_size < 16)
5986                 && ((block_count & 0xffffffff) == block_count)
5987                 && ((lba & 0xffffffff) == lba)) {
5988                 /* 
5989                  * The block count is too big for a 10 byte CDB, use a 12
5990                  * byte CDB.
5991                  */
5992                 struct scsi_rw_12 *scsi_cmd;
5993
5994                 scsi_cmd = (struct scsi_rw_12 *)&csio->cdb_io.cdb_bytes;
5995                 scsi_cmd->opcode = read ? READ_12 : WRITE_12;
5996                 scsi_cmd->byte2 = byte2;
5997                 scsi_ulto4b(lba, scsi_cmd->addr);
5998                 scsi_cmd->reserved = 0;
5999                 scsi_ulto4b(block_count, scsi_cmd->length);
6000                 scsi_cmd->control = 0;
6001                 cdb_len = sizeof(*scsi_cmd);
6002
6003                 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE,
6004                           ("12byte: %x%x%x%x:%x%x%x%x: %d\n", scsi_cmd->addr[0],
6005                            scsi_cmd->addr[1], scsi_cmd->addr[2],
6006                            scsi_cmd->addr[3], scsi_cmd->length[0],
6007                            scsi_cmd->length[1], scsi_cmd->length[2],
6008                            scsi_cmd->length[3], dxfer_len));
6009         } else {
6010                 /*
6011                  * 16 byte CDB.  We'll only get here if the LBA is larger
6012                  * than 2^32, or if the user asks for a 16 byte command.
6013                  */
6014                 struct scsi_rw_16 *scsi_cmd;
6015
6016                 scsi_cmd = (struct scsi_rw_16 *)&csio->cdb_io.cdb_bytes;
6017                 scsi_cmd->opcode = read ? READ_16 : WRITE_16;
6018                 scsi_cmd->byte2 = byte2;
6019                 scsi_u64to8b(lba, scsi_cmd->addr);
6020                 scsi_cmd->reserved = 0;
6021                 scsi_ulto4b(block_count, scsi_cmd->length);
6022                 scsi_cmd->control = 0;
6023                 cdb_len = sizeof(*scsi_cmd);
6024         }
6025         cam_fill_csio(csio,
6026                       retries,
6027                       cbfcnp,
6028                       (read ? CAM_DIR_IN : CAM_DIR_OUT) |
6029                       ((readop & SCSI_RW_BIO) != 0 ? CAM_DATA_BIO : 0),
6030                       tag_action,
6031                       data_ptr,
6032                       dxfer_len,
6033                       sense_len,
6034                       cdb_len,
6035                       timeout);
6036 }
6037
6038 void
6039 scsi_write_same(struct ccb_scsiio *csio, u_int32_t retries,
6040                 void (*cbfcnp)(struct cam_periph *, union ccb *),
6041                 u_int8_t tag_action, u_int8_t byte2,
6042                 int minimum_cmd_size, u_int64_t lba, u_int32_t block_count,
6043                 u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
6044                 u_int32_t timeout)
6045 {
6046         u_int8_t cdb_len;
6047         if ((minimum_cmd_size < 16) &&
6048             ((block_count & 0xffff) == block_count) &&
6049             ((lba & 0xffffffff) == lba)) {
6050                 /*
6051                  * Need a 10 byte cdb.
6052                  */
6053                 struct scsi_write_same_10 *scsi_cmd;
6054
6055                 scsi_cmd = (struct scsi_write_same_10 *)&csio->cdb_io.cdb_bytes;
6056                 scsi_cmd->opcode = WRITE_SAME_10;
6057                 scsi_cmd->byte2 = byte2;
6058                 scsi_ulto4b(lba, scsi_cmd->addr);
6059                 scsi_cmd->group = 0;
6060                 scsi_ulto2b(block_count, scsi_cmd->length);
6061                 scsi_cmd->control = 0;
6062                 cdb_len = sizeof(*scsi_cmd);
6063
6064                 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE,
6065                           ("10byte: %x%x%x%x:%x%x: %d\n", scsi_cmd->addr[0],
6066                            scsi_cmd->addr[1], scsi_cmd->addr[2],
6067                            scsi_cmd->addr[3], scsi_cmd->length[0],
6068                            scsi_cmd->length[1], dxfer_len));
6069         } else {
6070                 /*
6071                  * 16 byte CDB.  We'll only get here if the LBA is larger
6072                  * than 2^32, or if the user asks for a 16 byte command.
6073                  */
6074                 struct scsi_write_same_16 *scsi_cmd;
6075
6076                 scsi_cmd = (struct scsi_write_same_16 *)&csio->cdb_io.cdb_bytes;
6077                 scsi_cmd->opcode = WRITE_SAME_16;
6078                 scsi_cmd->byte2 = byte2;
6079                 scsi_u64to8b(lba, scsi_cmd->addr);
6080                 scsi_ulto4b(block_count, scsi_cmd->length);
6081                 scsi_cmd->group = 0;
6082                 scsi_cmd->control = 0;
6083                 cdb_len = sizeof(*scsi_cmd);
6084
6085                 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE,
6086                           ("16byte: %x%x%x%x%x%x%x%x:%x%x%x%x: %d\n",
6087                            scsi_cmd->addr[0], scsi_cmd->addr[1],
6088                            scsi_cmd->addr[2], scsi_cmd->addr[3],
6089                            scsi_cmd->addr[4], scsi_cmd->addr[5],
6090                            scsi_cmd->addr[6], scsi_cmd->addr[7],
6091                            scsi_cmd->length[0], scsi_cmd->length[1],
6092                            scsi_cmd->length[2], scsi_cmd->length[3],
6093                            dxfer_len));
6094         }
6095         cam_fill_csio(csio,
6096                       retries,
6097                       cbfcnp,
6098                       /*flags*/CAM_DIR_OUT,
6099                       tag_action,
6100                       data_ptr,
6101                       dxfer_len,
6102                       sense_len,
6103                       cdb_len,
6104                       timeout);
6105 }
6106
6107 void
6108 scsi_ata_identify(struct ccb_scsiio *csio, u_int32_t retries,
6109                   void (*cbfcnp)(struct cam_periph *, union ccb *),
6110                   u_int8_t tag_action, u_int8_t *data_ptr,
6111                   u_int16_t dxfer_len, u_int8_t sense_len,
6112                   u_int32_t timeout)
6113 {
6114         scsi_ata_pass_16(csio,
6115                          retries,
6116                          cbfcnp,
6117                          /*flags*/CAM_DIR_IN,
6118                          tag_action,
6119                          /*protocol*/AP_PROTO_PIO_IN,
6120                          /*ata_flags*/AP_FLAG_TDIR_FROM_DEV|
6121                                 AP_FLAG_BYT_BLOK_BYTES|AP_FLAG_TLEN_SECT_CNT,
6122                          /*features*/0,
6123                          /*sector_count*/dxfer_len,
6124                          /*lba*/0,
6125                          /*command*/ATA_ATA_IDENTIFY,
6126                          /*control*/0,
6127                          data_ptr,
6128                          dxfer_len,
6129                          sense_len,
6130                          timeout);
6131 }
6132
6133 void
6134 scsi_ata_trim(struct ccb_scsiio *csio, u_int32_t retries,
6135               void (*cbfcnp)(struct cam_periph *, union ccb *),
6136               u_int8_t tag_action, u_int16_t block_count,
6137               u_int8_t *data_ptr, u_int16_t dxfer_len, u_int8_t sense_len,
6138               u_int32_t timeout)
6139 {
6140         scsi_ata_pass_16(csio,
6141                          retries,
6142                          cbfcnp,
6143                          /*flags*/CAM_DIR_OUT,
6144                          tag_action,
6145                          /*protocol*/AP_EXTEND|AP_PROTO_DMA,
6146                          /*ata_flags*/AP_FLAG_TLEN_SECT_CNT|AP_FLAG_BYT_BLOK_BLOCKS,
6147                          /*features*/ATA_DSM_TRIM,
6148                          /*sector_count*/block_count,
6149                          /*lba*/0,
6150                          /*command*/ATA_DATA_SET_MANAGEMENT,
6151                          /*control*/0,
6152                          data_ptr,
6153                          dxfer_len,
6154                          sense_len,
6155                          timeout);
6156 }
6157
6158 void
6159 scsi_ata_pass_16(struct ccb_scsiio *csio, u_int32_t retries,
6160                  void (*cbfcnp)(struct cam_periph *, union ccb *),
6161                  u_int32_t flags, u_int8_t tag_action,
6162                  u_int8_t protocol, u_int8_t ata_flags, u_int16_t features,
6163                  u_int16_t sector_count, uint64_t lba, u_int8_t command,
6164                  u_int8_t control, u_int8_t *data_ptr, u_int16_t dxfer_len,
6165                  u_int8_t sense_len, u_int32_t timeout)
6166 {
6167         struct ata_pass_16 *ata_cmd;
6168
6169         ata_cmd = (struct ata_pass_16 *)&csio->cdb_io.cdb_bytes;
6170         ata_cmd->opcode = ATA_PASS_16;
6171         ata_cmd->protocol = protocol;
6172         ata_cmd->flags = ata_flags;
6173         ata_cmd->features_ext = features >> 8;
6174         ata_cmd->features = features;
6175         ata_cmd->sector_count_ext = sector_count >> 8;
6176         ata_cmd->sector_count = sector_count;
6177         ata_cmd->lba_low = lba;
6178         ata_cmd->lba_mid = lba >> 8;
6179         ata_cmd->lba_high = lba >> 16;
6180         ata_cmd->device = ATA_DEV_LBA;
6181         if (protocol & AP_EXTEND) {
6182                 ata_cmd->lba_low_ext = lba >> 24;
6183                 ata_cmd->lba_mid_ext = lba >> 32;
6184                 ata_cmd->lba_high_ext = lba >> 40;
6185         } else
6186                 ata_cmd->device |= (lba >> 24) & 0x0f;
6187         ata_cmd->command = command;
6188         ata_cmd->control = control;
6189
6190         cam_fill_csio(csio,
6191                       retries,
6192                       cbfcnp,
6193                       flags,
6194                       tag_action,
6195                       data_ptr,
6196                       dxfer_len,
6197                       sense_len,
6198                       sizeof(*ata_cmd),
6199                       timeout);
6200 }
6201
6202 void
6203 scsi_unmap(struct ccb_scsiio *csio, u_int32_t retries,
6204            void (*cbfcnp)(struct cam_periph *, union ccb *),
6205            u_int8_t tag_action, u_int8_t byte2,
6206            u_int8_t *data_ptr, u_int16_t dxfer_len, u_int8_t sense_len,
6207            u_int32_t timeout)
6208 {
6209         struct scsi_unmap *scsi_cmd;
6210
6211         scsi_cmd = (struct scsi_unmap *)&csio->cdb_io.cdb_bytes;
6212         scsi_cmd->opcode = UNMAP;
6213         scsi_cmd->byte2 = byte2;
6214         scsi_ulto4b(0, scsi_cmd->reserved);
6215         scsi_cmd->group = 0;
6216         scsi_ulto2b(dxfer_len, scsi_cmd->length);
6217         scsi_cmd->control = 0;
6218
6219         cam_fill_csio(csio,
6220                       retries,
6221                       cbfcnp,
6222                       /*flags*/CAM_DIR_OUT,
6223                       tag_action,
6224                       data_ptr,
6225                       dxfer_len,
6226                       sense_len,
6227                       sizeof(*scsi_cmd),
6228                       timeout);
6229 }
6230
6231 void
6232 scsi_receive_diagnostic_results(struct ccb_scsiio *csio, u_int32_t retries,
6233                                 void (*cbfcnp)(struct cam_periph *, union ccb*),
6234                                 uint8_t tag_action, int pcv, uint8_t page_code,
6235                                 uint8_t *data_ptr, uint16_t allocation_length,
6236                                 uint8_t sense_len, uint32_t timeout)
6237 {
6238         struct scsi_receive_diag *scsi_cmd;
6239
6240         scsi_cmd = (struct scsi_receive_diag *)&csio->cdb_io.cdb_bytes;
6241         memset(scsi_cmd, 0, sizeof(*scsi_cmd));
6242         scsi_cmd->opcode = RECEIVE_DIAGNOSTIC;
6243         if (pcv) {
6244                 scsi_cmd->byte2 |= SRD_PCV;
6245                 scsi_cmd->page_code = page_code;
6246         }
6247         scsi_ulto2b(allocation_length, scsi_cmd->length);
6248
6249         cam_fill_csio(csio,
6250                       retries,
6251                       cbfcnp,
6252                       /*flags*/CAM_DIR_IN,
6253                       tag_action,
6254                       data_ptr,
6255                       allocation_length,
6256                       sense_len,
6257                       sizeof(*scsi_cmd),
6258                       timeout);
6259 }
6260
6261 void
6262 scsi_send_diagnostic(struct ccb_scsiio *csio, u_int32_t retries,
6263                      void (*cbfcnp)(struct cam_periph *, union ccb *),
6264                      uint8_t tag_action, int unit_offline, int device_offline,
6265                      int self_test, int page_format, int self_test_code,
6266                      uint8_t *data_ptr, uint16_t param_list_length,
6267                      uint8_t sense_len, uint32_t timeout)
6268 {
6269         struct scsi_send_diag *scsi_cmd;
6270
6271         scsi_cmd = (struct scsi_send_diag *)&csio->cdb_io.cdb_bytes;
6272         memset(scsi_cmd, 0, sizeof(*scsi_cmd));
6273         scsi_cmd->opcode = SEND_DIAGNOSTIC;
6274
6275         /*
6276          * The default self-test mode control and specific test
6277          * control are mutually exclusive.
6278          */
6279         if (self_test)
6280                 self_test_code = SSD_SELF_TEST_CODE_NONE;
6281
6282         scsi_cmd->byte2 = ((self_test_code << SSD_SELF_TEST_CODE_SHIFT)
6283                          & SSD_SELF_TEST_CODE_MASK)
6284                         | (unit_offline   ? SSD_UNITOFFL : 0)
6285                         | (device_offline ? SSD_DEVOFFL  : 0)
6286                         | (self_test      ? SSD_SELFTEST : 0)
6287                         | (page_format    ? SSD_PF       : 0);
6288         scsi_ulto2b(param_list_length, scsi_cmd->length);
6289
6290         cam_fill_csio(csio,
6291                       retries,
6292                       cbfcnp,
6293                       /*flags*/param_list_length ? CAM_DIR_OUT : CAM_DIR_NONE,
6294                       tag_action,
6295                       data_ptr,
6296                       param_list_length,
6297                       sense_len,
6298                       sizeof(*scsi_cmd),
6299                       timeout);
6300 }
6301
6302 void
6303 scsi_read_buffer(struct ccb_scsiio *csio, u_int32_t retries,
6304                         void (*cbfcnp)(struct cam_periph *, union ccb*),
6305                         uint8_t tag_action, int mode,
6306                         uint8_t buffer_id, u_int32_t offset,
6307                         uint8_t *data_ptr, uint32_t allocation_length,
6308                         uint8_t sense_len, uint32_t timeout)
6309 {
6310         struct scsi_read_buffer *scsi_cmd;
6311
6312         scsi_cmd = (struct scsi_read_buffer *)&csio->cdb_io.cdb_bytes;
6313         memset(scsi_cmd, 0, sizeof(*scsi_cmd));
6314         scsi_cmd->opcode = READ_BUFFER;
6315         scsi_cmd->byte2 = mode;
6316         scsi_cmd->buffer_id = buffer_id;
6317         scsi_ulto3b(offset, scsi_cmd->offset);
6318         scsi_ulto3b(allocation_length, scsi_cmd->length);
6319
6320         cam_fill_csio(csio,
6321                       retries,
6322                       cbfcnp,
6323                       /*flags*/CAM_DIR_IN,
6324                       tag_action,
6325                       data_ptr,
6326                       allocation_length,
6327                       sense_len,
6328                       sizeof(*scsi_cmd),
6329                       timeout);
6330 }
6331
6332 void
6333 scsi_write_buffer(struct ccb_scsiio *csio, u_int32_t retries,
6334                         void (*cbfcnp)(struct cam_periph *, union ccb *),
6335                         uint8_t tag_action, int mode,
6336                         uint8_t buffer_id, u_int32_t offset,
6337                         uint8_t *data_ptr, uint32_t param_list_length,
6338                         uint8_t sense_len, uint32_t timeout)
6339 {
6340         struct scsi_write_buffer *scsi_cmd;
6341
6342         scsi_cmd = (struct scsi_write_buffer *)&csio->cdb_io.cdb_bytes;
6343         memset(scsi_cmd, 0, sizeof(*scsi_cmd));
6344         scsi_cmd->opcode = WRITE_BUFFER;
6345         scsi_cmd->byte2 = mode;
6346         scsi_cmd->buffer_id = buffer_id;
6347         scsi_ulto3b(offset, scsi_cmd->offset);
6348         scsi_ulto3b(param_list_length, scsi_cmd->length);
6349
6350         cam_fill_csio(csio,
6351                       retries,
6352                       cbfcnp,
6353                       /*flags*/param_list_length ? CAM_DIR_OUT : CAM_DIR_NONE,
6354                       tag_action,
6355                       data_ptr,
6356                       param_list_length,
6357                       sense_len,
6358                       sizeof(*scsi_cmd),
6359                       timeout);
6360 }
6361
6362 void 
6363 scsi_start_stop(struct ccb_scsiio *csio, u_int32_t retries,
6364                 void (*cbfcnp)(struct cam_periph *, union ccb *),
6365                 u_int8_t tag_action, int start, int load_eject,
6366                 int immediate, u_int8_t sense_len, u_int32_t timeout)
6367 {
6368         struct scsi_start_stop_unit *scsi_cmd;
6369         int extra_flags = 0;
6370
6371         scsi_cmd = (struct scsi_start_stop_unit *)&csio->cdb_io.cdb_bytes;
6372         bzero(scsi_cmd, sizeof(*scsi_cmd));
6373         scsi_cmd->opcode = START_STOP_UNIT;
6374         if (start != 0) {
6375                 scsi_cmd->how |= SSS_START;
6376                 /* it takes a lot of power to start a drive */
6377                 extra_flags |= CAM_HIGH_POWER;
6378         }
6379         if (load_eject != 0)
6380                 scsi_cmd->how |= SSS_LOEJ;
6381         if (immediate != 0)
6382                 scsi_cmd->byte2 |= SSS_IMMED;
6383
6384         cam_fill_csio(csio,
6385                       retries,
6386                       cbfcnp,
6387                       /*flags*/CAM_DIR_NONE | extra_flags,
6388                       tag_action,
6389                       /*data_ptr*/NULL,
6390                       /*dxfer_len*/0,
6391                       sense_len,
6392                       sizeof(*scsi_cmd),
6393                       timeout);
6394 }
6395
6396
6397 /*      
6398  * Try make as good a match as possible with
6399  * available sub drivers
6400  */
6401 int
6402 scsi_inquiry_match(caddr_t inqbuffer, caddr_t table_entry)
6403 {
6404         struct scsi_inquiry_pattern *entry;
6405         struct scsi_inquiry_data *inq;
6406  
6407         entry = (struct scsi_inquiry_pattern *)table_entry;
6408         inq = (struct scsi_inquiry_data *)inqbuffer;
6409
6410         if (((SID_TYPE(inq) == entry->type)
6411           || (entry->type == T_ANY))
6412          && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE
6413                                    : entry->media_type & SIP_MEDIA_FIXED)
6414          && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0)
6415          && (cam_strmatch(inq->product, entry->product,
6416                           sizeof(inq->product)) == 0)
6417          && (cam_strmatch(inq->revision, entry->revision,
6418                           sizeof(inq->revision)) == 0)) {
6419                 return (0);
6420         }
6421         return (-1);
6422 }
6423
6424 /*      
6425  * Try make as good a match as possible with
6426  * available sub drivers
6427  */
6428 int
6429 scsi_static_inquiry_match(caddr_t inqbuffer, caddr_t table_entry)
6430 {
6431         struct scsi_static_inquiry_pattern *entry;
6432         struct scsi_inquiry_data *inq;
6433  
6434         entry = (struct scsi_static_inquiry_pattern *)table_entry;
6435         inq = (struct scsi_inquiry_data *)inqbuffer;
6436
6437         if (((SID_TYPE(inq) == entry->type)
6438           || (entry->type == T_ANY))
6439          && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE
6440                                    : entry->media_type & SIP_MEDIA_FIXED)
6441          && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0)
6442          && (cam_strmatch(inq->product, entry->product,
6443                           sizeof(inq->product)) == 0)
6444          && (cam_strmatch(inq->revision, entry->revision,
6445                           sizeof(inq->revision)) == 0)) {
6446                 return (0);
6447         }
6448         return (-1);
6449 }
6450
6451 /**
6452  * Compare two buffers of vpd device descriptors for a match.
6453  *
6454  * \param lhs      Pointer to first buffer of descriptors to compare.
6455  * \param lhs_len  The length of the first buffer.
6456  * \param rhs      Pointer to second buffer of descriptors to compare.
6457  * \param rhs_len  The length of the second buffer.
6458  *
6459  * \return  0 on a match, -1 otherwise.
6460  *
6461  * Treat rhs and lhs as arrays of vpd device id descriptors.  Walk lhs matching
6462  * agains each element in rhs until all data are exhausted or we have found
6463  * a match.
6464  */
6465 int
6466 scsi_devid_match(uint8_t *lhs, size_t lhs_len, uint8_t *rhs, size_t rhs_len)
6467 {
6468         struct scsi_vpd_id_descriptor *lhs_id;
6469         struct scsi_vpd_id_descriptor *lhs_last;
6470         struct scsi_vpd_id_descriptor *rhs_last;
6471         uint8_t *lhs_end;
6472         uint8_t *rhs_end;
6473
6474         lhs_end = lhs + lhs_len;
6475         rhs_end = rhs + rhs_len;
6476
6477         /*
6478          * rhs_last and lhs_last are the last posible position of a valid
6479          * descriptor assuming it had a zero length identifier.  We use
6480          * these variables to insure we can safely dereference the length
6481          * field in our loop termination tests.
6482          */
6483         lhs_last = (struct scsi_vpd_id_descriptor *)
6484             (lhs_end - __offsetof(struct scsi_vpd_id_descriptor, identifier));
6485         rhs_last = (struct scsi_vpd_id_descriptor *)
6486             (rhs_end - __offsetof(struct scsi_vpd_id_descriptor, identifier));
6487
6488         lhs_id = (struct scsi_vpd_id_descriptor *)lhs;
6489         while (lhs_id <= lhs_last
6490             && (lhs_id->identifier + lhs_id->length) <= lhs_end) {
6491                 struct scsi_vpd_id_descriptor *rhs_id;
6492
6493                 rhs_id = (struct scsi_vpd_id_descriptor *)rhs;
6494                 while (rhs_id <= rhs_last
6495                     && (rhs_id->identifier + rhs_id->length) <= rhs_end) {
6496
6497                         if (rhs_id->length == lhs_id->length
6498                          && memcmp(rhs_id->identifier, lhs_id->identifier,
6499                                    rhs_id->length) == 0)
6500                                 return (0);
6501
6502                         rhs_id = (struct scsi_vpd_id_descriptor *)
6503                            (rhs_id->identifier + rhs_id->length);
6504                 }
6505                 lhs_id = (struct scsi_vpd_id_descriptor *)
6506                    (lhs_id->identifier + lhs_id->length);
6507         }
6508         return (-1);
6509 }
6510
6511 #ifdef _KERNEL
6512 int
6513 scsi_vpd_supported_page(struct cam_periph *periph, uint8_t page_id)
6514 {
6515         struct cam_ed *device;
6516         struct scsi_vpd_supported_pages *vpds;
6517         int i, num_pages;
6518
6519         device = periph->path->device;
6520         vpds = (struct scsi_vpd_supported_pages *)device->supported_vpds;
6521
6522         if (vpds != NULL) {
6523                 num_pages = device->supported_vpds_len -
6524                     SVPD_SUPPORTED_PAGES_HDR_LEN;
6525                 for (i = 0; i < num_pages; i++) {
6526                         if (vpds->page_list[i] == page_id)
6527                                 return (1);
6528                 }
6529         }
6530
6531         return (0);
6532 }
6533
6534 static void
6535 init_scsi_delay(void)
6536 {
6537         int delay;
6538
6539         delay = SCSI_DELAY;
6540         TUNABLE_INT_FETCH("kern.cam.scsi_delay", &delay);
6541
6542         if (set_scsi_delay(delay) != 0) {
6543                 printf("cam: invalid value for tunable kern.cam.scsi_delay\n");
6544                 set_scsi_delay(SCSI_DELAY);
6545         }
6546 }
6547 SYSINIT(scsi_delay, SI_SUB_TUNABLES, SI_ORDER_ANY, init_scsi_delay, NULL);
6548
6549 static int
6550 sysctl_scsi_delay(SYSCTL_HANDLER_ARGS)
6551 {
6552         int error, delay;
6553
6554         delay = scsi_delay;
6555         error = sysctl_handle_int(oidp, &delay, 0, req);
6556         if (error != 0 || req->newptr == NULL)
6557                 return (error);
6558         return (set_scsi_delay(delay));
6559 }
6560 SYSCTL_PROC(_kern_cam, OID_AUTO, scsi_delay, CTLTYPE_INT|CTLFLAG_RW,
6561     0, 0, sysctl_scsi_delay, "I",
6562     "Delay to allow devices to settle after a SCSI bus reset (ms)");
6563
6564 static int
6565 set_scsi_delay(int delay)
6566 {
6567         /*
6568          * If someone sets this to 0, we assume that they want the
6569          * minimum allowable bus settle delay.
6570          */
6571         if (delay == 0) {
6572                 printf("cam: using minimum scsi_delay (%dms)\n",
6573                     SCSI_MIN_DELAY);
6574                 delay = SCSI_MIN_DELAY;
6575         }
6576         if (delay < SCSI_MIN_DELAY)
6577                 return (EINVAL);
6578         scsi_delay = delay;
6579         return (0);
6580 }
6581 #endif /* _KERNEL */