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