scsi_all.c revision 187243
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 187243 2009-01-14 21:25:17Z trasz $");
32
33#include <sys/param.h>
34
35#ifdef _KERNEL
36#include <opt_scsi.h>
37
38#include <sys/systm.h>
39#include <sys/libkern.h>
40#include <sys/kernel.h>
41#include <sys/sysctl.h>
42#else
43#include <errno.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47#endif
48
49#include <cam/cam.h>
50#include <cam/cam_ccb.h>
51#include <cam/cam_xpt.h>
52#include <cam/scsi/scsi_all.h>
53#include <sys/sbuf.h>
54#ifndef _KERNEL
55#include <camlib.h>
56
57#ifndef FALSE
58#define FALSE   0
59#endif /* FALSE */
60#ifndef TRUE
61#define TRUE    1
62#endif /* TRUE */
63#define ERESTART        -1              /* restart syscall */
64#define EJUSTRETURN     -2              /* don't modify regs, just return */
65#endif /* !_KERNEL */
66
67/*
68 * This is the default number of milliseconds we wait for devices to settle
69 * after a SCSI bus reset.
70 */
71#ifndef SCSI_DELAY
72#define SCSI_DELAY 2000
73#endif
74/*
75 * All devices need _some_ sort of bus settle delay, so we'll set it to
76 * a minimum value of 100ms. Note that this is pertinent only for SPI-
77 * not transport like Fibre Channel or iSCSI where 'delay' is completely
78 * meaningless.
79 */
80#ifndef SCSI_MIN_DELAY
81#define SCSI_MIN_DELAY 100
82#endif
83/*
84 * Make sure the user isn't using seconds instead of milliseconds.
85 */
86#if (SCSI_DELAY < SCSI_MIN_DELAY && SCSI_DELAY != 0)
87#error "SCSI_DELAY is in milliseconds, not seconds!  Please use a larger value"
88#endif
89
90int scsi_delay;
91
92static int	ascentrycomp(const void *key, const void *member);
93static int	senseentrycomp(const void *key, const void *member);
94static void	fetchtableentries(int sense_key, int asc, int ascq,
95				  struct scsi_inquiry_data *,
96				  const struct sense_key_table_entry **,
97				  const struct asc_table_entry **);
98#ifdef _KERNEL
99static void	init_scsi_delay(void);
100static int	sysctl_scsi_delay(SYSCTL_HANDLER_ARGS);
101static int	set_scsi_delay(int delay);
102#endif
103
104#if !defined(SCSI_NO_OP_STRINGS)
105
106#define	D	(1 << T_DIRECT)
107#define	T	(1 << T_SEQUENTIAL)
108#define	L	(1 << T_PRINTER)
109#define	P	(1 << T_PROCESSOR)
110#define	W	(1 << T_WORM)
111#define	R	(1 << T_CDROM)
112#define	O	(1 << T_OPTICAL)
113#define	M	(1 << T_CHANGER)
114#define	A	(1 << T_STORARRAY)
115#define	E	(1 << T_ENCLOSURE)
116#define	B	(1 << T_RBC)
117#define	K	(1 << T_OCRW)
118#define	V	(1 << T_ADC)
119#define	F	(1 << T_OSD)
120#define	S	(1 << T_SCANNER)
121#define	C	(1 << T_COMM)
122
123#define ALL	(D | T | L | P | W | R | O | M | A | E | B | K | V | F | S | C)
124
125static struct op_table_entry plextor_cd_ops[] = {
126	{ 0xD8, R, "CD-DA READ" }
127};
128
129static struct scsi_op_quirk_entry scsi_op_quirk_table[] = {
130	{
131		/*
132		 * I believe that 0xD8 is the Plextor proprietary command
133		 * to read CD-DA data.  I'm not sure which Plextor CDROM
134		 * models support the command, though.  I know for sure
135		 * that the 4X, 8X, and 12X models do, and presumably the
136		 * 12-20X does.  I don't know about any earlier models,
137		 * though.  If anyone has any more complete information,
138		 * feel free to change this quirk entry.
139		 */
140		{T_CDROM, SIP_MEDIA_REMOVABLE, "PLEXTOR", "CD-ROM PX*", "*"},
141		sizeof(plextor_cd_ops)/sizeof(struct op_table_entry),
142		plextor_cd_ops
143	}
144};
145
146static struct op_table_entry scsi_op_codes[] = {
147	/*
148	 * From: http://www.t10.org/lists/op-num.txt
149	 * Modifications by Kenneth Merry (ken@FreeBSD.ORG)
150	 *              and Jung-uk Kim (jkim@FreeBSD.org)
151	 *
152	 * Note:  order is important in this table, scsi_op_desc() currently
153	 * depends on the opcodes in the table being in order to save
154	 * search time.
155	 * Note:  scanner and comm. devices are carried over from the previous
156	 * version because they were removed in the latest spec.
157	 */
158	/* File: OP-NUM.TXT
159	 *
160	 * SCSI Operation Codes
161	 * Numeric Sorted Listing
162	 * as of  3/11/08
163	 *
164	 *     D - DIRECT ACCESS DEVICE (SBC-2)                device column key
165	 *     .T - SEQUENTIAL ACCESS DEVICE (SSC-2)           -----------------
166	 *     . L - PRINTER DEVICE (SSC)                      M = Mandatory
167	 *     .  P - PROCESSOR DEVICE (SPC)                   O = Optional
168	 *     .  .W - WRITE ONCE READ MULTIPLE DEVICE (SBC-2) V = Vendor spec.
169	 *     .  . R - CD/DVE DEVICE (MMC-3)                  Z = Obsolete
170	 *     .  .  O - OPTICAL MEMORY DEVICE (SBC-2)
171	 *     .  .  .M - MEDIA CHANGER DEVICE (SMC-2)
172	 *     .  .  . A - STORAGE ARRAY DEVICE (SCC-2)
173	 *     .  .  . .E - ENCLOSURE SERVICES DEVICE (SES)
174	 *     .  .  .  .B - SIMPLIFIED DIRECT-ACCESS DEVICE (RBC)
175	 *     .  .  .  . K - OPTICAL CARD READER/WRITER DEVICE (OCRW)
176	 *     .  .  .  .  V - AUTOMATION/DRIVE INTERFACE (ADC)
177	 *     .  .  .  .  .F - OBJECT-BASED STORAGE (OSD)
178	 * OP  DTLPWROMAEBKVF  Description
179	 * --  --------------  ---------------------------------------------- */
180	/* 00  MMMMMMMMMMMMMM  TEST UNIT READY */
181	{ 0x00,	ALL, "TEST UNIT READY" },
182	/* 01   M              REWIND */
183	{ 0x01,	T, "REWIND" },
184	/* 01  Z V ZZZZ        REZERO UNIT */
185	{ 0x01,	D | W | R | O | M, "REZERO UNIT" },
186	/* 02  VVVVVV V */
187	/* 03  MMMMMMMMMMOMMM  REQUEST SENSE */
188	{ 0x03,	ALL, "REQUEST SENSE" },
189	/* 04  M    OO         FORMAT UNIT */
190	{ 0x04,	D | R | O, "FORMAT UNIT" },
191	/* 04   O              FORMAT MEDIUM */
192	{ 0x04,	T, "FORMAT MEDIUM" },
193	/* 04    O             FORMAT */
194	{ 0x04,	L, "FORMAT" },
195	/* 05  VMVVVV V        READ BLOCK LIMITS */
196	{ 0x05,	T, "READ BLOCK LIMITS" },
197	/* 06  VVVVVV V */
198	/* 07  OVV O OV        REASSIGN BLOCKS */
199	{ 0x07,	D | W | O, "REASSIGN BLOCKS" },
200	/* 07         O        INITIALIZE ELEMENT STATUS */
201	{ 0x07,	M, "INITIALIZE ELEMENT STATUS" },
202	/* 08  MOV O OV        READ(6) */
203	{ 0x08,	D | T | W | O, "READ(6)" },
204	/* 08     O            RECEIVE */
205	{ 0x08,	P, "RECEIVE" },
206	/* 08                  GET MESSAGE(6) */
207	{ 0x08, C, "GET MESSAGE(6)" },
208	/* 09  VVVVVV V */
209	/* 0A  OO  O OV        WRITE(6) */
210	{ 0x0A,	D | T | W | O, "WRITE(6)" },
211	/* 0A     M            SEND(6) */
212	{ 0x0A,	P, "SEND(6)" },
213	/* 0A                  SEND MESSAGE(6) */
214	{ 0x0A, C, "SEND MESSAGE(6)" },
215	/* 0A    M             PRINT */
216	{ 0x0A,	L, "PRINT" },
217	/* 0B  Z   ZOZV        SEEK(6) */
218	{ 0x0B,	D | W | R | O, "SEEK(6)" },
219	/* 0B   O              SET CAPACITY */
220	{ 0x0B,	T, "SET CAPACITY" },
221	/* 0B    O             SLEW AND PRINT */
222	{ 0x0B,	L, "SLEW AND PRINT" },
223	/* 0C  VVVVVV V */
224	/* 0D  VVVVVV V */
225	/* 0E  VVVVVV V */
226	/* 0F  VOVVVV V        READ REVERSE(6) */
227	{ 0x0F,	T, "READ REVERSE(6)" },
228	/* 10  VM VVV          WRITE FILEMARKS(6) */
229	{ 0x10,	T, "WRITE FILEMARKS(6)" },
230	/* 10    O             SYNCHRONIZE BUFFER */
231	{ 0x10,	L, "SYNCHRONIZE BUFFER" },
232	/* 11  VMVVVV          SPACE(6) */
233	{ 0x11,	T, "SPACE(6)" },
234	/* 12  MMMMMMMMMMMMMM  INQUIRY */
235	{ 0x12,	ALL, "INQUIRY" },
236	/* 13  V VVVV */
237	/* 13   O              VERIFY(6) */
238	{ 0x13,	T, "VERIFY(6)" },
239	/* 14  VOOVVV          RECOVER BUFFERED DATA */
240	{ 0x14,	T | L, "RECOVER BUFFERED DATA" },
241	/* 15  OMO O OOOO OO   MODE SELECT(6) */
242	{ 0x15,	ALL & ~(P | R | B | F), "MODE SELECT(6)" },
243	/* 16  ZZMZO OOOZ O    RESERVE(6) */
244	{ 0x16,	ALL & ~(R | B | V | F | C), "RESERVE(6)" },
245	/* 16         Z        RESERVE ELEMENT(6) */
246	{ 0x16,	M, "RESERVE ELEMENT(6)" },
247	/* 17  ZZMZO OOOZ O    RELEASE(6) */
248	{ 0x17,	ALL & ~(R | B | V | F | C), "RELEASE(6)" },
249	/* 17         Z        RELEASE ELEMENT(6) */
250	{ 0x17,	M, "RELEASE ELEMENT(6)" },
251	/* 18  ZZZZOZO    Z    COPY */
252	{ 0x18,	D | T | L | P | W | R | O | K | S, "COPY" },
253	/* 19  VMVVVV          ERASE(6) */
254	{ 0x19,	T, "ERASE(6)" },
255	/* 1A  OMO O OOOO OO   MODE SENSE(6) */
256	{ 0x1A,	ALL & ~(P | R | B | F), "MODE SENSE(6)" },
257	/* 1B  O   OOO O MO O  START STOP UNIT */
258	{ 0x1B,	D | W | R | O | A | B | K | F, "START STOP UNIT" },
259	/* 1B   O          M   LOAD UNLOAD */
260	{ 0x1B,	T | V, "LOAD UNLOAD" },
261	/* 1B                  SCAN */
262	{ 0x1B, S, "SCAN" },
263	/* 1B    O             STOP PRINT */
264	{ 0x1B,	L, "STOP PRINT" },
265	/* 1B         O        OPEN/CLOSE IMPORT/EXPORT ELEMENT */
266	{ 0x1B,	M, "OPEN/CLOSE IMPORT/EXPORT ELEMENT" },
267	/* 1C  OOOOO OOOM OOO  RECEIVE DIAGNOSTIC RESULTS */
268	{ 0x1C,	ALL & ~(R | B), "RECEIVE DIAGNOSTIC RESULTS" },
269	/* 1D  MMMMM MMOM MMM  SEND DIAGNOSTIC */
270	{ 0x1D,	ALL & ~(R | B), "SEND DIAGNOSTIC" },
271	/* 1E  OO  OOOO   O O  PREVENT ALLOW MEDIUM REMOVAL */
272	{ 0x1E,	D | T | W | R | O | M | K | F, "PREVENT ALLOW MEDIUM REMOVAL" },
273	/* 1F */
274	/* 20  V   VVV    V */
275	/* 21  V   VVV    V */
276	/* 22  V   VVV    V */
277	/* 23  V   V V    V */
278	/* 23       O          READ FORMAT CAPACITIES */
279	{ 0x23,	R, "READ FORMAT CAPACITIES" },
280	/* 24  V   VV          SET WINDOW */
281	{ 0x24, S, "SET WINDOW" },
282	/* 25  M   M M   M     READ CAPACITY(10) */
283	{ 0x25,	D | W | O | B, "READ CAPACITY(10)" },
284	/* 25       O          READ CAPACITY */
285	{ 0x25,	R, "READ CAPACITY" },
286	/* 25             M    READ CARD CAPACITY */
287	{ 0x25,	K, "READ CARD CAPACITY" },
288	/* 25                  GET WINDOW */
289	{ 0x25, S, "GET WINDOW" },
290	/* 26  V   VV */
291	/* 27  V   VV */
292	/* 28  M   MOM   MM    READ(10) */
293	{ 0x28,	D | W | R | O | B | K | S, "READ(10)" },
294	/* 28                  GET MESSAGE(10) */
295	{ 0x28, C, "GET MESSAGE(10)" },
296	/* 29  V   VVO         READ GENERATION */
297	{ 0x29,	O, "READ GENERATION" },
298	/* 2A  O   MOM   MO    WRITE(10) */
299	{ 0x2A,	D | W | R | O | B | K, "WRITE(10)" },
300	/* 2A                  SEND(10) */
301	{ 0x2A, S, "SEND(10)" },
302	/* 2A                  SEND MESSAGE(10) */
303	{ 0x2A, C, "SEND MESSAGE(10)" },
304	/* 2B  Z   OOO    O    SEEK(10) */
305	{ 0x2B,	D | W | R | O | K, "SEEK(10)" },
306	/* 2B   O              LOCATE(10) */
307	{ 0x2B,	T, "LOCATE(10)" },
308	/* 2B         O        POSITION TO ELEMENT */
309	{ 0x2B,	M, "POSITION TO ELEMENT" },
310	/* 2C  V    OO         ERASE(10) */
311	{ 0x2C,	R | O, "ERASE(10)" },
312	/* 2D        O         READ UPDATED BLOCK */
313	{ 0x2D,	O, "READ UPDATED BLOCK" },
314	/* 2D  V */
315	/* 2E  O   OOO   MO    WRITE AND VERIFY(10) */
316	{ 0x2E,	D | W | R | O | B | K, "WRITE AND VERIFY(10)" },
317	/* 2F  O   OOO         VERIFY(10) */
318	{ 0x2F,	D | W | R | O, "VERIFY(10)" },
319	/* 30  Z   ZZZ         SEARCH DATA HIGH(10) */
320	{ 0x30,	D | W | R | O, "SEARCH DATA HIGH(10)" },
321	/* 31  Z   ZZZ         SEARCH DATA EQUAL(10) */
322	{ 0x31,	D | W | R | O, "SEARCH DATA EQUAL(10)" },
323	/* 31                  OBJECT POSITION */
324	{ 0x31, S, "OBJECT POSITION" },
325	/* 32  Z   ZZZ         SEARCH DATA LOW(10) */
326	{ 0x32,	D | W | R | O, "SEARCH DATA LOW(10)" },
327	/* 33  Z   OZO         SET LIMITS(10) */
328	{ 0x33,	D | W | R | O, "SET LIMITS(10)" },
329	/* 34  O   O O    O    PRE-FETCH(10) */
330	{ 0x34,	D | W | O | K, "PRE-FETCH(10)" },
331	/* 34   M              READ POSITION */
332	{ 0x34,	T, "READ POSITION" },
333	/* 34                  GET DATA BUFFER STATUS */
334	{ 0x34, S, "GET DATA BUFFER STATUS" },
335	/* 35  O   OOO   MO    SYNCHRONIZE CACHE(10) */
336	{ 0x35,	D | W | R | O | B | K, "SYNCHRONIZE CACHE(10)" },
337	/* 36  Z   O O    O    LOCK UNLOCK CACHE(10) */
338	{ 0x36,	D | W | O | K, "LOCK UNLOCK CACHE(10)" },
339	/* 37  O     O         READ DEFECT DATA(10) */
340	{ 0x37,	D | O, "READ DEFECT DATA(10)" },
341	/* 37         O        INITIALIZE ELEMENT STATUS WITH RANGE */
342	{ 0x37,	M, "INITIALIZE ELEMENT STATUS WITH RANGE" },
343	/* 38      O O    O    MEDIUM SCAN */
344	{ 0x38,	W | O | K, "MEDIUM SCAN" },
345	/* 39  ZZZZOZO    Z    COMPARE */
346	{ 0x39,	D | T | L | P | W | R | O | K | S, "COMPARE" },
347	/* 3A  ZZZZOZO    Z    COPY AND VERIFY */
348	{ 0x3A,	D | T | L | P | W | R | O | K | S, "COPY AND VERIFY" },
349	/* 3B  OOOOOOOOOOMOOO  WRITE BUFFER */
350	{ 0x3B,	ALL, "WRITE BUFFER" },
351	/* 3C  OOOOOOOOOO OOO  READ BUFFER */
352	{ 0x3C,	ALL & ~(B), "READ BUFFER" },
353	/* 3D        O         UPDATE BLOCK */
354	{ 0x3D,	O, "UPDATE BLOCK" },
355	/* 3E  O   O O         READ LONG(10) */
356	{ 0x3E,	D | W | O, "READ LONG(10)" },
357	/* 3F  O   O O         WRITE LONG(10) */
358	{ 0x3F,	D | W | O, "WRITE LONG(10)" },
359	/* 40  ZZZZOZOZ        CHANGE DEFINITION */
360	{ 0x40,	D | T | L | P | W | R | O | M | S | C, "CHANGE DEFINITION" },
361	/* 41  O               WRITE SAME(10) */
362	{ 0x41,	D, "WRITE SAME(10)" },
363	/* 42       O          READ SUB-CHANNEL */
364	{ 0x42,	R, "READ SUB-CHANNEL" },
365	/* 43       O          READ TOC/PMA/ATIP */
366	{ 0x43,	R, "READ TOC/PMA/ATIP" },
367	/* 44   M          M   REPORT DENSITY SUPPORT */
368	{ 0x44,	T | V, "REPORT DENSITY SUPPORT" },
369	/* 44                  READ HEADER */
370	/* 45       O          PLAY AUDIO(10) */
371	{ 0x45,	R, "PLAY AUDIO(10)" },
372	/* 46       M          GET CONFIGURATION */
373	{ 0x46,	R, "GET CONFIGURATION" },
374	/* 47       O          PLAY AUDIO MSF */
375	{ 0x47,	R, "PLAY AUDIO MSF" },
376	/* 48 */
377	/* 49 */
378	/* 4A       M          GET EVENT STATUS NOTIFICATION */
379	{ 0x4A,	R, "GET EVENT STATUS NOTIFICATION" },
380	/* 4B       O          PAUSE/RESUME */
381	{ 0x4B,	R, "PAUSE/RESUME" },
382	/* 4C  OOOOO OOOO OOO  LOG SELECT */
383	{ 0x4C,	ALL & ~(R | B), "LOG SELECT" },
384	/* 4D  OOOOO OOOO OMO  LOG SENSE */
385	{ 0x4D,	ALL & ~(R | B), "LOG SENSE" },
386	/* 4E       O          STOP PLAY/SCAN */
387	{ 0x4E,	R, "STOP PLAY/SCAN" },
388	/* 4F */
389	/* 50  O               XDWRITE(10) */
390	{ 0x50,	D, "XDWRITE(10)" },
391	/* 51  O               XPWRITE(10) */
392	{ 0x51,	D, "XPWRITE(10)" },
393	/* 51       O          READ DISC INFORMATION */
394	{ 0x51,	R, "READ DISC INFORMATION" },
395	/* 52  O               XDREAD(10) */
396	{ 0x52,	D, "XDREAD(10)" },
397	/* 52       O          READ TRACK INFORMATION */
398	{ 0x52,	R, "READ TRACK INFORMATION" },
399	/* 53       O          RESERVE TRACK */
400	{ 0x53,	R, "RESERVE TRACK" },
401	/* 54       O          SEND OPC INFORMATION */
402	{ 0x54,	R, "SEND OPC INFORMATION" },
403	/* 55  OOO OMOOOOMOMO  MODE SELECT(10) */
404	{ 0x55,	ALL & ~(P), "MODE SELECT(10)" },
405	/* 56  ZZMZO OOOZ      RESERVE(10) */
406	{ 0x56,	ALL & ~(R | B | K | V | F | C), "RESERVE(10)" },
407	/* 56         Z        RESERVE ELEMENT(10) */
408	{ 0x56,	M, "RESERVE ELEMENT(10)" },
409	/* 57  ZZMZO OOOZ      RELEASE(10) */
410	{ 0x57,	ALL & ~(R | B | K | V | F | C), "RELEASE(10)" },
411	/* 57         Z        RELEASE ELEMENT(10) */
412	{ 0x57,	M, "RELEASE ELEMENT(10)" },
413	/* 58       O          REPAIR TRACK */
414	{ 0x58,	R, "REPAIR TRACK" },
415	/* 59 */
416	/* 5A  OOO OMOOOOMOMO  MODE SENSE(10) */
417	{ 0x5A,	ALL & ~(P), "MODE SENSE(10)" },
418	/* 5B       O          CLOSE TRACK/SESSION */
419	{ 0x5B,	R, "CLOSE TRACK/SESSION" },
420	/* 5C       O          READ BUFFER CAPACITY */
421	{ 0x5C,	R, "READ BUFFER CAPACITY" },
422	/* 5D       O          SEND CUE SHEET */
423	{ 0x5D,	R, "SEND CUE SHEET" },
424	/* 5E  OOOOO OOOO   M  PERSISTENT RESERVE IN */
425	{ 0x5E,	ALL & ~(R | B | K | V | C), "PERSISTENT RESERVE IN" },
426	/* 5F  OOOOO OOOO   M  PERSISTENT RESERVE OUT */
427	{ 0x5F,	ALL & ~(R | B | K | V | C), "PERSISTENT RESERVE OUT" },
428	/* 7E  OO   O OOOO O   extended CDB */
429	{ 0x7E,	D | T | R | M | A | E | B | V, "extended CDB" },
430	/* 7F  O            M  variable length CDB (more than 16 bytes) */
431	{ 0x7F,	D | F, "variable length CDB (more than 16 bytes)" },
432	/* 80  Z               XDWRITE EXTENDED(16) */
433	{ 0x80,	D, "XDWRITE EXTENDED(16)" },
434	/* 80   M              WRITE FILEMARKS(16) */
435	{ 0x80,	T, "WRITE FILEMARKS(16)" },
436	/* 81  Z               REBUILD(16) */
437	{ 0x81,	D, "REBUILD(16)" },
438	/* 81   O              READ REVERSE(16) */
439	{ 0x81,	T, "READ REVERSE(16)" },
440	/* 82  Z               REGENERATE(16) */
441	{ 0x82,	D, "REGENERATE(16)" },
442	/* 83  OOOOO O    OO   EXTENDED COPY */
443	{ 0x83,	D | T | L | P | W | O | K | V, "EXTENDED COPY" },
444	/* 84  OOOOO O    OO   RECEIVE COPY RESULTS */
445	{ 0x84,	D | T | L | P | W | O | K | V, "RECEIVE COPY RESULTS" },
446	/* 85  O    O    O     ATA COMMAND PASS THROUGH(16) */
447	{ 0x85,	D | R | B, "ATA COMMAND PASS THROUGH(16)" },
448	/* 86  OO OO OOOOOOO   ACCESS CONTROL IN */
449	{ 0x86,	ALL & ~(L | R | F), "ACCESS CONTROL IN" },
450	/* 87  OO OO OOOOOOO   ACCESS CONTROL OUT */
451	{ 0x87,	ALL & ~(L | R | F), "ACCESS CONTROL OUT" },
452	/*
453	 * XXX READ(16)/WRITE(16) were not listed for CD/DVE in op-num.txt
454	 * but we had it since r1.40.  Do we really want them?
455	 */
456	/* 88  MM  O O   O     READ(16) */
457	{ 0x88,	D | T | W | O | B, "READ(16)" },
458	/* 89 */
459	/* 8A  OM  O O   O     WRITE(16) */
460	{ 0x8A,	D | T | W | O | B, "WRITE(16)" },
461	/* 8B  O               ORWRITE */
462	{ 0x8B,	D, "ORWRITE" },
463	/* 8C  OO  O OO  O M   READ ATTRIBUTE */
464	{ 0x8C,	D | T | W | O | M | B | V, "READ ATTRIBUTE" },
465	/* 8D  OO  O OO  O O   WRITE ATTRIBUTE */
466	{ 0x8D,	D | T | W | O | M | B | V, "WRITE ATTRIBUTE" },
467	/* 8E  O   O O   O     WRITE AND VERIFY(16) */
468	{ 0x8E,	D | W | O | B, "WRITE AND VERIFY(16)" },
469	/* 8F  OO  O O   O     VERIFY(16) */
470	{ 0x8F,	D | T | W | O | B, "VERIFY(16)" },
471	/* 90  O   O O   O     PRE-FETCH(16) */
472	{ 0x90,	D | W | O | B, "PRE-FETCH(16)" },
473	/* 91  O   O O   O     SYNCHRONIZE CACHE(16) */
474	{ 0x91,	D | W | O | B, "SYNCHRONIZE CACHE(16)" },
475	/* 91   O              SPACE(16) */
476	{ 0x91,	T, "SPACE(16)" },
477	/* 92  Z   O O         LOCK UNLOCK CACHE(16) */
478	{ 0x92,	D | W | O, "LOCK UNLOCK CACHE(16)" },
479	/* 92   O              LOCATE(16) */
480	{ 0x92,	T, "LOCATE(16)" },
481	/* 93  O               WRITE SAME(16) */
482	{ 0x93,	D, "WRITE SAME(16)" },
483	/* 93   M              ERASE(16) */
484	{ 0x93,	T, "ERASE(16)" },
485	/* 94 [usage proposed by SCSI Socket Services project] */
486	/* 95 [usage proposed by SCSI Socket Services project] */
487	/* 96 [usage proposed by SCSI Socket Services project] */
488	/* 97 [usage proposed by SCSI Socket Services project] */
489	/* 98 */
490	/* 99 */
491	/* 9A */
492	/* 9B */
493	/* 9C */
494	/* 9D */
495	/* XXX KDM ALL for this?  op-num.txt defines it for none.. */
496	/* 9E                  SERVICE ACTION IN(16) */
497	{ 0x9E, ALL, "SERVICE ACTION IN(16)" },
498	/* XXX KDM ALL for this?  op-num.txt defines it for ADC.. */
499	/* 9F              M   SERVICE ACTION OUT(16) */
500	{ 0x9F,	ALL, "SERVICE ACTION OUT(16)" },
501	/* A0  MMOOO OMMM OMO  REPORT LUNS */
502	{ 0xA0,	ALL & ~(R | B), "REPORT LUNS" },
503	/* A1       O          BLANK */
504	{ 0xA1,	R, "BLANK" },
505	/* A1  O         O     ATA COMMAND PASS THROUGH(12) */
506	{ 0xA1,	D | B, "ATA COMMAND PASS THROUGH(12)" },
507	/* A2  OO   O      O   SECURITY PROTOCOL IN */
508	{ 0xA2,	D | T | R | V, "SECURITY PROTOCOL IN" },
509	/* A3  OOO O OOMOOOM   MAINTENANCE (IN) */
510	{ 0xA3,	ALL & ~(P | R | F), "MAINTENANCE (IN)" },
511	/* A3       O          SEND KEY */
512	{ 0xA3,	R, "SEND KEY" },
513	/* A4  OOO O OOOOOOO   MAINTENANCE (OUT) */
514	{ 0xA4,	ALL & ~(P | R | F), "MAINTENANCE (OUT)" },
515	/* A4       O          REPORT KEY */
516	{ 0xA4,	R, "REPORT KEY" },
517	/* A5   O  O OM        MOVE MEDIUM */
518	{ 0xA5,	T | W | O | M, "MOVE MEDIUM" },
519	/* A5       O          PLAY AUDIO(12) */
520	{ 0xA5,	R, "PLAY AUDIO(12)" },
521	/* A6         O        EXCHANGE MEDIUM */
522	{ 0xA6,	M, "EXCHANGE MEDIUM" },
523	/* A6       O          LOAD/UNLOAD C/DVD */
524	{ 0xA6,	R, "LOAD/UNLOAD C/DVD" },
525	/* A7  ZZ  O O         MOVE MEDIUM ATTACHED */
526	{ 0xA7,	D | T | W | O, "MOVE MEDIUM ATTACHED" },
527	/* A7       O          SET READ AHEAD */
528	{ 0xA7,	R, "SET READ AHEAD" },
529	/* A8  O   OOO         READ(12) */
530	{ 0xA8,	D | W | R | O, "READ(12)" },
531	/* A8                  GET MESSAGE(12) */
532	{ 0xA8, C, "GET MESSAGE(12)" },
533	/* A9              O   SERVICE ACTION OUT(12) */
534	{ 0xA9,	V, "SERVICE ACTION OUT(12)" },
535	/* AA  O   OOO         WRITE(12) */
536	{ 0xAA,	D | W | R | O, "WRITE(12)" },
537	/* AA                  SEND MESSAGE(12) */
538	{ 0xAA, C, "SEND MESSAGE(12)" },
539	/* AB       O      O   SERVICE ACTION IN(12) */
540	{ 0xAB,	R | V, "SERVICE ACTION IN(12)" },
541	/* AC        O         ERASE(12) */
542	{ 0xAC,	O, "ERASE(12)" },
543	/* AC       O          GET PERFORMANCE */
544	{ 0xAC,	R, "GET PERFORMANCE" },
545	/* AD       O          READ DVD STRUCTURE */
546	{ 0xAD,	R, "READ DVD STRUCTURE" },
547	/* AE  O   O O         WRITE AND VERIFY(12) */
548	{ 0xAE,	D | W | O, "WRITE AND VERIFY(12)" },
549	/* AF  O   OZO         VERIFY(12) */
550	{ 0xAF,	D | W | R | O, "VERIFY(12)" },
551	/* B0      ZZZ         SEARCH DATA HIGH(12) */
552	{ 0xB0,	W | R | O, "SEARCH DATA HIGH(12)" },
553	/* B1      ZZZ         SEARCH DATA EQUAL(12) */
554	{ 0xB1,	W | R | O, "SEARCH DATA EQUAL(12)" },
555	/* B2      ZZZ         SEARCH DATA LOW(12) */
556	{ 0xB2,	W | R | O, "SEARCH DATA LOW(12)" },
557	/* B3  Z   OZO         SET LIMITS(12) */
558	{ 0xB3,	D | W | R | O, "SET LIMITS(12)" },
559	/* B4  ZZ  OZO         READ ELEMENT STATUS ATTACHED */
560	{ 0xB4,	D | T | W | R | O, "READ ELEMENT STATUS ATTACHED" },
561	/* B5  OO   O      O   SECURITY PROTOCOL OUT */
562	{ 0xB5,	D | T | R | V, "SECURITY PROTOCOL OUT" },
563	/* B5         O        REQUEST VOLUME ELEMENT ADDRESS */
564	{ 0xB5,	M, "REQUEST VOLUME ELEMENT ADDRESS" },
565	/* B6         O        SEND VOLUME TAG */
566	{ 0xB6,	M, "SEND VOLUME TAG" },
567	/* B6       O          SET STREAMING */
568	{ 0xB6,	R, "SET STREAMING" },
569	/* B7  O     O         READ DEFECT DATA(12) */
570	{ 0xB7,	D | O, "READ DEFECT DATA(12)" },
571	/* B8   O  OZOM        READ ELEMENT STATUS */
572	{ 0xB8,	T | W | R | O | M, "READ ELEMENT STATUS" },
573	/* B9       O          READ CD MSF */
574	{ 0xB9,	R, "READ CD MSF" },
575	/* BA  O   O OOMO      REDUNDANCY GROUP (IN) */
576	{ 0xBA,	D | W | O | M | A | E, "REDUNDANCY GROUP (IN)" },
577	/* BA       O          SCAN */
578	{ 0xBA,	R, "SCAN" },
579	/* BB  O   O OOOO      REDUNDANCY GROUP (OUT) */
580	{ 0xBB,	D | W | O | M | A | E, "REDUNDANCY GROUP (OUT)" },
581	/* BB       O          SET CD SPEED */
582	{ 0xBB,	R, "SET CD SPEED" },
583	/* BC  O   O OOMO      SPARE (IN) */
584	{ 0xBC,	D | W | O | M | A | E, "SPARE (IN)" },
585	/* BD  O   O OOOO      SPARE (OUT) */
586	{ 0xBD,	D | W | O | M | A | E, "SPARE (OUT)" },
587	/* BD       O          MECHANISM STATUS */
588	{ 0xBD,	R, "MECHANISM STATUS" },
589	/* BE  O   O OOMO      VOLUME SET (IN) */
590	{ 0xBE,	D | W | O | M | A | E, "VOLUME SET (IN)" },
591	/* BE       O          READ CD */
592	{ 0xBE,	R, "READ CD" },
593	/* BF  O   O OOOO      VOLUME SET (OUT) */
594	{ 0xBF,	D | W | O | M | A | E, "VOLUME SET (OUT)" },
595	/* BF       O          SEND DVD STRUCTURE */
596	{ 0xBF,	R, "SEND DVD STRUCTURE" }
597};
598
599const char *
600scsi_op_desc(u_int16_t opcode, struct scsi_inquiry_data *inq_data)
601{
602	caddr_t match;
603	int i, j;
604	u_int32_t opmask;
605	u_int16_t pd_type;
606	int       num_ops[2];
607	struct op_table_entry *table[2];
608	int num_tables;
609
610	pd_type = SID_TYPE(inq_data);
611
612	match = cam_quirkmatch((caddr_t)inq_data,
613			       (caddr_t)scsi_op_quirk_table,
614			       sizeof(scsi_op_quirk_table)/
615			       sizeof(*scsi_op_quirk_table),
616			       sizeof(*scsi_op_quirk_table),
617			       scsi_inquiry_match);
618
619	if (match != NULL) {
620		table[0] = ((struct scsi_op_quirk_entry *)match)->op_table;
621		num_ops[0] = ((struct scsi_op_quirk_entry *)match)->num_ops;
622		table[1] = scsi_op_codes;
623		num_ops[1] = sizeof(scsi_op_codes)/sizeof(scsi_op_codes[0]);
624		num_tables = 2;
625	} else {
626		/*
627		 * If this is true, we have a vendor specific opcode that
628		 * wasn't covered in the quirk table.
629		 */
630		if ((opcode > 0xBF) || ((opcode > 0x5F) && (opcode < 0x80)))
631			return("Vendor Specific Command");
632
633		table[0] = scsi_op_codes;
634		num_ops[0] = sizeof(scsi_op_codes)/sizeof(scsi_op_codes[0]);
635		num_tables = 1;
636	}
637
638	/* RBC is 'Simplified' Direct Access Device */
639	if (pd_type == T_RBC)
640		pd_type = T_DIRECT;
641
642	opmask = 1 << pd_type;
643
644	for (j = 0; j < num_tables; j++) {
645		for (i = 0;i < num_ops[j] && table[j][i].opcode <= opcode; i++){
646			if ((table[j][i].opcode == opcode)
647			 && ((table[j][i].opmask & opmask) != 0))
648				return(table[j][i].desc);
649		}
650	}
651
652	/*
653	 * If we can't find a match for the command in the table, we just
654	 * assume it's a vendor specifc command.
655	 */
656	return("Vendor Specific Command");
657
658}
659
660#else /* SCSI_NO_OP_STRINGS */
661
662const char *
663scsi_op_desc(u_int16_t opcode, struct scsi_inquiry_data *inq_data)
664{
665	return("");
666}
667
668#endif
669
670
671#if !defined(SCSI_NO_SENSE_STRINGS)
672#define SST(asc, ascq, action, desc) \
673	asc, ascq, action, desc
674#else
675const char empty_string[] = "";
676
677#define SST(asc, ascq, action, desc) \
678	asc, ascq, action, empty_string
679#endif
680
681const struct sense_key_table_entry sense_key_table[] =
682{
683	{ SSD_KEY_NO_SENSE, SS_NOP, "NO SENSE" },
684	{ SSD_KEY_RECOVERED_ERROR, SS_NOP|SSQ_PRINT_SENSE, "RECOVERED ERROR" },
685	{
686	  SSD_KEY_NOT_READY, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY,
687	  "NOT READY"
688	},
689	{ SSD_KEY_MEDIUM_ERROR, SS_RDEF, "MEDIUM ERROR" },
690	{ SSD_KEY_HARDWARE_ERROR, SS_RDEF, "HARDWARE FAILURE" },
691	{ SSD_KEY_ILLEGAL_REQUEST, SS_FATAL|EINVAL, "ILLEGAL REQUEST" },
692	{ SSD_KEY_UNIT_ATTENTION, SS_FATAL|ENXIO, "UNIT ATTENTION" },
693	{ SSD_KEY_DATA_PROTECT, SS_FATAL|EACCES, "DATA PROTECT" },
694	{ SSD_KEY_BLANK_CHECK, SS_FATAL|ENOSPC, "BLANK CHECK" },
695	{ SSD_KEY_Vendor_Specific, SS_FATAL|EIO, "Vendor Specific" },
696	{ SSD_KEY_COPY_ABORTED, SS_FATAL|EIO, "COPY ABORTED" },
697	{ SSD_KEY_ABORTED_COMMAND, SS_RDEF, "ABORTED COMMAND" },
698	{ SSD_KEY_EQUAL, SS_NOP, "EQUAL" },
699	{ SSD_KEY_VOLUME_OVERFLOW, SS_FATAL|EIO, "VOLUME OVERFLOW" },
700	{ SSD_KEY_MISCOMPARE, SS_NOP, "MISCOMPARE" },
701	{ SSD_KEY_RESERVED, SS_FATAL|EIO, "RESERVED" }
702};
703
704const int sense_key_table_size =
705    sizeof(sense_key_table)/sizeof(sense_key_table[0]);
706
707static struct asc_table_entry quantum_fireball_entries[] = {
708	{ SST(0x04, 0x0b, SS_START | SSQ_DECREMENT_COUNT | ENXIO,
709	     "Logical unit not ready, initializing cmd. required") }
710};
711
712static struct asc_table_entry sony_mo_entries[] = {
713	{ SST(0x04, 0x00, SS_START | SSQ_DECREMENT_COUNT | ENXIO,
714	     "Logical unit not ready, cause not reportable") }
715};
716
717static struct scsi_sense_quirk_entry sense_quirk_table[] = {
718	{
719		/*
720		 * XXX The Quantum Fireball ST and SE like to return 0x04 0x0b
721		 * when they really should return 0x04 0x02.
722		 */
723		{T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "FIREBALL S*", "*"},
724		/*num_sense_keys*/0,
725		sizeof(quantum_fireball_entries)/sizeof(struct asc_table_entry),
726		/*sense key entries*/NULL,
727		quantum_fireball_entries
728	},
729	{
730		/*
731		 * This Sony MO drive likes to return 0x04, 0x00 when it
732		 * isn't spun up.
733		 */
734		{T_DIRECT, SIP_MEDIA_REMOVABLE, "SONY", "SMO-*", "*"},
735		/*num_sense_keys*/0,
736		sizeof(sony_mo_entries)/sizeof(struct asc_table_entry),
737		/*sense key entries*/NULL,
738		sony_mo_entries
739	}
740};
741
742const int sense_quirk_table_size =
743    sizeof(sense_quirk_table)/sizeof(sense_quirk_table[0]);
744
745static struct asc_table_entry asc_table[] = {
746	/*
747	 * From: http://www.t10.org/lists/asc-num.txt
748	 * Modifications by Jung-uk Kim (jkim@FreeBSD.org)
749	 */
750	/*
751	 * File: ASC-NUM.TXT
752	 *
753	 * SCSI ASC/ASCQ Assignments
754	 * Numeric Sorted Listing
755	 * as of  7/29/08
756	 *
757	 * D - DIRECT ACCESS DEVICE (SBC-2)                   device column key
758	 * .T - SEQUENTIAL ACCESS DEVICE (SSC)               -------------------
759	 * . L - PRINTER DEVICE (SSC)                           blank = reserved
760	 * .  P - PROCESSOR DEVICE (SPC)                     not blank = allowed
761	 * .  .W - WRITE ONCE READ MULTIPLE DEVICE (SBC-2)
762	 * .  . R - CD DEVICE (MMC)
763	 * .  .  O - OPTICAL MEMORY DEVICE (SBC-2)
764	 * .  .  .M - MEDIA CHANGER DEVICE (SMC)
765	 * .  .  . A - STORAGE ARRAY DEVICE (SCC)
766	 * .  .  .  E - ENCLOSURE SERVICES DEVICE (SES)
767	 * .  .  .  .B - SIMPLIFIED DIRECT-ACCESS DEVICE (RBC)
768	 * .  .  .  . K - OPTICAL CARD READER/WRITER DEVICE (OCRW)
769	 * .  .  .  .  V - AUTOMATION/DRIVE INTERFACE (ADC)
770	 * .  .  .  .  .F - OBJECT-BASED STORAGE (OSD)
771	 * DTLPWROMAEBKVF
772	 * ASC      ASCQ  Action
773	 * Description
774	 */
775	/* DTLPWROMAEBKVF */
776	{ SST(0x00, 0x00, SS_NOP,
777	    "No additional sense information") },
778	/*  T             */
779	{ SST(0x00, 0x01, SS_RDEF,
780	    "Filemark detected") },
781	/*  T             */
782	{ SST(0x00, 0x02, SS_RDEF,
783	    "End-of-partition/medium detected") },
784	/*  T             */
785	{ SST(0x00, 0x03, SS_RDEF,
786	    "Setmark detected") },
787	/*  T             */
788	{ SST(0x00, 0x04, SS_RDEF,
789	    "Beginning-of-partition/medium detected") },
790	/*  TL            */
791	{ SST(0x00, 0x05, SS_RDEF,
792	    "End-of-data detected") },
793	/* DTLPWROMAEBKVF */
794	{ SST(0x00, 0x06, SS_RDEF,
795	    "I/O process terminated") },
796	/*  T             */
797	{ SST(0x00, 0x07, SS_RDEF,	/* XXX TBD */
798	    "Programmable early warning detected") },
799	/*      R         */
800	{ SST(0x00, 0x11, SS_FATAL | EBUSY,
801	    "Audio play operation in progress") },
802	/*      R         */
803	{ SST(0x00, 0x12, SS_NOP,
804	    "Audio play operation paused") },
805	/*      R         */
806	{ SST(0x00, 0x13, SS_NOP,
807	    "Audio play operation successfully completed") },
808	/*      R         */
809	{ SST(0x00, 0x14, SS_RDEF,
810	    "Audio play operation stopped due to error") },
811	/*      R         */
812	{ SST(0x00, 0x15, SS_NOP,
813	    "No current audio status to return") },
814	/* DTLPWROMAEBKVF */
815	{ SST(0x00, 0x16, SS_FATAL | EBUSY,
816	    "Operation in progress") },
817	/* DTL WROMAEBKVF */
818	{ SST(0x00, 0x17, SS_RDEF,
819	    "Cleaning requested") },
820	/*  T             */
821	{ SST(0x00, 0x18, SS_RDEF,	/* XXX TBD */
822	    "Erase operation in progress") },
823	/*  T             */
824	{ SST(0x00, 0x19, SS_RDEF,	/* XXX TBD */
825	    "Locate operation in progress") },
826	/*  T             */
827	{ SST(0x00, 0x1A, SS_RDEF,	/* XXX TBD */
828	    "Rewind operation in progress") },
829	/*  T             */
830	{ SST(0x00, 0x1B, SS_RDEF,	/* XXX TBD */
831	    "Set capacity operation in progress") },
832	/*  T             */
833	{ SST(0x00, 0x1C, SS_RDEF,	/* XXX TBD */
834	    "Verify operation in progress") },
835	/* DT        B    */
836	{ SST(0x00, 0x1D, SS_RDEF,	/* XXX TBD */
837	    "ATA pass through information available") },
838	/* DT   R MAEBKV  */
839	{ SST(0x00, 0x1E, SS_RDEF,	/* XXX TBD */
840	    "Conflicting SA creation request") },
841	/* D   W O   BK   */
842	{ SST(0x01, 0x00, SS_RDEF,
843	    "No index/sector signal") },
844	/* D   WRO   BK   */
845	{ SST(0x02, 0x00, SS_RDEF,
846	    "No seek complete") },
847	/* DTL W O   BK   */
848	{ SST(0x03, 0x00, SS_RDEF,
849	    "Peripheral device write fault") },
850	/*  T             */
851	{ SST(0x03, 0x01, SS_RDEF,
852	    "No write current") },
853	/*  T             */
854	{ SST(0x03, 0x02, SS_RDEF,
855	    "Excessive write errors") },
856	/* DTLPWROMAEBKVF */
857	{ SST(0x04, 0x00, SS_TUR | SSQ_MANY | SSQ_DECREMENT_COUNT | EIO,
858	    "Logical unit not ready, cause not reportable") },
859	/* DTLPWROMAEBKVF */
860	{ SST(0x04, 0x01, SS_TUR | SSQ_MANY | SSQ_DECREMENT_COUNT | EBUSY,
861	    "Logical unit is in process of becoming ready") },
862	/* DTLPWROMAEBKVF */
863	{ SST(0x04, 0x02, SS_START | SSQ_DECREMENT_COUNT | ENXIO,
864	    "Logical unit not ready, initializing command required") },
865	/* DTLPWROMAEBKVF */
866	{ SST(0x04, 0x03, SS_FATAL | ENXIO,
867	    "Logical unit not ready, manual intervention required") },
868	/* DTL  RO   B    */
869	{ SST(0x04, 0x04, SS_FATAL | EBUSY,
870	    "Logical unit not ready, format in progress") },
871	/* DT  W O A BK F */
872	{ SST(0x04, 0x05, SS_FATAL | EBUSY,
873	    "Logical unit not ready, rebuild in progress") },
874	/* DT  W O A BK   */
875	{ SST(0x04, 0x06, SS_FATAL | EBUSY,
876	    "Logical unit not ready, recalculation in progress") },
877	/* DTLPWROMAEBKVF */
878	{ SST(0x04, 0x07, SS_FATAL | EBUSY,
879	    "Logical unit not ready, operation in progress") },
880	/*      R         */
881	{ SST(0x04, 0x08, SS_FATAL | EBUSY,
882	    "Logical unit not ready, long write in progress") },
883	/* DTLPWROMAEBKVF */
884	{ SST(0x04, 0x09, SS_RDEF,	/* XXX TBD */
885	    "Logical unit not ready, self-test in progress") },
886	/* DTLPWROMAEBKVF */
887	{ SST(0x04, 0x0A, SS_RDEF,	/* XXX TBD */
888	    "Logical unit not accessible, asymmetric access state transition")},
889	/* DTLPWROMAEBKVF */
890	{ SST(0x04, 0x0B, SS_RDEF,	/* XXX TBD */
891	    "Logical unit not accessible, target port in standby state") },
892	/* DTLPWROMAEBKVF */
893	{ SST(0x04, 0x0C, SS_RDEF,	/* XXX TBD */
894	    "Logical unit not accessible, target port in unavailable state") },
895	/*              F */
896	{ SST(0x04, 0x0D, SS_RDEF,	/* XXX TBD */
897	    "Logical unit not ready, structure check required") },
898	/* DT  WROM  B    */
899	{ SST(0x04, 0x10, SS_RDEF,	/* XXX TBD */
900	    "Logical unit not ready, auxiliary memory not accessible") },
901	/* DT  WRO AEB VF */
902	{ SST(0x04, 0x11, SS_RDEF,	/* XXX TBD */
903	    "Logical unit not ready, notify (enable spinup) required") },
904	/*        M    V  */
905	{ SST(0x04, 0x12, SS_RDEF,	/* XXX TBD */
906	    "Logical unit not ready, offline") },
907	/* DT   R MAEBKV  */
908	{ SST(0x04, 0x13, SS_RDEF,	/* XXX TBD */
909	    "Logical unit not ready, SA creation in progress") },
910	/* DTL WROMAEBKVF */
911	{ SST(0x05, 0x00, SS_RDEF,
912	    "Logical unit does not respond to selection") },
913	/* D   WROM  BK   */
914	{ SST(0x06, 0x00, SS_RDEF,
915	    "No reference position found") },
916	/* DTL WROM  BK   */
917	{ SST(0x07, 0x00, SS_RDEF,
918	    "Multiple peripheral devices selected") },
919	/* DTL WROMAEBKVF */
920	{ SST(0x08, 0x00, SS_RDEF,
921	    "Logical unit communication failure") },
922	/* DTL WROMAEBKVF */
923	{ SST(0x08, 0x01, SS_RDEF,
924	    "Logical unit communication time-out") },
925	/* DTL WROMAEBKVF */
926	{ SST(0x08, 0x02, SS_RDEF,
927	    "Logical unit communication parity error") },
928	/* DT   ROM  BK   */
929	{ SST(0x08, 0x03, SS_RDEF,
930	    "Logical unit communication CRC error (Ultra-DMA/32)") },
931	/* DTLPWRO    K   */
932	{ SST(0x08, 0x04, SS_RDEF,	/* XXX TBD */
933	    "Unreachable copy target") },
934	/* DT  WRO   B    */
935	{ SST(0x09, 0x00, SS_RDEF,
936	    "Track following error") },
937	/*     WRO    K   */
938	{ SST(0x09, 0x01, SS_RDEF,
939	    "Tracking servo failure") },
940	/*     WRO    K   */
941	{ SST(0x09, 0x02, SS_RDEF,
942	    "Focus servo failure") },
943	/*     WRO        */
944	{ SST(0x09, 0x03, SS_RDEF,
945	    "Spindle servo failure") },
946	/* DT  WRO   B    */
947	{ SST(0x09, 0x04, SS_RDEF,
948	    "Head select fault") },
949	/* DTLPWROMAEBKVF */
950	{ SST(0x0A, 0x00, SS_FATAL | ENOSPC,
951	    "Error log overflow") },
952	/* DTLPWROMAEBKVF */
953	{ SST(0x0B, 0x00, SS_RDEF,
954	    "Warning") },
955	/* DTLPWROMAEBKVF */
956	{ SST(0x0B, 0x01, SS_RDEF,
957	    "Warning - specified temperature exceeded") },
958	/* DTLPWROMAEBKVF */
959	{ SST(0x0B, 0x02, SS_RDEF,
960	    "Warning - enclosure degraded") },
961	/* DTLPWROMAEBKVF */
962	{ SST(0x0B, 0x03, SS_RDEF,	/* XXX TBD */
963	    "Warning - background self-test failed") },
964	/* DTLPWRO AEBKVF */
965	{ SST(0x0B, 0x04, SS_RDEF,	/* XXX TBD */
966	    "Warning - background pre-scan detected medium error") },
967	/* DTLPWRO AEBKVF */
968	{ SST(0x0B, 0x05, SS_RDEF,	/* XXX TBD */
969	    "Warning - background medium scan detected medium error") },
970	/* DTLPWROMAEBKVF */
971	{ SST(0x0B, 0x06, SS_RDEF,	/* XXX TBD */
972	    "Warning - non-volatile cache now volatile") },
973	/* DTLPWROMAEBKVF */
974	{ SST(0x0B, 0x07, SS_RDEF,	/* XXX TBD */
975	    "Warning - degraded power to non-volatile cache") },
976	/*  T   R         */
977	{ SST(0x0C, 0x00, SS_RDEF,
978	    "Write error") },
979	/*            K   */
980	{ SST(0x0C, 0x01, SS_NOP | SSQ_PRINT_SENSE,
981	    "Write error - recovered with auto reallocation") },
982	/* D   W O   BK   */
983	{ SST(0x0C, 0x02, SS_RDEF,
984	    "Write error - auto reallocation failed") },
985	/* D   W O   BK   */
986	{ SST(0x0C, 0x03, SS_RDEF,
987	    "Write error - recommend reassignment") },
988	/* DT  W O   B    */
989	{ SST(0x0C, 0x04, SS_RDEF,
990	    "Compression check miscompare error") },
991	/* DT  W O   B    */
992	{ SST(0x0C, 0x05, SS_RDEF,
993	    "Data expansion occurred during compression") },
994	/* DT  W O   B    */
995	{ SST(0x0C, 0x06, SS_RDEF,
996	    "Block not compressible") },
997	/*      R         */
998	{ SST(0x0C, 0x07, SS_RDEF,
999	    "Write error - recovery needed") },
1000	/*      R         */
1001	{ SST(0x0C, 0x08, SS_RDEF,
1002	    "Write error - recovery failed") },
1003	/*      R         */
1004	{ SST(0x0C, 0x09, SS_RDEF,
1005	    "Write error - loss of streaming") },
1006	/*      R         */
1007	{ SST(0x0C, 0x0A, SS_RDEF,
1008	    "Write error - padding blocks added") },
1009	/* DT  WROM  B    */
1010	{ SST(0x0C, 0x0B, SS_RDEF,	/* XXX TBD */
1011	    "Auxiliary memory write error") },
1012	/* DTLPWRO AEBKVF */
1013	{ SST(0x0C, 0x0C, SS_RDEF,	/* XXX TBD */
1014	    "Write error - unexpected unsolicited data") },
1015	/* DTLPWRO AEBKVF */
1016	{ SST(0x0C, 0x0D, SS_RDEF,	/* XXX TBD */
1017	    "Write error - not enough unsolicited data") },
1018	/*      R         */
1019	{ SST(0x0C, 0x0F, SS_RDEF,	/* XXX TBD */
1020	    "Defects in error window") },
1021	/* DTLPWRO A  K   */
1022	{ SST(0x0D, 0x00, SS_RDEF,	/* XXX TBD */
1023	    "Error detected by third party temporary initiator") },
1024	/* DTLPWRO A  K   */
1025	{ SST(0x0D, 0x01, SS_RDEF,	/* XXX TBD */
1026	    "Third party device failure") },
1027	/* DTLPWRO A  K   */
1028	{ SST(0x0D, 0x02, SS_RDEF,	/* XXX TBD */
1029	    "Copy target device not reachable") },
1030	/* DTLPWRO A  K   */
1031	{ SST(0x0D, 0x03, SS_RDEF,	/* XXX TBD */
1032	    "Incorrect copy target device type") },
1033	/* DTLPWRO A  K   */
1034	{ SST(0x0D, 0x04, SS_RDEF,	/* XXX TBD */
1035	    "Copy target device data underrun") },
1036	/* DTLPWRO A  K   */
1037	{ SST(0x0D, 0x05, SS_RDEF,	/* XXX TBD */
1038	    "Copy target device data overrun") },
1039	/* DT PWROMAEBK F */
1040	{ SST(0x0E, 0x00, SS_RDEF,	/* XXX TBD */
1041	    "Invalid information unit") },
1042	/* DT PWROMAEBK F */
1043	{ SST(0x0E, 0x01, SS_RDEF,	/* XXX TBD */
1044	    "Information unit too short") },
1045	/* DT PWROMAEBK F */
1046	{ SST(0x0E, 0x02, SS_RDEF,	/* XXX TBD */
1047	    "Information unit too long") },
1048	/* DT P R MAEBK F */
1049	{ SST(0x0E, 0x03, SS_RDEF,	/* XXX TBD */
1050	    "Invalid field in command information unit") },
1051	/* D   W O   BK   */
1052	{ SST(0x10, 0x00, SS_RDEF,
1053	    "ID CRC or ECC error") },
1054	/* DT  W O        */
1055	{ SST(0x10, 0x01, SS_RDEF,	/* XXX TBD */
1056	    "Logical block guard check failed") },
1057	/* DT  W O        */
1058	{ SST(0x10, 0x02, SS_RDEF,	/* XXX TBD */
1059	    "Logical block application tag check failed") },
1060	/* DT  W O        */
1061	{ SST(0x10, 0x03, SS_RDEF,	/* XXX TBD */
1062	    "Logical block reference tag check failed") },
1063	/* DT  WRO   BK   */
1064	{ SST(0x11, 0x00, SS_RDEF,
1065	    "Unrecovered read error") },
1066	/* DT  WRO   BK   */
1067	{ SST(0x11, 0x01, SS_RDEF,
1068	    "Read retries exhausted") },
1069	/* DT  WRO   BK   */
1070	{ SST(0x11, 0x02, SS_RDEF,
1071	    "Error too long to correct") },
1072	/* DT  W O   BK   */
1073	{ SST(0x11, 0x03, SS_RDEF,
1074	    "Multiple read errors") },
1075	/* D   W O   BK   */
1076	{ SST(0x11, 0x04, SS_RDEF,
1077	    "Unrecovered read error - auto reallocate failed") },
1078	/*     WRO   B    */
1079	{ SST(0x11, 0x05, SS_RDEF,
1080	    "L-EC uncorrectable error") },
1081	/*     WRO   B    */
1082	{ SST(0x11, 0x06, SS_RDEF,
1083	    "CIRC unrecovered error") },
1084	/*     W O   B    */
1085	{ SST(0x11, 0x07, SS_RDEF,
1086	    "Data re-synchronization error") },
1087	/*  T             */
1088	{ SST(0x11, 0x08, SS_RDEF,
1089	    "Incomplete block read") },
1090	/*  T             */
1091	{ SST(0x11, 0x09, SS_RDEF,
1092	    "No gap found") },
1093	/* DT    O   BK   */
1094	{ SST(0x11, 0x0A, SS_RDEF,
1095	    "Miscorrected error") },
1096	/* D   W O   BK   */
1097	{ SST(0x11, 0x0B, SS_RDEF,
1098	    "Unrecovered read error - recommend reassignment") },
1099	/* D   W O   BK   */
1100	{ SST(0x11, 0x0C, SS_RDEF,
1101	    "Unrecovered read error - recommend rewrite the data") },
1102	/* DT  WRO   B    */
1103	{ SST(0x11, 0x0D, SS_RDEF,
1104	    "De-compression CRC error") },
1105	/* DT  WRO   B    */
1106	{ SST(0x11, 0x0E, SS_RDEF,
1107	    "Cannot decompress using declared algorithm") },
1108	/*      R         */
1109	{ SST(0x11, 0x0F, SS_RDEF,
1110	    "Error reading UPC/EAN number") },
1111	/*      R         */
1112	{ SST(0x11, 0x10, SS_RDEF,
1113	    "Error reading ISRC number") },
1114	/*      R         */
1115	{ SST(0x11, 0x11, SS_RDEF,
1116	    "Read error - loss of streaming") },
1117	/* DT  WROM  B    */
1118	{ SST(0x11, 0x12, SS_RDEF,	/* XXX TBD */
1119	    "Auxiliary memory read error") },
1120	/* DTLPWRO AEBKVF */
1121	{ SST(0x11, 0x13, SS_RDEF,	/* XXX TBD */
1122	    "Read error - failed retransmission request") },
1123	/* D              */
1124	{ SST(0x11, 0x14, SS_RDEF,	/* XXX TBD */
1125	    "Read error - LBA marked bad by application client") },
1126	/* D   W O   BK   */
1127	{ SST(0x12, 0x00, SS_RDEF,
1128	    "Address mark not found for ID field") },
1129	/* D   W O   BK   */
1130	{ SST(0x13, 0x00, SS_RDEF,
1131	    "Address mark not found for data field") },
1132	/* DTL WRO   BK   */
1133	{ SST(0x14, 0x00, SS_RDEF,
1134	    "Recorded entity not found") },
1135	/* DT  WRO   BK   */
1136	{ SST(0x14, 0x01, SS_RDEF,
1137	    "Record not found") },
1138	/*  T             */
1139	{ SST(0x14, 0x02, SS_RDEF,
1140	    "Filemark or setmark not found") },
1141	/*  T             */
1142	{ SST(0x14, 0x03, SS_RDEF,
1143	    "End-of-data not found") },
1144	/*  T             */
1145	{ SST(0x14, 0x04, SS_RDEF,
1146	    "Block sequence error") },
1147	/* DT  W O   BK   */
1148	{ SST(0x14, 0x05, SS_RDEF,
1149	    "Record not found - recommend reassignment") },
1150	/* DT  W O   BK   */
1151	{ SST(0x14, 0x06, SS_RDEF,
1152	    "Record not found - data auto-reallocated") },
1153	/*  T             */
1154	{ SST(0x14, 0x07, SS_RDEF,	/* XXX TBD */
1155	    "Locate operation failure") },
1156	/* DTL WROM  BK   */
1157	{ SST(0x15, 0x00, SS_RDEF,
1158	    "Random positioning error") },
1159	/* DTL WROM  BK   */
1160	{ SST(0x15, 0x01, SS_RDEF,
1161	    "Mechanical positioning error") },
1162	/* DT  WRO   BK   */
1163	{ SST(0x15, 0x02, SS_RDEF,
1164	    "Positioning error detected by read of medium") },
1165	/* D   W O   BK   */
1166	{ SST(0x16, 0x00, SS_RDEF,
1167	    "Data synchronization mark error") },
1168	/* D   W O   BK   */
1169	{ SST(0x16, 0x01, SS_RDEF,
1170	    "Data sync error - data rewritten") },
1171	/* D   W O   BK   */
1172	{ SST(0x16, 0x02, SS_RDEF,
1173	    "Data sync error - recommend rewrite") },
1174	/* D   W O   BK   */
1175	{ SST(0x16, 0x03, SS_NOP | SSQ_PRINT_SENSE,
1176	    "Data sync error - data auto-reallocated") },
1177	/* D   W O   BK   */
1178	{ SST(0x16, 0x04, SS_RDEF,
1179	    "Data sync error - recommend reassignment") },
1180	/* DT  WRO   BK   */
1181	{ SST(0x17, 0x00, SS_NOP | SSQ_PRINT_SENSE,
1182	    "Recovered data with no error correction applied") },
1183	/* DT  WRO   BK   */
1184	{ SST(0x17, 0x01, SS_NOP | SSQ_PRINT_SENSE,
1185	    "Recovered data with retries") },
1186	/* DT  WRO   BK   */
1187	{ SST(0x17, 0x02, SS_NOP | SSQ_PRINT_SENSE,
1188	    "Recovered data with positive head offset") },
1189	/* DT  WRO   BK   */
1190	{ SST(0x17, 0x03, SS_NOP | SSQ_PRINT_SENSE,
1191	    "Recovered data with negative head offset") },
1192	/*     WRO   B    */
1193	{ SST(0x17, 0x04, SS_NOP | SSQ_PRINT_SENSE,
1194	    "Recovered data with retries and/or CIRC applied") },
1195	/* D   WRO   BK   */
1196	{ SST(0x17, 0x05, SS_NOP | SSQ_PRINT_SENSE,
1197	    "Recovered data using previous sector ID") },
1198	/* D   W O   BK   */
1199	{ SST(0x17, 0x06, SS_NOP | SSQ_PRINT_SENSE,
1200	    "Recovered data without ECC - data auto-reallocated") },
1201	/* D   WRO   BK   */
1202	{ SST(0x17, 0x07, SS_NOP | SSQ_PRINT_SENSE,
1203	    "Recovered data without ECC - recommend reassignment") },
1204	/* D   WRO   BK   */
1205	{ SST(0x17, 0x08, SS_NOP | SSQ_PRINT_SENSE,
1206	    "Recovered data without ECC - recommend rewrite") },
1207	/* D   WRO   BK   */
1208	{ SST(0x17, 0x09, SS_NOP | SSQ_PRINT_SENSE,
1209	    "Recovered data without ECC - data rewritten") },
1210	/* DT  WRO   BK   */
1211	{ SST(0x18, 0x00, SS_NOP | SSQ_PRINT_SENSE,
1212	    "Recovered data with error correction applied") },
1213	/* D   WRO   BK   */
1214	{ SST(0x18, 0x01, SS_NOP | SSQ_PRINT_SENSE,
1215	    "Recovered data with error corr. & retries applied") },
1216	/* D   WRO   BK   */
1217	{ SST(0x18, 0x02, SS_NOP | SSQ_PRINT_SENSE,
1218	    "Recovered data - data auto-reallocated") },
1219	/*      R         */
1220	{ SST(0x18, 0x03, SS_NOP | SSQ_PRINT_SENSE,
1221	    "Recovered data with CIRC") },
1222	/*      R         */
1223	{ SST(0x18, 0x04, SS_NOP | SSQ_PRINT_SENSE,
1224	    "Recovered data with L-EC") },
1225	/* D   WRO   BK   */
1226	{ SST(0x18, 0x05, SS_NOP | SSQ_PRINT_SENSE,
1227	    "Recovered data - recommend reassignment") },
1228	/* D   WRO   BK   */
1229	{ SST(0x18, 0x06, SS_NOP | SSQ_PRINT_SENSE,
1230	    "Recovered data - recommend rewrite") },
1231	/* D   W O   BK   */
1232	{ SST(0x18, 0x07, SS_NOP | SSQ_PRINT_SENSE,
1233	    "Recovered data with ECC - data rewritten") },
1234	/*      R         */
1235	{ SST(0x18, 0x08, SS_RDEF,	/* XXX TBD */
1236	    "Recovered data with linking") },
1237	/* D     O    K   */
1238	{ SST(0x19, 0x00, SS_RDEF,
1239	    "Defect list error") },
1240	/* D     O    K   */
1241	{ SST(0x19, 0x01, SS_RDEF,
1242	    "Defect list not available") },
1243	/* D     O    K   */
1244	{ SST(0x19, 0x02, SS_RDEF,
1245	    "Defect list error in primary list") },
1246	/* D     O    K   */
1247	{ SST(0x19, 0x03, SS_RDEF,
1248	    "Defect list error in grown list") },
1249	/* DTLPWROMAEBKVF */
1250	{ SST(0x1A, 0x00, SS_RDEF,
1251	    "Parameter list length error") },
1252	/* DTLPWROMAEBKVF */
1253	{ SST(0x1B, 0x00, SS_RDEF,
1254	    "Synchronous data transfer error") },
1255	/* D     O   BK   */
1256	{ SST(0x1C, 0x00, SS_RDEF,
1257	    "Defect list not found") },
1258	/* D     O   BK   */
1259	{ SST(0x1C, 0x01, SS_RDEF,
1260	    "Primary defect list not found") },
1261	/* D     O   BK   */
1262	{ SST(0x1C, 0x02, SS_RDEF,
1263	    "Grown defect list not found") },
1264	/* DT  WRO   BK   */
1265	{ SST(0x1D, 0x00, SS_FATAL,
1266	    "Miscompare during verify operation") },
1267	/* D   W O   BK   */
1268	{ SST(0x1E, 0x00, SS_NOP | SSQ_PRINT_SENSE,
1269	    "Recovered ID with ECC correction") },
1270	/* D     O    K   */
1271	{ SST(0x1F, 0x00, SS_RDEF,
1272	    "Partial defect list transfer") },
1273	/* DTLPWROMAEBKVF */
1274	{ SST(0x20, 0x00, SS_FATAL | EINVAL,
1275	    "Invalid command operation code") },
1276	/* DT PWROMAEBK   */
1277	{ SST(0x20, 0x01, SS_RDEF,	/* XXX TBD */
1278	    "Access denied - initiator pending-enrolled") },
1279	/* DT PWROMAEBK   */
1280	{ SST(0x20, 0x02, SS_RDEF,	/* XXX TBD */
1281	    "Access denied - no access rights") },
1282	/* DT PWROMAEBK   */
1283	{ SST(0x20, 0x03, SS_RDEF,	/* XXX TBD */
1284	    "Access denied - invalid mgmt ID key") },
1285	/*  T             */
1286	{ SST(0x20, 0x04, SS_RDEF,	/* XXX TBD */
1287	    "Illegal command while in write capable state") },
1288	/*  T             */
1289	{ SST(0x20, 0x05, SS_RDEF,	/* XXX TBD */
1290	    "Obsolete") },
1291	/*  T             */
1292	{ SST(0x20, 0x06, SS_RDEF,	/* XXX TBD */
1293	    "Illegal command while in explicit address mode") },
1294	/*  T             */
1295	{ SST(0x20, 0x07, SS_RDEF,	/* XXX TBD */
1296	    "Illegal command while in implicit address mode") },
1297	/* DT PWROMAEBK   */
1298	{ SST(0x20, 0x08, SS_RDEF,	/* XXX TBD */
1299	    "Access denied - enrollment conflict") },
1300	/* DT PWROMAEBK   */
1301	{ SST(0x20, 0x09, SS_RDEF,	/* XXX TBD */
1302	    "Access denied - invalid LU identifier") },
1303	/* DT PWROMAEBK   */
1304	{ SST(0x20, 0x0A, SS_RDEF,	/* XXX TBD */
1305	    "Access denied - invalid proxy token") },
1306	/* DT PWROMAEBK   */
1307	{ SST(0x20, 0x0B, SS_RDEF,	/* XXX TBD */
1308	    "Access denied - ACL LUN conflict") },
1309	/* DT  WRO   BK   */
1310	{ SST(0x21, 0x00, SS_FATAL | EINVAL,
1311	    "Logical block address out of range") },
1312	/* DT  WROM  BK   */
1313	{ SST(0x21, 0x01, SS_FATAL | EINVAL,
1314	    "Invalid element address") },
1315	/*      R         */
1316	{ SST(0x21, 0x02, SS_RDEF,	/* XXX TBD */
1317	    "Invalid address for write") },
1318	/*      R         */
1319	{ SST(0x21, 0x03, SS_RDEF,	/* XXX TBD */
1320	    "Invalid write crossing layer jump") },
1321	/* D              */
1322	{ SST(0x22, 0x00, SS_FATAL | EINVAL,
1323	    "Illegal function (use 20 00, 24 00, or 26 00)") },
1324	/* DTLPWROMAEBKVF */
1325	{ SST(0x24, 0x00, SS_FATAL | EINVAL,
1326	    "Invalid field in CDB") },
1327	/* DTLPWRO AEBKVF */
1328	{ SST(0x24, 0x01, SS_RDEF,	/* XXX TBD */
1329	    "CDB decryption error") },
1330	/*  T             */
1331	{ SST(0x24, 0x02, SS_RDEF,	/* XXX TBD */
1332	    "Obsolete") },
1333	/*  T             */
1334	{ SST(0x24, 0x03, SS_RDEF,	/* XXX TBD */
1335	    "Obsolete") },
1336	/*              F */
1337	{ SST(0x24, 0x04, SS_RDEF,	/* XXX TBD */
1338	    "Security audit value frozen") },
1339	/*              F */
1340	{ SST(0x24, 0x05, SS_RDEF,	/* XXX TBD */
1341	    "Security working key frozen") },
1342	/*              F */
1343	{ SST(0x24, 0x06, SS_RDEF,	/* XXX TBD */
1344	    "NONCE not unique") },
1345	/*              F */
1346	{ SST(0x24, 0x07, SS_RDEF,	/* XXX TBD */
1347	    "NONCE timestamp out of range") },
1348	/* DT   R MAEBKV  */
1349	{ SST(0x24, 0x08, SS_RDEF,	/* XXX TBD */
1350	    "Invalid XCDB") },
1351	/* DTLPWROMAEBKVF */
1352	{ SST(0x25, 0x00, SS_FATAL | ENXIO,
1353	    "Logical unit not supported") },
1354	/* DTLPWROMAEBKVF */
1355	{ SST(0x26, 0x00, SS_FATAL | EINVAL,
1356	    "Invalid field in parameter list") },
1357	/* DTLPWROMAEBKVF */
1358	{ SST(0x26, 0x01, SS_FATAL | EINVAL,
1359	    "Parameter not supported") },
1360	/* DTLPWROMAEBKVF */
1361	{ SST(0x26, 0x02, SS_FATAL | EINVAL,
1362	    "Parameter value invalid") },
1363	/* DTLPWROMAE K   */
1364	{ SST(0x26, 0x03, SS_FATAL | EINVAL,
1365	    "Threshold parameters not supported") },
1366	/* DTLPWROMAEBKVF */
1367	{ SST(0x26, 0x04, SS_FATAL | EINVAL,
1368	    "Invalid release of persistent reservation") },
1369	/* DTLPWRO A BK   */
1370	{ SST(0x26, 0x05, SS_RDEF,	/* XXX TBD */
1371	    "Data decryption error") },
1372	/* DTLPWRO    K   */
1373	{ SST(0x26, 0x06, SS_RDEF,	/* XXX TBD */
1374	    "Too many target descriptors") },
1375	/* DTLPWRO    K   */
1376	{ SST(0x26, 0x07, SS_RDEF,	/* XXX TBD */
1377	    "Unsupported target descriptor type code") },
1378	/* DTLPWRO    K   */
1379	{ SST(0x26, 0x08, SS_RDEF,	/* XXX TBD */
1380	    "Too many segment descriptors") },
1381	/* DTLPWRO    K   */
1382	{ SST(0x26, 0x09, SS_RDEF,	/* XXX TBD */
1383	    "Unsupported segment descriptor type code") },
1384	/* DTLPWRO    K   */
1385	{ SST(0x26, 0x0A, SS_RDEF,	/* XXX TBD */
1386	    "Unexpected inexact segment") },
1387	/* DTLPWRO    K   */
1388	{ SST(0x26, 0x0B, SS_RDEF,	/* XXX TBD */
1389	    "Inline data length exceeded") },
1390	/* DTLPWRO    K   */
1391	{ SST(0x26, 0x0C, SS_RDEF,	/* XXX TBD */
1392	    "Invalid operation for copy source or destination") },
1393	/* DTLPWRO    K   */
1394	{ SST(0x26, 0x0D, SS_RDEF,	/* XXX TBD */
1395	    "Copy segment granularity violation") },
1396	/* DT PWROMAEBK   */
1397	{ SST(0x26, 0x0E, SS_RDEF,	/* XXX TBD */
1398	    "Invalid parameter while port is enabled") },
1399	/*              F */
1400	{ SST(0x26, 0x0F, SS_RDEF,	/* XXX TBD */
1401	    "Invalid data-out buffer integrity check value") },
1402	/*  T             */
1403	{ SST(0x26, 0x10, SS_RDEF,	/* XXX TBD */
1404	    "Data decryption key fail limit reached") },
1405	/*  T             */
1406	{ SST(0x26, 0x11, SS_RDEF,	/* XXX TBD */
1407	    "Incomplete key-associated data set") },
1408	/*  T             */
1409	{ SST(0x26, 0x12, SS_RDEF,	/* XXX TBD */
1410	    "Vendor specific key reference not found") },
1411	/* DT  WRO   BK   */
1412	{ SST(0x27, 0x00, SS_FATAL | EACCES,
1413	    "Write protected") },
1414	/* DT  WRO   BK   */
1415	{ SST(0x27, 0x01, SS_FATAL | EACCES,
1416	    "Hardware write protected") },
1417	/* DT  WRO   BK   */
1418	{ SST(0x27, 0x02, SS_FATAL | EACCES,
1419	    "Logical unit software write protected") },
1420	/*  T   R         */
1421	{ SST(0x27, 0x03, SS_FATAL | EACCES,
1422	    "Associated write protect") },
1423	/*  T   R         */
1424	{ SST(0x27, 0x04, SS_FATAL | EACCES,
1425	    "Persistent write protect") },
1426	/*  T   R         */
1427	{ SST(0x27, 0x05, SS_FATAL | EACCES,
1428	    "Permanent write protect") },
1429	/*      R       F */
1430	{ SST(0x27, 0x06, SS_RDEF,	/* XXX TBD */
1431	    "Conditional write protect") },
1432	/* DTLPWROMAEBKVF */
1433	{ SST(0x28, 0x00, SS_FATAL | ENXIO,
1434	    "Not ready to ready change, medium may have changed") },
1435	/* DT  WROM  B    */
1436	{ SST(0x28, 0x01, SS_FATAL | ENXIO,
1437	    "Import or export element accessed") },
1438	/*      R         */
1439	{ SST(0x28, 0x02, SS_RDEF,	/* XXX TBD */
1440	    "Format-layer may have changed") },
1441	/*        M       */
1442	{ SST(0x28, 0x03, SS_RDEF,	/* XXX TBD */
1443	    "Import/export element accessed, medium changed") },
1444	/*
1445	 * XXX JGibbs - All of these should use the same errno, but I don't
1446	 * think ENXIO is the correct choice.  Should we borrow from
1447	 * the networking errnos?  ECONNRESET anyone?
1448	 */
1449	/* DTLPWROMAEBKVF */
1450	{ SST(0x29, 0x00, SS_FATAL | ENXIO,
1451	    "Power on, reset, or bus device reset occurred") },
1452	/* DTLPWROMAEBKVF */
1453	{ SST(0x29, 0x01, SS_RDEF,
1454	    "Power on occurred") },
1455	/* DTLPWROMAEBKVF */
1456	{ SST(0x29, 0x02, SS_RDEF,
1457	    "SCSI bus reset occurred") },
1458	/* DTLPWROMAEBKVF */
1459	{ SST(0x29, 0x03, SS_RDEF,
1460	    "Bus device reset function occurred") },
1461	/* DTLPWROMAEBKVF */
1462	{ SST(0x29, 0x04, SS_RDEF,
1463	    "Device internal reset") },
1464	/* DTLPWROMAEBKVF */
1465	{ SST(0x29, 0x05, SS_RDEF,
1466	    "Transceiver mode changed to single-ended") },
1467	/* DTLPWROMAEBKVF */
1468	{ SST(0x29, 0x06, SS_RDEF,
1469	    "Transceiver mode changed to LVD") },
1470	/* DTLPWROMAEBKVF */
1471	{ SST(0x29, 0x07, SS_RDEF,	/* XXX TBD */
1472	    "I_T nexus loss occurred") },
1473	/* DTL WROMAEBKVF */
1474	{ SST(0x2A, 0x00, SS_RDEF,
1475	    "Parameters changed") },
1476	/* DTL WROMAEBKVF */
1477	{ SST(0x2A, 0x01, SS_RDEF,
1478	    "Mode parameters changed") },
1479	/* DTL WROMAE K   */
1480	{ SST(0x2A, 0x02, SS_RDEF,
1481	    "Log parameters changed") },
1482	/* DTLPWROMAE K   */
1483	{ SST(0x2A, 0x03, SS_RDEF,
1484	    "Reservations preempted") },
1485	/* DTLPWROMAE     */
1486	{ SST(0x2A, 0x04, SS_RDEF,	/* XXX TBD */
1487	    "Reservations released") },
1488	/* DTLPWROMAE     */
1489	{ SST(0x2A, 0x05, SS_RDEF,	/* XXX TBD */
1490	    "Registrations preempted") },
1491	/* DTLPWROMAEBKVF */
1492	{ SST(0x2A, 0x06, SS_RDEF,	/* XXX TBD */
1493	    "Asymmetric access state changed") },
1494	/* DTLPWROMAEBKVF */
1495	{ SST(0x2A, 0x07, SS_RDEF,	/* XXX TBD */
1496	    "Implicit asymmetric access state transition failed") },
1497	/* DT  WROMAEBKVF */
1498	{ SST(0x2A, 0x08, SS_RDEF,	/* XXX TBD */
1499	    "Priority changed") },
1500	/* D              */
1501	{ SST(0x2A, 0x09, SS_RDEF,	/* XXX TBD */
1502	    "Capacity data has changed") },
1503	/* DT             */
1504	{ SST(0x2A, 0x0A, SS_RDEF,	/* XXX TBD */
1505	    "Error history I_T nexus cleared") },
1506	/* DT             */
1507	{ SST(0x2A, 0x0B, SS_RDEF,	/* XXX TBD */
1508	    "Error history snapshot released") },
1509	/*              F */
1510	{ SST(0x2A, 0x0C, SS_RDEF,	/* XXX TBD */
1511	    "Error recovery attributes have changed") },
1512	/*  T             */
1513	{ SST(0x2A, 0x0D, SS_RDEF,	/* XXX TBD */
1514	    "Data encryption capabilities changed") },
1515	/* DT     M E  V  */
1516	{ SST(0x2A, 0x10, SS_RDEF,	/* XXX TBD */
1517	    "Timestamp changed") },
1518	/*  T             */
1519	{ SST(0x2A, 0x11, SS_RDEF,	/* XXX TBD */
1520	    "Data encryption parameters changed by another I_T nexus") },
1521	/*  T             */
1522	{ SST(0x2A, 0x12, SS_RDEF,	/* XXX TBD */
1523	    "Data encryption parameters changed by vendor specific event") },
1524	/*  T             */
1525	{ SST(0x2A, 0x13, SS_RDEF,	/* XXX TBD */
1526	    "Data encryption key instance counter has changed") },
1527	/* DT   R MAEBKV  */
1528	{ SST(0x2A, 0x14, SS_RDEF,	/* XXX TBD */
1529	    "SA creation capabilities data has changed") },
1530	/* DTLPWRO    K   */
1531	{ SST(0x2B, 0x00, SS_RDEF,
1532	    "Copy cannot execute since host cannot disconnect") },
1533	/* DTLPWROMAEBKVF */
1534	{ SST(0x2C, 0x00, SS_RDEF,
1535	    "Command sequence error") },
1536	/*                */
1537	{ SST(0x2C, 0x01, SS_RDEF,
1538	    "Too many windows specified") },
1539	/*                */
1540	{ SST(0x2C, 0x02, SS_RDEF,
1541	    "Invalid combination of windows specified") },
1542	/*      R         */
1543	{ SST(0x2C, 0x03, SS_RDEF,
1544	    "Current program area is not empty") },
1545	/*      R         */
1546	{ SST(0x2C, 0x04, SS_RDEF,
1547	    "Current program area is empty") },
1548	/*           B    */
1549	{ SST(0x2C, 0x05, SS_RDEF,	/* XXX TBD */
1550	    "Illegal power condition request") },
1551	/*      R         */
1552	{ SST(0x2C, 0x06, SS_RDEF,	/* XXX TBD */
1553	    "Persistent prevent conflict") },
1554	/* DTLPWROMAEBKVF */
1555	{ SST(0x2C, 0x07, SS_RDEF,	/* XXX TBD */
1556	    "Previous busy status") },
1557	/* DTLPWROMAEBKVF */
1558	{ SST(0x2C, 0x08, SS_RDEF,	/* XXX TBD */
1559	    "Previous task set full status") },
1560	/* DTLPWROM EBKVF */
1561	{ SST(0x2C, 0x09, SS_RDEF,	/* XXX TBD */
1562	    "Previous reservation conflict status") },
1563	/*              F */
1564	{ SST(0x2C, 0x0A, SS_RDEF,	/* XXX TBD */
1565	    "Partition or collection contains user objects") },
1566	/*  T             */
1567	{ SST(0x2C, 0x0B, SS_RDEF,	/* XXX TBD */
1568	    "Not reserved") },
1569	/*  T             */
1570	{ SST(0x2D, 0x00, SS_RDEF,
1571	    "Overwrite error on update in place") },
1572	/*      R         */
1573	{ SST(0x2E, 0x00, SS_RDEF,	/* XXX TBD */
1574	    "Insufficient time for operation") },
1575	/* DTLPWROMAEBKVF */
1576	{ SST(0x2F, 0x00, SS_RDEF,
1577	    "Commands cleared by another initiator") },
1578	/* D              */
1579	{ SST(0x2F, 0x01, SS_RDEF,	/* XXX TBD */
1580	    "Commands cleared by power loss notification") },
1581	/* DTLPWROMAEBKVF */
1582	{ SST(0x2F, 0x02, SS_RDEF,	/* XXX TBD */
1583	    "Commands cleared by device server") },
1584	/* DT  WROM  BK   */
1585	{ SST(0x30, 0x00, SS_RDEF,
1586	    "Incompatible medium installed") },
1587	/* DT  WRO   BK   */
1588	{ SST(0x30, 0x01, SS_RDEF,
1589	    "Cannot read medium - unknown format") },
1590	/* DT  WRO   BK   */
1591	{ SST(0x30, 0x02, SS_RDEF,
1592	    "Cannot read medium - incompatible format") },
1593	/* DT   R     K   */
1594	{ SST(0x30, 0x03, SS_RDEF,
1595	    "Cleaning cartridge installed") },
1596	/* DT  WRO   BK   */
1597	{ SST(0x30, 0x04, SS_RDEF,
1598	    "Cannot write medium - unknown format") },
1599	/* DT  WRO   BK   */
1600	{ SST(0x30, 0x05, SS_RDEF,
1601	    "Cannot write medium - incompatible format") },
1602	/* DT  WRO   B    */
1603	{ SST(0x30, 0x06, SS_RDEF,
1604	    "Cannot format medium - incompatible medium") },
1605	/* DTL WROMAEBKVF */
1606	{ SST(0x30, 0x07, SS_RDEF,
1607	    "Cleaning failure") },
1608	/*      R         */
1609	{ SST(0x30, 0x08, SS_RDEF,
1610	    "Cannot write - application code mismatch") },
1611	/*      R         */
1612	{ SST(0x30, 0x09, SS_RDEF,
1613	    "Current session not fixated for append") },
1614	/* DT  WRO AEBK   */
1615	{ SST(0x30, 0x0A, SS_RDEF,	/* XXX TBD */
1616	    "Cleaning request rejected") },
1617	/*  T             */
1618	{ SST(0x30, 0x0C, SS_RDEF,	/* XXX TBD */
1619	    "WORM medium - overwrite attempted") },
1620	/*  T             */
1621	{ SST(0x30, 0x0D, SS_RDEF,	/* XXX TBD */
1622	    "WORM medium - integrity check") },
1623	/*      R         */
1624	{ SST(0x30, 0x10, SS_RDEF,	/* XXX TBD */
1625	    "Medium not formatted") },
1626	/*        M       */
1627	{ SST(0x30, 0x11, SS_RDEF,	/* XXX TBD */
1628	    "Incompatible volume type") },
1629	/*        M       */
1630	{ SST(0x30, 0x12, SS_RDEF,	/* XXX TBD */
1631	    "Incompatible volume qualifier") },
1632	/* DT  WRO   BK   */
1633	{ SST(0x31, 0x00, SS_RDEF,
1634	    "Medium format corrupted") },
1635	/* D L  RO   B    */
1636	{ SST(0x31, 0x01, SS_RDEF,
1637	    "Format command failed") },
1638	/*      R         */
1639	{ SST(0x31, 0x02, SS_RDEF,	/* XXX TBD */
1640	    "Zoned formatting failed due to spare linking") },
1641	/* D   W O   BK   */
1642	{ SST(0x32, 0x00, SS_RDEF,
1643	    "No defect spare location available") },
1644	/* D   W O   BK   */
1645	{ SST(0x32, 0x01, SS_RDEF,
1646	    "Defect list update failure") },
1647	/*  T             */
1648	{ SST(0x33, 0x00, SS_RDEF,
1649	    "Tape length error") },
1650	/* DTLPWROMAEBKVF */
1651	{ SST(0x34, 0x00, SS_RDEF,
1652	    "Enclosure failure") },
1653	/* DTLPWROMAEBKVF */
1654	{ SST(0x35, 0x00, SS_RDEF,
1655	    "Enclosure services failure") },
1656	/* DTLPWROMAEBKVF */
1657	{ SST(0x35, 0x01, SS_RDEF,
1658	    "Unsupported enclosure function") },
1659	/* DTLPWROMAEBKVF */
1660	{ SST(0x35, 0x02, SS_RDEF,
1661	    "Enclosure services unavailable") },
1662	/* DTLPWROMAEBKVF */
1663	{ SST(0x35, 0x03, SS_RDEF,
1664	    "Enclosure services transfer failure") },
1665	/* DTLPWROMAEBKVF */
1666	{ SST(0x35, 0x04, SS_RDEF,
1667	    "Enclosure services transfer refused") },
1668	/* DTL WROMAEBKVF */
1669	{ SST(0x35, 0x05, SS_RDEF,	/* XXX TBD */
1670	    "Enclosure services checksum error") },
1671	/*   L            */
1672	{ SST(0x36, 0x00, SS_RDEF,
1673	    "Ribbon, ink, or toner failure") },
1674	/* DTL WROMAEBKVF */
1675	{ SST(0x37, 0x00, SS_RDEF,
1676	    "Rounded parameter") },
1677	/*           B    */
1678	{ SST(0x38, 0x00, SS_RDEF,	/* XXX TBD */
1679	    "Event status notification") },
1680	/*           B    */
1681	{ SST(0x38, 0x02, SS_RDEF,	/* XXX TBD */
1682	    "ESN - power management class event") },
1683	/*           B    */
1684	{ SST(0x38, 0x04, SS_RDEF,	/* XXX TBD */
1685	    "ESN - media class event") },
1686	/*           B    */
1687	{ SST(0x38, 0x06, SS_RDEF,	/* XXX TBD */
1688	    "ESN - device busy class event") },
1689	/* DTL WROMAE K   */
1690	{ SST(0x39, 0x00, SS_RDEF,
1691	    "Saving parameters not supported") },
1692	/* DTL WROM  BK   */
1693	{ SST(0x3A, 0x00, SS_FATAL | ENXIO,
1694	    "Medium not present") },
1695	/* DT  WROM  BK   */
1696	{ SST(0x3A, 0x01, SS_FATAL | ENXIO,
1697	    "Medium not present - tray closed") },
1698	/* DT  WROM  BK   */
1699	{ SST(0x3A, 0x02, SS_FATAL | ENXIO,
1700	    "Medium not present - tray open") },
1701	/* DT  WROM  B    */
1702	{ SST(0x3A, 0x03, SS_RDEF,	/* XXX TBD */
1703	    "Medium not present - loadable") },
1704	/* DT  WRO   B    */
1705	{ SST(0x3A, 0x04, SS_RDEF,	/* XXX TBD */
1706	    "Medium not present - medium auxiliary memory accessible") },
1707	/*  TL            */
1708	{ SST(0x3B, 0x00, SS_RDEF,
1709	    "Sequential positioning error") },
1710	/*  T             */
1711	{ SST(0x3B, 0x01, SS_RDEF,
1712	    "Tape position error at beginning-of-medium") },
1713	/*  T             */
1714	{ SST(0x3B, 0x02, SS_RDEF,
1715	    "Tape position error at end-of-medium") },
1716	/*   L            */
1717	{ SST(0x3B, 0x03, SS_RDEF,
1718	    "Tape or electronic vertical forms unit not ready") },
1719	/*   L            */
1720	{ SST(0x3B, 0x04, SS_RDEF,
1721	    "Slew failure") },
1722	/*   L            */
1723	{ SST(0x3B, 0x05, SS_RDEF,
1724	    "Paper jam") },
1725	/*   L            */
1726	{ SST(0x3B, 0x06, SS_RDEF,
1727	    "Failed to sense top-of-form") },
1728	/*   L            */
1729	{ SST(0x3B, 0x07, SS_RDEF,
1730	    "Failed to sense bottom-of-form") },
1731	/*  T             */
1732	{ SST(0x3B, 0x08, SS_RDEF,
1733	    "Reposition error") },
1734	/*                */
1735	{ SST(0x3B, 0x09, SS_RDEF,
1736	    "Read past end of medium") },
1737	/*                */
1738	{ SST(0x3B, 0x0A, SS_RDEF,
1739	    "Read past beginning of medium") },
1740	/*                */
1741	{ SST(0x3B, 0x0B, SS_RDEF,
1742	    "Position past end of medium") },
1743	/*  T             */
1744	{ SST(0x3B, 0x0C, SS_RDEF,
1745	    "Position past beginning of medium") },
1746	/* DT  WROM  BK   */
1747	{ SST(0x3B, 0x0D, SS_FATAL | ENOSPC,
1748	    "Medium destination element full") },
1749	/* DT  WROM  BK   */
1750	{ SST(0x3B, 0x0E, SS_RDEF,
1751	    "Medium source element empty") },
1752	/*      R         */
1753	{ SST(0x3B, 0x0F, SS_RDEF,
1754	    "End of medium reached") },
1755	/* DT  WROM  BK   */
1756	{ SST(0x3B, 0x11, SS_RDEF,
1757	    "Medium magazine not accessible") },
1758	/* DT  WROM  BK   */
1759	{ SST(0x3B, 0x12, SS_RDEF,
1760	    "Medium magazine removed") },
1761	/* DT  WROM  BK   */
1762	{ SST(0x3B, 0x13, SS_RDEF,
1763	    "Medium magazine inserted") },
1764	/* DT  WROM  BK   */
1765	{ SST(0x3B, 0x14, SS_RDEF,
1766	    "Medium magazine locked") },
1767	/* DT  WROM  BK   */
1768	{ SST(0x3B, 0x15, SS_RDEF,
1769	    "Medium magazine unlocked") },
1770	/*      R         */
1771	{ SST(0x3B, 0x16, SS_RDEF,	/* XXX TBD */
1772	    "Mechanical positioning or changer error") },
1773	/*              F */
1774	{ SST(0x3B, 0x17, SS_RDEF,	/* XXX TBD */
1775	    "Read past end of user object") },
1776	/*        M       */
1777	{ SST(0x3B, 0x18, SS_RDEF,	/* XXX TBD */
1778	    "Element disabled") },
1779	/*        M       */
1780	{ SST(0x3B, 0x19, SS_RDEF,	/* XXX TBD */
1781	    "Element enabled") },
1782	/*        M       */
1783	{ SST(0x3B, 0x1A, SS_RDEF,	/* XXX TBD */
1784	    "Data transfer device removed") },
1785	/*        M       */
1786	{ SST(0x3B, 0x1B, SS_RDEF,	/* XXX TBD */
1787	    "Data transfer device inserted") },
1788	/* DTLPWROMAE K   */
1789	{ SST(0x3D, 0x00, SS_RDEF,
1790	    "Invalid bits in IDENTIFY message") },
1791	/* DTLPWROMAEBKVF */
1792	{ SST(0x3E, 0x00, SS_RDEF,
1793	    "Logical unit has not self-configured yet") },
1794	/* DTLPWROMAEBKVF */
1795	{ SST(0x3E, 0x01, SS_RDEF,
1796	    "Logical unit failure") },
1797	/* DTLPWROMAEBKVF */
1798	{ SST(0x3E, 0x02, SS_RDEF,
1799	    "Timeout on logical unit") },
1800	/* DTLPWROMAEBKVF */
1801	{ SST(0x3E, 0x03, SS_RDEF,	/* XXX TBD */
1802	    "Logical unit failed self-test") },
1803	/* DTLPWROMAEBKVF */
1804	{ SST(0x3E, 0x04, SS_RDEF,	/* XXX TBD */
1805	    "Logical unit unable to update self-test log") },
1806	/* DTLPWROMAEBKVF */
1807	{ SST(0x3F, 0x00, SS_RDEF,
1808	    "Target operating conditions have changed") },
1809	/* DTLPWROMAEBKVF */
1810	{ SST(0x3F, 0x01, SS_RDEF,
1811	    "Microcode has been changed") },
1812	/* DTLPWROM  BK   */
1813	{ SST(0x3F, 0x02, SS_RDEF,
1814	    "Changed operating definition") },
1815	/* DTLPWROMAEBKVF */
1816	{ SST(0x3F, 0x03, SS_RDEF,
1817	    "INQUIRY data has changed") },
1818	/* DT  WROMAEBK   */
1819	{ SST(0x3F, 0x04, SS_RDEF,
1820	    "Component device attached") },
1821	/* DT  WROMAEBK   */
1822	{ SST(0x3F, 0x05, SS_RDEF,
1823	    "Device identifier changed") },
1824	/* DT  WROMAEB    */
1825	{ SST(0x3F, 0x06, SS_RDEF,
1826	    "Redundancy group created or modified") },
1827	/* DT  WROMAEB    */
1828	{ SST(0x3F, 0x07, SS_RDEF,
1829	    "Redundancy group deleted") },
1830	/* DT  WROMAEB    */
1831	{ SST(0x3F, 0x08, SS_RDEF,
1832	    "Spare created or modified") },
1833	/* DT  WROMAEB    */
1834	{ SST(0x3F, 0x09, SS_RDEF,
1835	    "Spare deleted") },
1836	/* DT  WROMAEBK   */
1837	{ SST(0x3F, 0x0A, SS_RDEF,
1838	    "Volume set created or modified") },
1839	/* DT  WROMAEBK   */
1840	{ SST(0x3F, 0x0B, SS_RDEF,
1841	    "Volume set deleted") },
1842	/* DT  WROMAEBK   */
1843	{ SST(0x3F, 0x0C, SS_RDEF,
1844	    "Volume set deassigned") },
1845	/* DT  WROMAEBK   */
1846	{ SST(0x3F, 0x0D, SS_RDEF,
1847	    "Volume set reassigned") },
1848	/* DTLPWROMAE     */
1849	{ SST(0x3F, 0x0E, SS_RDEF,	/* XXX TBD */
1850	    "Reported LUNs data has changed") },
1851	/* DTLPWROMAEBKVF */
1852	{ SST(0x3F, 0x0F, SS_RDEF,	/* XXX TBD */
1853	    "Echo buffer overwritten") },
1854	/* DT  WROM  B    */
1855	{ SST(0x3F, 0x10, SS_RDEF,	/* XXX TBD */
1856	    "Medium loadable") },
1857	/* DT  WROM  B    */
1858	{ SST(0x3F, 0x11, SS_RDEF,	/* XXX TBD */
1859	    "Medium auxiliary memory accessible") },
1860	/* DTLPWR MAEBK F */
1861	{ SST(0x3F, 0x12, SS_RDEF,	/* XXX TBD */
1862	    "iSCSI IP address added") },
1863	/* DTLPWR MAEBK F */
1864	{ SST(0x3F, 0x13, SS_RDEF,	/* XXX TBD */
1865	    "iSCSI IP address removed") },
1866	/* DTLPWR MAEBK F */
1867	{ SST(0x3F, 0x14, SS_RDEF,	/* XXX TBD */
1868	    "iSCSI IP address changed") },
1869	/* D              */
1870	{ SST(0x40, 0x00, SS_RDEF,
1871	    "RAM failure") },		/* deprecated - use 40 NN instead */
1872	/* DTLPWROMAEBKVF */
1873	{ SST(0x40, 0x80, SS_RDEF,
1874	    "Diagnostic failure: ASCQ = Component ID") },
1875	/* DTLPWROMAEBKVF */
1876	{ SST(0x40, 0xFF, SS_RDEF | SSQ_RANGE,
1877	    NULL) },			/* Range 0x80->0xFF */
1878	/* D              */
1879	{ SST(0x41, 0x00, SS_RDEF,
1880	    "Data path failure") },	/* deprecated - use 40 NN instead */
1881	/* D              */
1882	{ SST(0x42, 0x00, SS_RDEF,
1883	    "Power-on or self-test failure") },
1884					/* deprecated - use 40 NN instead */
1885	/* DTLPWROMAEBKVF */
1886	{ SST(0x43, 0x00, SS_RDEF,
1887	    "Message error") },
1888	/* DTLPWROMAEBKVF */
1889	{ SST(0x44, 0x00, SS_RDEF,
1890	    "Internal target failure") },
1891	/* DT        B    */
1892	{ SST(0x44, 0x71, SS_RDEF,	/* XXX TBD */
1893	    "ATA device failed set features") },
1894	/* DTLPWROMAEBKVF */
1895	{ SST(0x45, 0x00, SS_RDEF,
1896	    "Select or reselect failure") },
1897	/* DTLPWROM  BK   */
1898	{ SST(0x46, 0x00, SS_RDEF,
1899	    "Unsuccessful soft reset") },
1900	/* DTLPWROMAEBKVF */
1901	{ SST(0x47, 0x00, SS_RDEF,
1902	    "SCSI parity error") },
1903	/* DTLPWROMAEBKVF */
1904	{ SST(0x47, 0x01, SS_RDEF,	/* XXX TBD */
1905	    "Data phase CRC error detected") },
1906	/* DTLPWROMAEBKVF */
1907	{ SST(0x47, 0x02, SS_RDEF,	/* XXX TBD */
1908	    "SCSI parity error detected during ST data phase") },
1909	/* DTLPWROMAEBKVF */
1910	{ SST(0x47, 0x03, SS_RDEF,	/* XXX TBD */
1911	    "Information unit iuCRC error detected") },
1912	/* DTLPWROMAEBKVF */
1913	{ SST(0x47, 0x04, SS_RDEF,	/* XXX TBD */
1914	    "Asynchronous information protection error detected") },
1915	/* DTLPWROMAEBKVF */
1916	{ SST(0x47, 0x05, SS_RDEF,	/* XXX TBD */
1917	    "Protocol service CRC error") },
1918	/* DT     MAEBKVF */
1919	{ SST(0x47, 0x06, SS_RDEF,	/* XXX TBD */
1920	    "PHY test function in progress") },
1921	/* DT PWROMAEBK   */
1922	{ SST(0x47, 0x7F, SS_RDEF,	/* XXX TBD */
1923	    "Some commands cleared by iSCSI protocol event") },
1924	/* DTLPWROMAEBKVF */
1925	{ SST(0x48, 0x00, SS_RDEF,
1926	    "Initiator detected error message received") },
1927	/* DTLPWROMAEBKVF */
1928	{ SST(0x49, 0x00, SS_RDEF,
1929	    "Invalid message error") },
1930	/* DTLPWROMAEBKVF */
1931	{ SST(0x4A, 0x00, SS_RDEF,
1932	    "Command phase error") },
1933	/* DTLPWROMAEBKVF */
1934	{ SST(0x4B, 0x00, SS_RDEF,
1935	    "Data phase error") },
1936	/* DT PWROMAEBK   */
1937	{ SST(0x4B, 0x01, SS_RDEF,	/* XXX TBD */
1938	    "Invalid target port transfer tag received") },
1939	/* DT PWROMAEBK   */
1940	{ SST(0x4B, 0x02, SS_RDEF,	/* XXX TBD */
1941	    "Too much write data") },
1942	/* DT PWROMAEBK   */
1943	{ SST(0x4B, 0x03, SS_RDEF,	/* XXX TBD */
1944	    "ACK/NAK timeout") },
1945	/* DT PWROMAEBK   */
1946	{ SST(0x4B, 0x04, SS_RDEF,	/* XXX TBD */
1947	    "NAK received") },
1948	/* DT PWROMAEBK   */
1949	{ SST(0x4B, 0x05, SS_RDEF,	/* XXX TBD */
1950	    "Data offset error") },
1951	/* DT PWROMAEBK   */
1952	{ SST(0x4B, 0x06, SS_RDEF,	/* XXX TBD */
1953	    "Initiator response timeout") },
1954	/* DTLPWROMAEBKVF */
1955	{ SST(0x4C, 0x00, SS_RDEF,
1956	    "Logical unit failed self-configuration") },
1957	/* DTLPWROMAEBKVF */
1958	{ SST(0x4D, 0x00, SS_RDEF,
1959	    "Tagged overlapped commands: ASCQ = Queue tag ID") },
1960	/* DTLPWROMAEBKVF */
1961	{ SST(0x4D, 0xFF, SS_RDEF | SSQ_RANGE,
1962	    NULL) },			/* Range 0x00->0xFF */
1963	/* DTLPWROMAEBKVF */
1964	{ SST(0x4E, 0x00, SS_RDEF,
1965	    "Overlapped commands attempted") },
1966	/*  T             */
1967	{ SST(0x50, 0x00, SS_RDEF,
1968	    "Write append error") },
1969	/*  T             */
1970	{ SST(0x50, 0x01, SS_RDEF,
1971	    "Write append position error") },
1972	/*  T             */
1973	{ SST(0x50, 0x02, SS_RDEF,
1974	    "Position error related to timing") },
1975	/*  T   RO        */
1976	{ SST(0x51, 0x00, SS_RDEF,
1977	    "Erase failure") },
1978	/*      R         */
1979	{ SST(0x51, 0x01, SS_RDEF,	/* XXX TBD */
1980	    "Erase failure - incomplete erase operation detected") },
1981	/*  T             */
1982	{ SST(0x52, 0x00, SS_RDEF,
1983	    "Cartridge fault") },
1984	/* DTL WROM  BK   */
1985	{ SST(0x53, 0x00, SS_RDEF,
1986	    "Media load or eject failed") },
1987	/*  T             */
1988	{ SST(0x53, 0x01, SS_RDEF,
1989	    "Unload tape failure") },
1990	/* DT  WROM  BK   */
1991	{ SST(0x53, 0x02, SS_RDEF,
1992	    "Medium removal prevented") },
1993	/*        M       */
1994	{ SST(0x53, 0x03, SS_RDEF,	/* XXX TBD */
1995	    "Medium removal prevented by data transfer element") },
1996	/*  T             */
1997	{ SST(0x53, 0x04, SS_RDEF,	/* XXX TBD */
1998	    "Medium thread or unthread failure") },
1999	/*    P           */
2000	{ SST(0x54, 0x00, SS_RDEF,
2001	    "SCSI to host system interface failure") },
2002	/*    P           */
2003	{ SST(0x55, 0x00, SS_RDEF,
2004	    "System resource failure") },
2005	/* D     O   BK   */
2006	{ SST(0x55, 0x01, SS_FATAL | ENOSPC,
2007	    "System buffer full") },
2008	/* DTLPWROMAE K   */
2009	{ SST(0x55, 0x02, SS_RDEF,	/* XXX TBD */
2010	    "Insufficient reservation resources") },
2011	/* DTLPWROMAE K   */
2012	{ SST(0x55, 0x03, SS_RDEF,	/* XXX TBD */
2013	    "Insufficient resources") },
2014	/* DTLPWROMAE K   */
2015	{ SST(0x55, 0x04, SS_RDEF,	/* XXX TBD */
2016	    "Insufficient registration resources") },
2017	/* DT PWROMAEBK   */
2018	{ SST(0x55, 0x05, SS_RDEF,	/* XXX TBD */
2019	    "Insufficient access control resources") },
2020	/* DT  WROM  B    */
2021	{ SST(0x55, 0x06, SS_RDEF,	/* XXX TBD */
2022	    "Auxiliary memory out of space") },
2023	/*              F */
2024	{ SST(0x55, 0x07, SS_RDEF,	/* XXX TBD */
2025	    "Quota error") },
2026	/*  T             */
2027	{ SST(0x55, 0x08, SS_RDEF,	/* XXX TBD */
2028	    "Maximum number of supplemental decryption keys exceeded") },
2029	/*        M       */
2030	{ SST(0x55, 0x09, SS_RDEF,	/* XXX TBD */
2031	    "Medium auxiliary memory not accessible") },
2032	/*        M       */
2033	{ SST(0x55, 0x0A, SS_RDEF,	/* XXX TBD */
2034	    "Data currently unavailable") },
2035	/*      R         */
2036	{ SST(0x57, 0x00, SS_RDEF,
2037	    "Unable to recover table-of-contents") },
2038	/*       O        */
2039	{ SST(0x58, 0x00, SS_RDEF,
2040	    "Generation does not exist") },
2041	/*       O        */
2042	{ SST(0x59, 0x00, SS_RDEF,
2043	    "Updated block read") },
2044	/* DTLPWRO   BK   */
2045	{ SST(0x5A, 0x00, SS_RDEF,
2046	    "Operator request or state change input") },
2047	/* DT  WROM  BK   */
2048	{ SST(0x5A, 0x01, SS_RDEF,
2049	    "Operator medium removal request") },
2050	/* DT  WRO A BK   */
2051	{ SST(0x5A, 0x02, SS_RDEF,
2052	    "Operator selected write protect") },
2053	/* DT  WRO A BK   */
2054	{ SST(0x5A, 0x03, SS_RDEF,
2055	    "Operator selected write permit") },
2056	/* DTLPWROM   K   */
2057	{ SST(0x5B, 0x00, SS_RDEF,
2058	    "Log exception") },
2059	/* DTLPWROM   K   */
2060	{ SST(0x5B, 0x01, SS_RDEF,
2061	    "Threshold condition met") },
2062	/* DTLPWROM   K   */
2063	{ SST(0x5B, 0x02, SS_RDEF,
2064	    "Log counter at maximum") },
2065	/* DTLPWROM   K   */
2066	{ SST(0x5B, 0x03, SS_RDEF,
2067	    "Log list codes exhausted") },
2068	/* D     O        */
2069	{ SST(0x5C, 0x00, SS_RDEF,
2070	    "RPL status change") },
2071	/* D     O        */
2072	{ SST(0x5C, 0x01, SS_NOP | SSQ_PRINT_SENSE,
2073	    "Spindles synchronized") },
2074	/* D     O        */
2075	{ SST(0x5C, 0x02, SS_RDEF,
2076	    "Spindles not synchronized") },
2077	/* DTLPWROMAEBKVF */
2078	{ SST(0x5D, 0x00, SS_RDEF,
2079	    "Failure prediction threshold exceeded") },
2080	/*      R    B    */
2081	{ SST(0x5D, 0x01, SS_RDEF,	/* XXX TBD */
2082	    "Media failure prediction threshold exceeded") },
2083	/*      R         */
2084	{ SST(0x5D, 0x02, SS_RDEF,	/* XXX TBD */
2085	    "Logical unit failure prediction threshold exceeded") },
2086	/*      R         */
2087	{ SST(0x5D, 0x03, SS_RDEF,	/* XXX TBD */
2088	    "Spare area exhaustion prediction threshold exceeded") },
2089	/* D         B    */
2090	{ SST(0x5D, 0x10, SS_RDEF,	/* XXX TBD */
2091	    "Hardware impending failure general hard drive failure") },
2092	/* D         B    */
2093	{ SST(0x5D, 0x11, SS_RDEF,	/* XXX TBD */
2094	    "Hardware impending failure drive error rate too high") },
2095	/* D         B    */
2096	{ SST(0x5D, 0x12, SS_RDEF,	/* XXX TBD */
2097	    "Hardware impending failure data error rate too high") },
2098	/* D         B    */
2099	{ SST(0x5D, 0x13, SS_RDEF,	/* XXX TBD */
2100	    "Hardware impending failure seek error rate too high") },
2101	/* D         B    */
2102	{ SST(0x5D, 0x14, SS_RDEF,	/* XXX TBD */
2103	    "Hardware impending failure too many block reassigns") },
2104	/* D         B    */
2105	{ SST(0x5D, 0x15, SS_RDEF,	/* XXX TBD */
2106	    "Hardware impending failure access times too high") },
2107	/* D         B    */
2108	{ SST(0x5D, 0x16, SS_RDEF,	/* XXX TBD */
2109	    "Hardware impending failure start unit times too high") },
2110	/* D         B    */
2111	{ SST(0x5D, 0x17, SS_RDEF,	/* XXX TBD */
2112	    "Hardware impending failure channel parametrics") },
2113	/* D         B    */
2114	{ SST(0x5D, 0x18, SS_RDEF,	/* XXX TBD */
2115	    "Hardware impending failure controller detected") },
2116	/* D         B    */
2117	{ SST(0x5D, 0x19, SS_RDEF,	/* XXX TBD */
2118	    "Hardware impending failure throughput performance") },
2119	/* D         B    */
2120	{ SST(0x5D, 0x1A, SS_RDEF,	/* XXX TBD */
2121	    "Hardware impending failure seek time performance") },
2122	/* D         B    */
2123	{ SST(0x5D, 0x1B, SS_RDEF,	/* XXX TBD */
2124	    "Hardware impending failure spin-up retry count") },
2125	/* D         B    */
2126	{ SST(0x5D, 0x1C, SS_RDEF,	/* XXX TBD */
2127	    "Hardware impending failure drive calibration retry count") },
2128	/* D         B    */
2129	{ SST(0x5D, 0x20, SS_RDEF,	/* XXX TBD */
2130	    "Controller impending failure general hard drive failure") },
2131	/* D         B    */
2132	{ SST(0x5D, 0x21, SS_RDEF,	/* XXX TBD */
2133	    "Controller impending failure drive error rate too high") },
2134	/* D         B    */
2135	{ SST(0x5D, 0x22, SS_RDEF,	/* XXX TBD */
2136	    "Controller impending failure data error rate too high") },
2137	/* D         B    */
2138	{ SST(0x5D, 0x23, SS_RDEF,	/* XXX TBD */
2139	    "Controller impending failure seek error rate too high") },
2140	/* D         B    */
2141	{ SST(0x5D, 0x24, SS_RDEF,	/* XXX TBD */
2142	    "Controller impending failure too many block reassigns") },
2143	/* D         B    */
2144	{ SST(0x5D, 0x25, SS_RDEF,	/* XXX TBD */
2145	    "Controller impending failure access times too high") },
2146	/* D         B    */
2147	{ SST(0x5D, 0x26, SS_RDEF,	/* XXX TBD */
2148	    "Controller impending failure start unit times too high") },
2149	/* D         B    */
2150	{ SST(0x5D, 0x27, SS_RDEF,	/* XXX TBD */
2151	    "Controller impending failure channel parametrics") },
2152	/* D         B    */
2153	{ SST(0x5D, 0x28, SS_RDEF,	/* XXX TBD */
2154	    "Controller impending failure controller detected") },
2155	/* D         B    */
2156	{ SST(0x5D, 0x29, SS_RDEF,	/* XXX TBD */
2157	    "Controller impending failure throughput performance") },
2158	/* D         B    */
2159	{ SST(0x5D, 0x2A, SS_RDEF,	/* XXX TBD */
2160	    "Controller impending failure seek time performance") },
2161	/* D         B    */
2162	{ SST(0x5D, 0x2B, SS_RDEF,	/* XXX TBD */
2163	    "Controller impending failure spin-up retry count") },
2164	/* D         B    */
2165	{ SST(0x5D, 0x2C, SS_RDEF,	/* XXX TBD */
2166	    "Controller impending failure drive calibration retry count") },
2167	/* D         B    */
2168	{ SST(0x5D, 0x30, SS_RDEF,	/* XXX TBD */
2169	    "Data channel impending failure general hard drive failure") },
2170	/* D         B    */
2171	{ SST(0x5D, 0x31, SS_RDEF,	/* XXX TBD */
2172	    "Data channel impending failure drive error rate too high") },
2173	/* D         B    */
2174	{ SST(0x5D, 0x32, SS_RDEF,	/* XXX TBD */
2175	    "Data channel impending failure data error rate too high") },
2176	/* D         B    */
2177	{ SST(0x5D, 0x33, SS_RDEF,	/* XXX TBD */
2178	    "Data channel impending failure seek error rate too high") },
2179	/* D         B    */
2180	{ SST(0x5D, 0x34, SS_RDEF,	/* XXX TBD */
2181	    "Data channel impending failure too many block reassigns") },
2182	/* D         B    */
2183	{ SST(0x5D, 0x35, SS_RDEF,	/* XXX TBD */
2184	    "Data channel impending failure access times too high") },
2185	/* D         B    */
2186	{ SST(0x5D, 0x36, SS_RDEF,	/* XXX TBD */
2187	    "Data channel impending failure start unit times too high") },
2188	/* D         B    */
2189	{ SST(0x5D, 0x37, SS_RDEF,	/* XXX TBD */
2190	    "Data channel impending failure channel parametrics") },
2191	/* D         B    */
2192	{ SST(0x5D, 0x38, SS_RDEF,	/* XXX TBD */
2193	    "Data channel impending failure controller detected") },
2194	/* D         B    */
2195	{ SST(0x5D, 0x39, SS_RDEF,	/* XXX TBD */
2196	    "Data channel impending failure throughput performance") },
2197	/* D         B    */
2198	{ SST(0x5D, 0x3A, SS_RDEF,	/* XXX TBD */
2199	    "Data channel impending failure seek time performance") },
2200	/* D         B    */
2201	{ SST(0x5D, 0x3B, SS_RDEF,	/* XXX TBD */
2202	    "Data channel impending failure spin-up retry count") },
2203	/* D         B    */
2204	{ SST(0x5D, 0x3C, SS_RDEF,	/* XXX TBD */
2205	    "Data channel impending failure drive calibration retry count") },
2206	/* D         B    */
2207	{ SST(0x5D, 0x40, SS_RDEF,	/* XXX TBD */
2208	    "Servo impending failure general hard drive failure") },
2209	/* D         B    */
2210	{ SST(0x5D, 0x41, SS_RDEF,	/* XXX TBD */
2211	    "Servo impending failure drive error rate too high") },
2212	/* D         B    */
2213	{ SST(0x5D, 0x42, SS_RDEF,	/* XXX TBD */
2214	    "Servo impending failure data error rate too high") },
2215	/* D         B    */
2216	{ SST(0x5D, 0x43, SS_RDEF,	/* XXX TBD */
2217	    "Servo impending failure seek error rate too high") },
2218	/* D         B    */
2219	{ SST(0x5D, 0x44, SS_RDEF,	/* XXX TBD */
2220	    "Servo impending failure too many block reassigns") },
2221	/* D         B    */
2222	{ SST(0x5D, 0x45, SS_RDEF,	/* XXX TBD */
2223	    "Servo impending failure access times too high") },
2224	/* D         B    */
2225	{ SST(0x5D, 0x46, SS_RDEF,	/* XXX TBD */
2226	    "Servo impending failure start unit times too high") },
2227	/* D         B    */
2228	{ SST(0x5D, 0x47, SS_RDEF,	/* XXX TBD */
2229	    "Servo impending failure channel parametrics") },
2230	/* D         B    */
2231	{ SST(0x5D, 0x48, SS_RDEF,	/* XXX TBD */
2232	    "Servo impending failure controller detected") },
2233	/* D         B    */
2234	{ SST(0x5D, 0x49, SS_RDEF,	/* XXX TBD */
2235	    "Servo impending failure throughput performance") },
2236	/* D         B    */
2237	{ SST(0x5D, 0x4A, SS_RDEF,	/* XXX TBD */
2238	    "Servo impending failure seek time performance") },
2239	/* D         B    */
2240	{ SST(0x5D, 0x4B, SS_RDEF,	/* XXX TBD */
2241	    "Servo impending failure spin-up retry count") },
2242	/* D         B    */
2243	{ SST(0x5D, 0x4C, SS_RDEF,	/* XXX TBD */
2244	    "Servo impending failure drive calibration retry count") },
2245	/* D         B    */
2246	{ SST(0x5D, 0x50, SS_RDEF,	/* XXX TBD */
2247	    "Spindle impending failure general hard drive failure") },
2248	/* D         B    */
2249	{ SST(0x5D, 0x51, SS_RDEF,	/* XXX TBD */
2250	    "Spindle impending failure drive error rate too high") },
2251	/* D         B    */
2252	{ SST(0x5D, 0x52, SS_RDEF,	/* XXX TBD */
2253	    "Spindle impending failure data error rate too high") },
2254	/* D         B    */
2255	{ SST(0x5D, 0x53, SS_RDEF,	/* XXX TBD */
2256	    "Spindle impending failure seek error rate too high") },
2257	/* D         B    */
2258	{ SST(0x5D, 0x54, SS_RDEF,	/* XXX TBD */
2259	    "Spindle impending failure too many block reassigns") },
2260	/* D         B    */
2261	{ SST(0x5D, 0x55, SS_RDEF,	/* XXX TBD */
2262	    "Spindle impending failure access times too high") },
2263	/* D         B    */
2264	{ SST(0x5D, 0x56, SS_RDEF,	/* XXX TBD */
2265	    "Spindle impending failure start unit times too high") },
2266	/* D         B    */
2267	{ SST(0x5D, 0x57, SS_RDEF,	/* XXX TBD */
2268	    "Spindle impending failure channel parametrics") },
2269	/* D         B    */
2270	{ SST(0x5D, 0x58, SS_RDEF,	/* XXX TBD */
2271	    "Spindle impending failure controller detected") },
2272	/* D         B    */
2273	{ SST(0x5D, 0x59, SS_RDEF,	/* XXX TBD */
2274	    "Spindle impending failure throughput performance") },
2275	/* D         B    */
2276	{ SST(0x5D, 0x5A, SS_RDEF,	/* XXX TBD */
2277	    "Spindle impending failure seek time performance") },
2278	/* D         B    */
2279	{ SST(0x5D, 0x5B, SS_RDEF,	/* XXX TBD */
2280	    "Spindle impending failure spin-up retry count") },
2281	/* D         B    */
2282	{ SST(0x5D, 0x5C, SS_RDEF,	/* XXX TBD */
2283	    "Spindle impending failure drive calibration retry count") },
2284	/* D         B    */
2285	{ SST(0x5D, 0x60, SS_RDEF,	/* XXX TBD */
2286	    "Firmware impending failure general hard drive failure") },
2287	/* D         B    */
2288	{ SST(0x5D, 0x61, SS_RDEF,	/* XXX TBD */
2289	    "Firmware impending failure drive error rate too high") },
2290	/* D         B    */
2291	{ SST(0x5D, 0x62, SS_RDEF,	/* XXX TBD */
2292	    "Firmware impending failure data error rate too high") },
2293	/* D         B    */
2294	{ SST(0x5D, 0x63, SS_RDEF,	/* XXX TBD */
2295	    "Firmware impending failure seek error rate too high") },
2296	/* D         B    */
2297	{ SST(0x5D, 0x64, SS_RDEF,	/* XXX TBD */
2298	    "Firmware impending failure too many block reassigns") },
2299	/* D         B    */
2300	{ SST(0x5D, 0x65, SS_RDEF,	/* XXX TBD */
2301	    "Firmware impending failure access times too high") },
2302	/* D         B    */
2303	{ SST(0x5D, 0x66, SS_RDEF,	/* XXX TBD */
2304	    "Firmware impending failure start unit times too high") },
2305	/* D         B    */
2306	{ SST(0x5D, 0x67, SS_RDEF,	/* XXX TBD */
2307	    "Firmware impending failure channel parametrics") },
2308	/* D         B    */
2309	{ SST(0x5D, 0x68, SS_RDEF,	/* XXX TBD */
2310	    "Firmware impending failure controller detected") },
2311	/* D         B    */
2312	{ SST(0x5D, 0x69, SS_RDEF,	/* XXX TBD */
2313	    "Firmware impending failure throughput performance") },
2314	/* D         B    */
2315	{ SST(0x5D, 0x6A, SS_RDEF,	/* XXX TBD */
2316	    "Firmware impending failure seek time performance") },
2317	/* D         B    */
2318	{ SST(0x5D, 0x6B, SS_RDEF,	/* XXX TBD */
2319	    "Firmware impending failure spin-up retry count") },
2320	/* D         B    */
2321	{ SST(0x5D, 0x6C, SS_RDEF,	/* XXX TBD */
2322	    "Firmware impending failure drive calibration retry count") },
2323	/* DTLPWROMAEBKVF */
2324	{ SST(0x5D, 0xFF, SS_RDEF,
2325	    "Failure prediction threshold exceeded (false)") },
2326	/* DTLPWRO A  K   */
2327	{ SST(0x5E, 0x00, SS_RDEF,
2328	    "Low power condition on") },
2329	/* DTLPWRO A  K   */
2330	{ SST(0x5E, 0x01, SS_RDEF,
2331	    "Idle condition activated by timer") },
2332	/* DTLPWRO A  K   */
2333	{ SST(0x5E, 0x02, SS_RDEF,
2334	    "Standby condition activated by timer") },
2335	/* DTLPWRO A  K   */
2336	{ SST(0x5E, 0x03, SS_RDEF,
2337	    "Idle condition activated by command") },
2338	/* DTLPWRO A  K   */
2339	{ SST(0x5E, 0x04, SS_RDEF,
2340	    "Standby condition activated by command") },
2341	/*           B    */
2342	{ SST(0x5E, 0x41, SS_RDEF,	/* XXX TBD */
2343	    "Power state change to active") },
2344	/*           B    */
2345	{ SST(0x5E, 0x42, SS_RDEF,	/* XXX TBD */
2346	    "Power state change to idle") },
2347	/*           B    */
2348	{ SST(0x5E, 0x43, SS_RDEF,	/* XXX TBD */
2349	    "Power state change to standby") },
2350	/*           B    */
2351	{ SST(0x5E, 0x45, SS_RDEF,	/* XXX TBD */
2352	    "Power state change to sleep") },
2353	/*           BK   */
2354	{ SST(0x5E, 0x47, SS_RDEF,	/* XXX TBD */
2355	    "Power state change to device control") },
2356	/*                */
2357	{ SST(0x60, 0x00, SS_RDEF,
2358	    "Lamp failure") },
2359	/*                */
2360	{ SST(0x61, 0x00, SS_RDEF,
2361	    "Video acquisition error") },
2362	/*                */
2363	{ SST(0x61, 0x01, SS_RDEF,
2364	    "Unable to acquire video") },
2365	/*                */
2366	{ SST(0x61, 0x02, SS_RDEF,
2367	    "Out of focus") },
2368	/*                */
2369	{ SST(0x62, 0x00, SS_RDEF,
2370	    "Scan head positioning error") },
2371	/*      R         */
2372	{ SST(0x63, 0x00, SS_RDEF,
2373	    "End of user area encountered on this track") },
2374	/*      R         */
2375	{ SST(0x63, 0x01, SS_FATAL | ENOSPC,
2376	    "Packet does not fit in available space") },
2377	/*      R         */
2378	{ SST(0x64, 0x00, SS_FATAL | ENXIO,
2379	    "Illegal mode for this track") },
2380	/*      R         */
2381	{ SST(0x64, 0x01, SS_RDEF,
2382	    "Invalid packet size") },
2383	/* DTLPWROMAEBKVF */
2384	{ SST(0x65, 0x00, SS_RDEF,
2385	    "Voltage fault") },
2386	/*                */
2387	{ SST(0x66, 0x00, SS_RDEF,
2388	    "Automatic document feeder cover up") },
2389	/*                */
2390	{ SST(0x66, 0x01, SS_RDEF,
2391	    "Automatic document feeder lift up") },
2392	/*                */
2393	{ SST(0x66, 0x02, SS_RDEF,
2394	    "Document jam in automatic document feeder") },
2395	/*                */
2396	{ SST(0x66, 0x03, SS_RDEF,
2397	    "Document miss feed automatic in document feeder") },
2398	/*         A      */
2399	{ SST(0x67, 0x00, SS_RDEF,
2400	    "Configuration failure") },
2401	/*         A      */
2402	{ SST(0x67, 0x01, SS_RDEF,
2403	    "Configuration of incapable logical units failed") },
2404	/*         A      */
2405	{ SST(0x67, 0x02, SS_RDEF,
2406	    "Add logical unit failed") },
2407	/*         A      */
2408	{ SST(0x67, 0x03, SS_RDEF,
2409	    "Modification of logical unit failed") },
2410	/*         A      */
2411	{ SST(0x67, 0x04, SS_RDEF,
2412	    "Exchange of logical unit failed") },
2413	/*         A      */
2414	{ SST(0x67, 0x05, SS_RDEF,
2415	    "Remove of logical unit failed") },
2416	/*         A      */
2417	{ SST(0x67, 0x06, SS_RDEF,
2418	    "Attachment of logical unit failed") },
2419	/*         A      */
2420	{ SST(0x67, 0x07, SS_RDEF,
2421	    "Creation of logical unit failed") },
2422	/*         A      */
2423	{ SST(0x67, 0x08, SS_RDEF,	/* XXX TBD */
2424	    "Assign failure occurred") },
2425	/*         A      */
2426	{ SST(0x67, 0x09, SS_RDEF,	/* XXX TBD */
2427	    "Multiply assigned logical unit") },
2428	/* DTLPWROMAEBKVF */
2429	{ SST(0x67, 0x0A, SS_RDEF,	/* XXX TBD */
2430	    "Set target port groups command failed") },
2431	/* DT        B    */
2432	{ SST(0x67, 0x0B, SS_RDEF,	/* XXX TBD */
2433	    "ATA device feature not enabled") },
2434	/*         A      */
2435	{ SST(0x68, 0x00, SS_RDEF,
2436	    "Logical unit not configured") },
2437	/*         A      */
2438	{ SST(0x69, 0x00, SS_RDEF,
2439	    "Data loss on logical unit") },
2440	/*         A      */
2441	{ SST(0x69, 0x01, SS_RDEF,
2442	    "Multiple logical unit failures") },
2443	/*         A      */
2444	{ SST(0x69, 0x02, SS_RDEF,
2445	    "Parity/data mismatch") },
2446	/*         A      */
2447	{ SST(0x6A, 0x00, SS_RDEF,
2448	    "Informational, refer to log") },
2449	/*         A      */
2450	{ SST(0x6B, 0x00, SS_RDEF,
2451	    "State change has occurred") },
2452	/*         A      */
2453	{ SST(0x6B, 0x01, SS_RDEF,
2454	    "Redundancy level got better") },
2455	/*         A      */
2456	{ SST(0x6B, 0x02, SS_RDEF,
2457	    "Redundancy level got worse") },
2458	/*         A      */
2459	{ SST(0x6C, 0x00, SS_RDEF,
2460	    "Rebuild failure occurred") },
2461	/*         A      */
2462	{ SST(0x6D, 0x00, SS_RDEF,
2463	    "Recalculate failure occurred") },
2464	/*         A      */
2465	{ SST(0x6E, 0x00, SS_RDEF,
2466	    "Command to logical unit failed") },
2467	/*      R         */
2468	{ SST(0x6F, 0x00, SS_RDEF,	/* XXX TBD */
2469	    "Copy protection key exchange failure - authentication failure") },
2470	/*      R         */
2471	{ SST(0x6F, 0x01, SS_RDEF,	/* XXX TBD */
2472	    "Copy protection key exchange failure - key not present") },
2473	/*      R         */
2474	{ SST(0x6F, 0x02, SS_RDEF,	/* XXX TBD */
2475	    "Copy protection key exchange failure - key not established") },
2476	/*      R         */
2477	{ SST(0x6F, 0x03, SS_RDEF,	/* XXX TBD */
2478	    "Read of scrambled sector without authentication") },
2479	/*      R         */
2480	{ SST(0x6F, 0x04, SS_RDEF,	/* XXX TBD */
2481	    "Media region code is mismatched to logical unit region") },
2482	/*      R         */
2483	{ SST(0x6F, 0x05, SS_RDEF,	/* XXX TBD */
2484	    "Drive region must be permanent/region reset count error") },
2485	/*      R         */
2486	{ SST(0x6F, 0x06, SS_RDEF,	/* XXX TBD */
2487	    "Insufficient block count for binding NONCE recording") },
2488	/*      R         */
2489	{ SST(0x6F, 0x07, SS_RDEF,	/* XXX TBD */
2490	    "Conflict in binding NONCE recording") },
2491	/*  T             */
2492	{ SST(0x70, 0x00, SS_RDEF,
2493	    "Decompression exception short: ASCQ = Algorithm ID") },
2494	/*  T             */
2495	{ SST(0x70, 0xFF, SS_RDEF | SSQ_RANGE,
2496	    NULL) },			/* Range 0x00 -> 0xFF */
2497	/*  T             */
2498	{ SST(0x71, 0x00, SS_RDEF,
2499	    "Decompression exception long: ASCQ = Algorithm ID") },
2500	/*  T             */
2501	{ SST(0x71, 0xFF, SS_RDEF | SSQ_RANGE,
2502	    NULL) },			/* Range 0x00 -> 0xFF */
2503	/*      R         */
2504	{ SST(0x72, 0x00, SS_RDEF,
2505	    "Session fixation error") },
2506	/*      R         */
2507	{ SST(0x72, 0x01, SS_RDEF,
2508	    "Session fixation error writing lead-in") },
2509	/*      R         */
2510	{ SST(0x72, 0x02, SS_RDEF,
2511	    "Session fixation error writing lead-out") },
2512	/*      R         */
2513	{ SST(0x72, 0x03, SS_RDEF,
2514	    "Session fixation error - incomplete track in session") },
2515	/*      R         */
2516	{ SST(0x72, 0x04, SS_RDEF,
2517	    "Empty or partially written reserved track") },
2518	/*      R         */
2519	{ SST(0x72, 0x05, SS_RDEF,	/* XXX TBD */
2520	    "No more track reservations allowed") },
2521	/*      R         */
2522	{ SST(0x72, 0x06, SS_RDEF,	/* XXX TBD */
2523	    "RMZ extension is not allowed") },
2524	/*      R         */
2525	{ SST(0x72, 0x07, SS_RDEF,	/* XXX TBD */
2526	    "No more test zone extensions are allowed") },
2527	/*      R         */
2528	{ SST(0x73, 0x00, SS_RDEF,
2529	    "CD control error") },
2530	/*      R         */
2531	{ SST(0x73, 0x01, SS_RDEF,
2532	    "Power calibration area almost full") },
2533	/*      R         */
2534	{ SST(0x73, 0x02, SS_FATAL | ENOSPC,
2535	    "Power calibration area is full") },
2536	/*      R         */
2537	{ SST(0x73, 0x03, SS_RDEF,
2538	    "Power calibration area error") },
2539	/*      R         */
2540	{ SST(0x73, 0x04, SS_RDEF,
2541	    "Program memory area update failure") },
2542	/*      R         */
2543	{ SST(0x73, 0x05, SS_RDEF,
2544	    "Program memory area is full") },
2545	/*      R         */
2546	{ SST(0x73, 0x06, SS_RDEF,	/* XXX TBD */
2547	    "RMA/PMA is almost full") },
2548	/*      R         */
2549	{ SST(0x73, 0x10, SS_RDEF,	/* XXX TBD */
2550	    "Current power calibration area almost full") },
2551	/*      R         */
2552	{ SST(0x73, 0x11, SS_RDEF,	/* XXX TBD */
2553	    "Current power calibration area is full") },
2554	/*      R         */
2555	{ SST(0x73, 0x17, SS_RDEF,	/* XXX TBD */
2556	    "RDZ is full") },
2557	/*  T             */
2558	{ SST(0x74, 0x00, SS_RDEF,	/* XXX TBD */
2559	    "Security error") },
2560	/*  T             */
2561	{ SST(0x74, 0x01, SS_RDEF,	/* XXX TBD */
2562	    "Unable to decrypt data") },
2563	/*  T             */
2564	{ SST(0x74, 0x02, SS_RDEF,	/* XXX TBD */
2565	    "Unencrypted data encountered while decrypting") },
2566	/*  T             */
2567	{ SST(0x74, 0x03, SS_RDEF,	/* XXX TBD */
2568	    "Incorrect data encryption key") },
2569	/*  T             */
2570	{ SST(0x74, 0x04, SS_RDEF,	/* XXX TBD */
2571	    "Cryptographic integrity validation failed") },
2572	/*  T             */
2573	{ SST(0x74, 0x05, SS_RDEF,	/* XXX TBD */
2574	    "Error decrypting data") },
2575	/*  T             */
2576	{ SST(0x74, 0x06, SS_RDEF,	/* XXX TBD */
2577	    "Unknown signature verification key") },
2578	/*  T             */
2579	{ SST(0x74, 0x07, SS_RDEF,	/* XXX TBD */
2580	    "Encryption parameters not useable") },
2581	/* DT   R M E  VF */
2582	{ SST(0x74, 0x08, SS_RDEF,	/* XXX TBD */
2583	    "Digital signature validation failure") },
2584	/*  T             */
2585	{ SST(0x74, 0x09, SS_RDEF,	/* XXX TBD */
2586	    "Encryption mode mismatch on read") },
2587	/*  T             */
2588	{ SST(0x74, 0x0A, SS_RDEF,	/* XXX TBD */
2589	    "Encrypted block not raw read enabled") },
2590	/*  T             */
2591	{ SST(0x74, 0x0B, SS_RDEF,	/* XXX TBD */
2592	    "Incorrect encryption parameters") },
2593	/* DT   R MAEBKV  */
2594	{ SST(0x74, 0x0C, SS_RDEF,	/* XXX TBD */
2595	    "Unable to decrypt parameter list") },
2596	/*  T             */
2597	{ SST(0x74, 0x0D, SS_RDEF,	/* XXX TBD */
2598	    "Encryption algorithm disabled") },
2599	/* DT   R MAEBKV  */
2600	{ SST(0x74, 0x10, SS_RDEF,	/* XXX TBD */
2601	    "SA creation parameter value invalid") },
2602	/* DT   R MAEBKV  */
2603	{ SST(0x74, 0x11, SS_RDEF,	/* XXX TBD */
2604	    "SA creation parameter value rejected") },
2605	/* DT   R MAEBKV  */
2606	{ SST(0x74, 0x12, SS_RDEF,	/* XXX TBD */
2607	    "Invalid SA usage") },
2608	/*  T             */
2609	{ SST(0x74, 0x21, SS_RDEF,	/* XXX TBD */
2610	    "Data encryption configuration prevented") },
2611	/* DT   R MAEBKV  */
2612	{ SST(0x74, 0x30, SS_RDEF,	/* XXX TBD */
2613	    "SA creation parameter not supported") },
2614	/* DT   R MAEBKV  */
2615	{ SST(0x74, 0x40, SS_RDEF,	/* XXX TBD */
2616	    "Authentication failed") },
2617	/*             V  */
2618	{ SST(0x74, 0x61, SS_RDEF,	/* XXX TBD */
2619	    "External data encryption key manager access error") },
2620	/*             V  */
2621	{ SST(0x74, 0x62, SS_RDEF,	/* XXX TBD */
2622	    "External data encryption key manager error") },
2623	/*             V  */
2624	{ SST(0x74, 0x63, SS_RDEF,	/* XXX TBD */
2625	    "External data encryption key not found") },
2626	/*             V  */
2627	{ SST(0x74, 0x64, SS_RDEF,	/* XXX TBD */
2628	    "External data encryption request not authorized") },
2629	/*  T             */
2630	{ SST(0x74, 0x6E, SS_RDEF,	/* XXX TBD */
2631	    "External data encryption control timeout") },
2632	/*  T             */
2633	{ SST(0x74, 0x6F, SS_RDEF,	/* XXX TBD */
2634	    "External data encryption control error") },
2635	/* DT   R M E  V  */
2636	{ SST(0x74, 0x71, SS_RDEF,	/* XXX TBD */
2637	    "Logical unit access not authorized") },
2638	/* D              */
2639	{ SST(0x74, 0x79, SS_RDEF,	/* XXX TBD */
2640	    "Security conflict in translated device") }
2641};
2642
2643const int asc_table_size = sizeof(asc_table)/sizeof(asc_table[0]);
2644
2645struct asc_key
2646{
2647	int asc;
2648	int ascq;
2649};
2650
2651static int
2652ascentrycomp(const void *key, const void *member)
2653{
2654	int asc;
2655	int ascq;
2656	const struct asc_table_entry *table_entry;
2657
2658	asc = ((const struct asc_key *)key)->asc;
2659	ascq = ((const struct asc_key *)key)->ascq;
2660	table_entry = (const struct asc_table_entry *)member;
2661
2662	if (asc >= table_entry->asc) {
2663
2664		if (asc > table_entry->asc)
2665			return (1);
2666
2667		if (ascq <= table_entry->ascq) {
2668			/* Check for ranges */
2669			if (ascq == table_entry->ascq
2670		 	 || ((table_entry->action & SSQ_RANGE) != 0
2671		  	   && ascq >= (table_entry - 1)->ascq))
2672				return (0);
2673			return (-1);
2674		}
2675		return (1);
2676	}
2677	return (-1);
2678}
2679
2680static int
2681senseentrycomp(const void *key, const void *member)
2682{
2683	int sense_key;
2684	const struct sense_key_table_entry *table_entry;
2685
2686	sense_key = *((const int *)key);
2687	table_entry = (const struct sense_key_table_entry *)member;
2688
2689	if (sense_key >= table_entry->sense_key) {
2690		if (sense_key == table_entry->sense_key)
2691			return (0);
2692		return (1);
2693	}
2694	return (-1);
2695}
2696
2697static void
2698fetchtableentries(int sense_key, int asc, int ascq,
2699		  struct scsi_inquiry_data *inq_data,
2700		  const struct sense_key_table_entry **sense_entry,
2701		  const struct asc_table_entry **asc_entry)
2702{
2703	caddr_t match;
2704	const struct asc_table_entry *asc_tables[2];
2705	const struct sense_key_table_entry *sense_tables[2];
2706	struct asc_key asc_ascq;
2707	size_t asc_tables_size[2];
2708	size_t sense_tables_size[2];
2709	int num_asc_tables;
2710	int num_sense_tables;
2711	int i;
2712
2713	/* Default to failure */
2714	*sense_entry = NULL;
2715	*asc_entry = NULL;
2716	match = NULL;
2717	if (inq_data != NULL)
2718		match = cam_quirkmatch((caddr_t)inq_data,
2719				       (caddr_t)sense_quirk_table,
2720				       sense_quirk_table_size,
2721				       sizeof(*sense_quirk_table),
2722				       scsi_inquiry_match);
2723
2724	if (match != NULL) {
2725		struct scsi_sense_quirk_entry *quirk;
2726
2727		quirk = (struct scsi_sense_quirk_entry *)match;
2728		asc_tables[0] = quirk->asc_info;
2729		asc_tables_size[0] = quirk->num_ascs;
2730		asc_tables[1] = asc_table;
2731		asc_tables_size[1] = asc_table_size;
2732		num_asc_tables = 2;
2733		sense_tables[0] = quirk->sense_key_info;
2734		sense_tables_size[0] = quirk->num_sense_keys;
2735		sense_tables[1] = sense_key_table;
2736		sense_tables_size[1] = sense_key_table_size;
2737		num_sense_tables = 2;
2738	} else {
2739		asc_tables[0] = asc_table;
2740		asc_tables_size[0] = asc_table_size;
2741		num_asc_tables = 1;
2742		sense_tables[0] = sense_key_table;
2743		sense_tables_size[0] = sense_key_table_size;
2744		num_sense_tables = 1;
2745	}
2746
2747	asc_ascq.asc = asc;
2748	asc_ascq.ascq = ascq;
2749	for (i = 0; i < num_asc_tables; i++) {
2750		void *found_entry;
2751
2752		found_entry = bsearch(&asc_ascq, asc_tables[i],
2753				      asc_tables_size[i],
2754				      sizeof(**asc_tables),
2755				      ascentrycomp);
2756
2757		if (found_entry) {
2758			*asc_entry = (struct asc_table_entry *)found_entry;
2759			break;
2760		}
2761	}
2762
2763	for (i = 0; i < num_sense_tables; i++) {
2764		void *found_entry;
2765
2766		found_entry = bsearch(&sense_key, sense_tables[i],
2767				      sense_tables_size[i],
2768				      sizeof(**sense_tables),
2769				      senseentrycomp);
2770
2771		if (found_entry) {
2772			*sense_entry =
2773			    (struct sense_key_table_entry *)found_entry;
2774			break;
2775		}
2776	}
2777}
2778
2779void
2780scsi_sense_desc(int sense_key, int asc, int ascq,
2781		struct scsi_inquiry_data *inq_data,
2782		const char **sense_key_desc, const char **asc_desc)
2783{
2784	const struct asc_table_entry *asc_entry;
2785	const struct sense_key_table_entry *sense_entry;
2786
2787	fetchtableentries(sense_key, asc, ascq,
2788			  inq_data,
2789			  &sense_entry,
2790			  &asc_entry);
2791
2792	*sense_key_desc = sense_entry->desc;
2793
2794	if (asc_entry != NULL)
2795		*asc_desc = asc_entry->desc;
2796	else if (asc >= 0x80 && asc <= 0xff)
2797		*asc_desc = "Vendor Specific ASC";
2798	else if (ascq >= 0x80 && ascq <= 0xff)
2799		*asc_desc = "Vendor Specific ASCQ";
2800	else
2801		*asc_desc = "Reserved ASC/ASCQ pair";
2802}
2803
2804/*
2805 * Given sense and device type information, return the appropriate action.
2806 * If we do not understand the specific error as identified by the ASC/ASCQ
2807 * pair, fall back on the more generic actions derived from the sense key.
2808 */
2809scsi_sense_action
2810scsi_error_action(struct ccb_scsiio *csio, struct scsi_inquiry_data *inq_data,
2811		  u_int32_t sense_flags)
2812{
2813	const struct asc_table_entry *asc_entry;
2814	const struct sense_key_table_entry *sense_entry;
2815	int error_code, sense_key, asc, ascq;
2816	scsi_sense_action action;
2817
2818	scsi_extract_sense(&csio->sense_data, &error_code,
2819			   &sense_key, &asc, &ascq);
2820
2821	if (error_code == SSD_DEFERRED_ERROR) {
2822		/*
2823		 * XXX dufault@FreeBSD.org
2824		 * This error doesn't relate to the command associated
2825		 * with this request sense.  A deferred error is an error
2826		 * for a command that has already returned GOOD status
2827		 * (see SCSI2 8.2.14.2).
2828		 *
2829		 * By my reading of that section, it looks like the current
2830		 * command has been cancelled, we should now clean things up
2831		 * (hopefully recovering any lost data) and then retry the
2832		 * current command.  There are two easy choices, both wrong:
2833		 *
2834		 * 1. Drop through (like we had been doing), thus treating
2835		 *    this as if the error were for the current command and
2836		 *    return and stop the current command.
2837		 *
2838		 * 2. Issue a retry (like I made it do) thus hopefully
2839		 *    recovering the current transfer, and ignoring the
2840		 *    fact that we've dropped a command.
2841		 *
2842		 * These should probably be handled in a device specific
2843		 * sense handler or punted back up to a user mode daemon
2844		 */
2845		action = SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE;
2846	} else {
2847		fetchtableentries(sense_key, asc, ascq,
2848				  inq_data,
2849				  &sense_entry,
2850				  &asc_entry);
2851
2852		/*
2853		 * Override the 'No additional Sense' entry (0,0)
2854		 * with the error action of the sense key.
2855		 */
2856		if (asc_entry != NULL
2857		 && (asc != 0 || ascq != 0))
2858			action = asc_entry->action;
2859		else
2860			action = sense_entry->action;
2861
2862		if (sense_key == SSD_KEY_RECOVERED_ERROR) {
2863			/*
2864			 * The action succeeded but the device wants
2865			 * the user to know that some recovery action
2866			 * was required.
2867			 */
2868			action &= ~(SS_MASK|SSQ_MASK|SS_ERRMASK);
2869			action |= SS_NOP|SSQ_PRINT_SENSE;
2870		} else if (sense_key == SSD_KEY_ILLEGAL_REQUEST) {
2871			if ((sense_flags & SF_QUIET_IR) != 0)
2872				action &= ~SSQ_PRINT_SENSE;
2873		} else if (sense_key == SSD_KEY_UNIT_ATTENTION) {
2874			if ((sense_flags & SF_RETRY_UA) != 0
2875			 && (action & SS_MASK) == SS_FAIL) {
2876				action &= ~(SS_MASK|SSQ_MASK);
2877				action |= SS_RETRY|SSQ_DECREMENT_COUNT|
2878					  SSQ_PRINT_SENSE;
2879			}
2880		}
2881	}
2882#ifdef KERNEL
2883	if (bootverbose)
2884		sense_flags |= SF_PRINT_ALWAYS;
2885#endif
2886	if ((sense_flags & SF_PRINT_ALWAYS) != 0)
2887		action |= SSQ_PRINT_SENSE;
2888	else if ((sense_flags & SF_NO_PRINT) != 0)
2889		action &= ~SSQ_PRINT_SENSE;
2890
2891	return (action);
2892}
2893
2894char *
2895scsi_cdb_string(u_int8_t *cdb_ptr, char *cdb_string, size_t len)
2896{
2897	u_int8_t cdb_len;
2898	int i;
2899
2900	if (cdb_ptr == NULL)
2901		return("");
2902
2903	/* Silence warnings */
2904	cdb_len = 0;
2905
2906	/*
2907	 * This is taken from the SCSI-3 draft spec.
2908	 * (T10/1157D revision 0.3)
2909	 * The top 3 bits of an opcode are the group code.  The next 5 bits
2910	 * are the command code.
2911	 * Group 0:  six byte commands
2912	 * Group 1:  ten byte commands
2913	 * Group 2:  ten byte commands
2914	 * Group 3:  reserved
2915	 * Group 4:  sixteen byte commands
2916	 * Group 5:  twelve byte commands
2917	 * Group 6:  vendor specific
2918	 * Group 7:  vendor specific
2919	 */
2920	switch((*cdb_ptr >> 5) & 0x7) {
2921		case 0:
2922			cdb_len = 6;
2923			break;
2924		case 1:
2925		case 2:
2926			cdb_len = 10;
2927			break;
2928		case 3:
2929		case 6:
2930		case 7:
2931			/* in this case, just print out the opcode */
2932			cdb_len = 1;
2933			break;
2934		case 4:
2935			cdb_len = 16;
2936			break;
2937		case 5:
2938			cdb_len = 12;
2939			break;
2940	}
2941	*cdb_string = '\0';
2942	for (i = 0; i < cdb_len; i++)
2943		snprintf(cdb_string + strlen(cdb_string),
2944			 len - strlen(cdb_string), "%x ", cdb_ptr[i]);
2945
2946	return(cdb_string);
2947}
2948
2949const char *
2950scsi_status_string(struct ccb_scsiio *csio)
2951{
2952	switch(csio->scsi_status) {
2953	case SCSI_STATUS_OK:
2954		return("OK");
2955	case SCSI_STATUS_CHECK_COND:
2956		return("Check Condition");
2957	case SCSI_STATUS_BUSY:
2958		return("Busy");
2959	case SCSI_STATUS_INTERMED:
2960		return("Intermediate");
2961	case SCSI_STATUS_INTERMED_COND_MET:
2962		return("Intermediate-Condition Met");
2963	case SCSI_STATUS_RESERV_CONFLICT:
2964		return("Reservation Conflict");
2965	case SCSI_STATUS_CMD_TERMINATED:
2966		return("Command Terminated");
2967	case SCSI_STATUS_QUEUE_FULL:
2968		return("Queue Full");
2969	case SCSI_STATUS_ACA_ACTIVE:
2970		return("ACA Active");
2971	case SCSI_STATUS_TASK_ABORTED:
2972		return("Task Aborted");
2973	default: {
2974		static char unkstr[64];
2975		snprintf(unkstr, sizeof(unkstr), "Unknown %#x",
2976			 csio->scsi_status);
2977		return(unkstr);
2978	}
2979	}
2980}
2981
2982/*
2983 * scsi_command_string() returns 0 for success and -1 for failure.
2984 */
2985#ifdef _KERNEL
2986int
2987scsi_command_string(struct ccb_scsiio *csio, struct sbuf *sb)
2988#else /* !_KERNEL */
2989int
2990scsi_command_string(struct cam_device *device, struct ccb_scsiio *csio,
2991		    struct sbuf *sb)
2992#endif /* _KERNEL/!_KERNEL */
2993{
2994	struct scsi_inquiry_data *inq_data;
2995	char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
2996#ifdef _KERNEL
2997	struct	  ccb_getdev cgd;
2998#endif /* _KERNEL */
2999
3000#ifdef _KERNEL
3001	/*
3002	 * Get the device information.
3003	 */
3004	xpt_setup_ccb(&cgd.ccb_h,
3005		      csio->ccb_h.path,
3006		      /*priority*/ 1);
3007	cgd.ccb_h.func_code = XPT_GDEV_TYPE;
3008	xpt_action((union ccb *)&cgd);
3009
3010	/*
3011	 * If the device is unconfigured, just pretend that it is a hard
3012	 * drive.  scsi_op_desc() needs this.
3013	 */
3014	if (cgd.ccb_h.status == CAM_DEV_NOT_THERE)
3015		cgd.inq_data.device = T_DIRECT;
3016
3017	inq_data = &cgd.inq_data;
3018
3019#else /* !_KERNEL */
3020
3021	inq_data = &device->inq_data;
3022
3023#endif /* _KERNEL/!_KERNEL */
3024
3025	if ((csio->ccb_h.flags & CAM_CDB_POINTER) != 0) {
3026		sbuf_printf(sb, "%s. CDB: %s",
3027			    scsi_op_desc(csio->cdb_io.cdb_ptr[0], inq_data),
3028			    scsi_cdb_string(csio->cdb_io.cdb_ptr, cdb_str,
3029					    sizeof(cdb_str)));
3030	} else {
3031		sbuf_printf(sb, "%s. CDB: %s",
3032			    scsi_op_desc(csio->cdb_io.cdb_bytes[0], inq_data),
3033			    scsi_cdb_string(csio->cdb_io.cdb_bytes, cdb_str,
3034					    sizeof(cdb_str)));
3035	}
3036
3037	return(0);
3038}
3039
3040
3041/*
3042 * scsi_sense_sbuf() returns 0 for success and -1 for failure.
3043 */
3044#ifdef _KERNEL
3045int
3046scsi_sense_sbuf(struct ccb_scsiio *csio, struct sbuf *sb,
3047		scsi_sense_string_flags flags)
3048#else /* !_KERNEL */
3049int
3050scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
3051		struct sbuf *sb, scsi_sense_string_flags flags)
3052#endif /* _KERNEL/!_KERNEL */
3053{
3054	struct	  scsi_sense_data *sense;
3055	struct	  scsi_inquiry_data *inq_data;
3056#ifdef _KERNEL
3057	struct	  ccb_getdev cgd;
3058#endif /* _KERNEL */
3059	u_int32_t info;
3060	int	  error_code;
3061	int	  sense_key;
3062	int	  asc, ascq;
3063	char	  path_str[64];
3064
3065#ifndef _KERNEL
3066	if (device == NULL)
3067		return(-1);
3068#endif /* !_KERNEL */
3069	if ((csio == NULL) || (sb == NULL))
3070		return(-1);
3071
3072	/*
3073	 * If the CDB is a physical address, we can't deal with it..
3074	 */
3075	if ((csio->ccb_h.flags & CAM_CDB_PHYS) != 0)
3076		flags &= ~SSS_FLAG_PRINT_COMMAND;
3077
3078#ifdef _KERNEL
3079	xpt_path_string(csio->ccb_h.path, path_str, sizeof(path_str));
3080#else /* !_KERNEL */
3081	cam_path_string(device, path_str, sizeof(path_str));
3082#endif /* _KERNEL/!_KERNEL */
3083
3084#ifdef _KERNEL
3085	/*
3086	 * Get the device information.
3087	 */
3088	xpt_setup_ccb(&cgd.ccb_h,
3089		      csio->ccb_h.path,
3090		      /*priority*/ 1);
3091	cgd.ccb_h.func_code = XPT_GDEV_TYPE;
3092	xpt_action((union ccb *)&cgd);
3093
3094	/*
3095	 * If the device is unconfigured, just pretend that it is a hard
3096	 * drive.  scsi_op_desc() needs this.
3097	 */
3098	if (cgd.ccb_h.status == CAM_DEV_NOT_THERE)
3099		cgd.inq_data.device = T_DIRECT;
3100
3101	inq_data = &cgd.inq_data;
3102
3103#else /* !_KERNEL */
3104
3105	inq_data = &device->inq_data;
3106
3107#endif /* _KERNEL/!_KERNEL */
3108
3109	sense = NULL;
3110
3111	if (flags & SSS_FLAG_PRINT_COMMAND) {
3112
3113		sbuf_cat(sb, path_str);
3114
3115#ifdef _KERNEL
3116		scsi_command_string(csio, sb);
3117#else /* !_KERNEL */
3118		scsi_command_string(device, csio, sb);
3119#endif /* _KERNEL/!_KERNEL */
3120		sbuf_printf(sb, "\n");
3121	}
3122
3123	/*
3124	 * If the sense data is a physical pointer, forget it.
3125	 */
3126	if (csio->ccb_h.flags & CAM_SENSE_PTR) {
3127		if (csio->ccb_h.flags & CAM_SENSE_PHYS)
3128			return(-1);
3129		else {
3130			/*
3131			 * bcopy the pointer to avoid unaligned access
3132			 * errors on finicky architectures.  We don't
3133			 * ensure that the sense data is pointer aligned.
3134			 */
3135			bcopy(&csio->sense_data, &sense,
3136			      sizeof(struct scsi_sense_data *));
3137		}
3138	} else {
3139		/*
3140		 * If the physical sense flag is set, but the sense pointer
3141		 * is not also set, we assume that the user is an idiot and
3142		 * return.  (Well, okay, it could be that somehow, the
3143		 * entire csio is physical, but we would have probably core
3144		 * dumped on one of the bogus pointer deferences above
3145		 * already.)
3146		 */
3147		if (csio->ccb_h.flags & CAM_SENSE_PHYS)
3148			return(-1);
3149		else
3150			sense = &csio->sense_data;
3151	}
3152
3153
3154	sbuf_cat(sb, path_str);
3155
3156	error_code = sense->error_code & SSD_ERRCODE;
3157	sense_key = sense->flags & SSD_KEY;
3158
3159	switch (error_code) {
3160	case SSD_DEFERRED_ERROR:
3161		sbuf_printf(sb, "Deferred Error: ");
3162
3163		/* FALLTHROUGH */
3164	case SSD_CURRENT_ERROR:
3165	{
3166		const char *sense_key_desc;
3167		const char *asc_desc;
3168
3169		asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0;
3170		ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0;
3171		scsi_sense_desc(sense_key, asc, ascq, inq_data,
3172				&sense_key_desc, &asc_desc);
3173		sbuf_cat(sb, sense_key_desc);
3174
3175		info = scsi_4btoul(sense->info);
3176
3177		if (sense->error_code & SSD_ERRCODE_VALID) {
3178
3179			switch (sense_key) {
3180			case SSD_KEY_NOT_READY:
3181			case SSD_KEY_ILLEGAL_REQUEST:
3182			case SSD_KEY_UNIT_ATTENTION:
3183			case SSD_KEY_DATA_PROTECT:
3184				break;
3185			case SSD_KEY_BLANK_CHECK:
3186				sbuf_printf(sb, " req sz: %d (decimal)", info);
3187				break;
3188			default:
3189				if (info) {
3190					if (sense->flags & SSD_ILI) {
3191						sbuf_printf(sb, " ILI (length "
3192							"mismatch): %d", info);
3193
3194					} else {
3195						sbuf_printf(sb, " info:%x",
3196							    info);
3197					}
3198				}
3199			}
3200		} else if (info) {
3201			sbuf_printf(sb, " info?:%x", info);
3202		}
3203
3204		if (sense->extra_len >= 4) {
3205			if (bcmp(sense->cmd_spec_info, "\0\0\0\0", 4)) {
3206				sbuf_printf(sb, " csi:%x,%x,%x,%x",
3207					    sense->cmd_spec_info[0],
3208					    sense->cmd_spec_info[1],
3209					    sense->cmd_spec_info[2],
3210					    sense->cmd_spec_info[3]);
3211			}
3212		}
3213
3214		sbuf_printf(sb, " asc:%x,%x\n%s%s", asc, ascq,
3215			    path_str, asc_desc);
3216
3217		if (sense->extra_len >= 7 && sense->fru) {
3218			sbuf_printf(sb, " field replaceable unit: %x",
3219				    sense->fru);
3220		}
3221
3222		if ((sense->extra_len >= 10)
3223		 && (sense->sense_key_spec[0] & SSD_SCS_VALID) != 0) {
3224			switch(sense_key) {
3225			case SSD_KEY_ILLEGAL_REQUEST: {
3226				int bad_command;
3227				char tmpstr2[40];
3228
3229				if (sense->sense_key_spec[0] & 0x40)
3230					bad_command = 1;
3231				else
3232					bad_command = 0;
3233
3234				tmpstr2[0] = '\0';
3235
3236				/* Bit pointer is valid */
3237				if (sense->sense_key_spec[0] & 0x08)
3238					snprintf(tmpstr2, sizeof(tmpstr2),
3239						 "bit %d ",
3240						sense->sense_key_spec[0] & 0x7);
3241				sbuf_printf(sb, ": %s byte %d %sis invalid",
3242					    bad_command ? "Command" : "Data",
3243					    scsi_2btoul(
3244					    &sense->sense_key_spec[1]),
3245					    tmpstr2);
3246				break;
3247			}
3248			case SSD_KEY_RECOVERED_ERROR:
3249			case SSD_KEY_HARDWARE_ERROR:
3250			case SSD_KEY_MEDIUM_ERROR:
3251				sbuf_printf(sb, " actual retry count: %d",
3252					    scsi_2btoul(
3253					    &sense->sense_key_spec[1]));
3254				break;
3255			default:
3256				sbuf_printf(sb, " sks:%#x,%#x",
3257					    sense->sense_key_spec[0],
3258					    scsi_2btoul(
3259					    &sense->sense_key_spec[1]));
3260				break;
3261			}
3262		}
3263		break;
3264
3265	}
3266	default:
3267		sbuf_printf(sb, "Sense Error Code 0x%x", sense->error_code);
3268		if (sense->error_code & SSD_ERRCODE_VALID) {
3269			sbuf_printf(sb, " at block no. %d (decimal)",
3270				    info = scsi_4btoul(sense->info));
3271		}
3272	}
3273
3274	sbuf_printf(sb, "\n");
3275
3276	return(0);
3277}
3278
3279
3280
3281#ifdef _KERNEL
3282char *
3283scsi_sense_string(struct ccb_scsiio *csio, char *str, int str_len)
3284#else /* !_KERNEL */
3285char *
3286scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
3287		  char *str, int str_len)
3288#endif /* _KERNEL/!_KERNEL */
3289{
3290	struct sbuf sb;
3291
3292	sbuf_new(&sb, str, str_len, 0);
3293
3294#ifdef _KERNEL
3295	scsi_sense_sbuf(csio, &sb, SSS_FLAG_PRINT_COMMAND);
3296#else /* !_KERNEL */
3297	scsi_sense_sbuf(device, csio, &sb, SSS_FLAG_PRINT_COMMAND);
3298#endif /* _KERNEL/!_KERNEL */
3299
3300	sbuf_finish(&sb);
3301
3302	return(sbuf_data(&sb));
3303}
3304
3305#ifdef _KERNEL
3306void
3307scsi_sense_print(struct ccb_scsiio *csio)
3308{
3309	struct sbuf sb;
3310	char str[512];
3311
3312	sbuf_new(&sb, str, sizeof(str), 0);
3313
3314	scsi_sense_sbuf(csio, &sb, SSS_FLAG_PRINT_COMMAND);
3315
3316	sbuf_finish(&sb);
3317
3318	printf("%s", sbuf_data(&sb));
3319}
3320
3321#else /* !_KERNEL */
3322void
3323scsi_sense_print(struct cam_device *device, struct ccb_scsiio *csio,
3324		 FILE *ofile)
3325{
3326	struct sbuf sb;
3327	char str[512];
3328
3329	if ((device == NULL) || (csio == NULL) || (ofile == NULL))
3330		return;
3331
3332	sbuf_new(&sb, str, sizeof(str), 0);
3333
3334	scsi_sense_sbuf(device, csio, &sb, SSS_FLAG_PRINT_COMMAND);
3335
3336	sbuf_finish(&sb);
3337
3338	fprintf(ofile, "%s", sbuf_data(&sb));
3339}
3340
3341#endif /* _KERNEL/!_KERNEL */
3342
3343/*
3344 * This function currently requires at least 36 bytes, or
3345 * SHORT_INQUIRY_LENGTH, worth of data to function properly.  If this
3346 * function needs more or less data in the future, another length should be
3347 * defined in scsi_all.h to indicate the minimum amount of data necessary
3348 * for this routine to function properly.
3349 */
3350void
3351scsi_print_inquiry(struct scsi_inquiry_data *inq_data)
3352{
3353	u_int8_t type;
3354	char *dtype, *qtype;
3355	char vendor[16], product[48], revision[16], rstr[4];
3356
3357	type = SID_TYPE(inq_data);
3358
3359	/*
3360	 * Figure out basic device type and qualifier.
3361	 */
3362	if (SID_QUAL_IS_VENDOR_UNIQUE(inq_data)) {
3363		qtype = "(vendor-unique qualifier)";
3364	} else {
3365		switch (SID_QUAL(inq_data)) {
3366		case SID_QUAL_LU_CONNECTED:
3367			qtype = "";
3368			break;
3369
3370		case SID_QUAL_LU_OFFLINE:
3371			qtype = "(offline)";
3372			break;
3373
3374		case SID_QUAL_RSVD:
3375			qtype = "(reserved qualifier)";
3376			break;
3377		default:
3378		case SID_QUAL_BAD_LU:
3379			qtype = "(LUN not supported)";
3380			break;
3381		}
3382	}
3383
3384	switch (type) {
3385	case T_DIRECT:
3386		dtype = "Direct Access";
3387		break;
3388	case T_SEQUENTIAL:
3389		dtype = "Sequential Access";
3390		break;
3391	case T_PRINTER:
3392		dtype = "Printer";
3393		break;
3394	case T_PROCESSOR:
3395		dtype = "Processor";
3396		break;
3397	case T_WORM:
3398		dtype = "WORM";
3399		break;
3400	case T_CDROM:
3401		dtype = "CD-ROM";
3402		break;
3403	case T_SCANNER:
3404		dtype = "Scanner";
3405		break;
3406	case T_OPTICAL:
3407		dtype = "Optical";
3408		break;
3409	case T_CHANGER:
3410		dtype = "Changer";
3411		break;
3412	case T_COMM:
3413		dtype = "Communication";
3414		break;
3415	case T_STORARRAY:
3416		dtype = "Storage Array";
3417		break;
3418	case T_ENCLOSURE:
3419		dtype = "Enclosure Services";
3420		break;
3421	case T_RBC:
3422		dtype = "Simplified Direct Access";
3423		break;
3424	case T_OCRW:
3425		dtype = "Optical Card Read/Write";
3426		break;
3427	case T_OSD:
3428		dtype = "Object-Based Storage";
3429		break;
3430	case T_ADC:
3431		dtype = "Automation/Drive Interface";
3432		break;
3433	case T_NODEVICE:
3434		dtype = "Uninstalled";
3435		break;
3436	default:
3437		dtype = "unknown";
3438		break;
3439	}
3440
3441	cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor),
3442		   sizeof(vendor));
3443	cam_strvis(product, inq_data->product, sizeof(inq_data->product),
3444		   sizeof(product));
3445	cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision),
3446		   sizeof(revision));
3447
3448	if (SID_ANSI_REV(inq_data) == SCSI_REV_CCS)
3449		bcopy("CCS", rstr, 4);
3450	else
3451		snprintf(rstr, sizeof (rstr), "%d", SID_ANSI_REV(inq_data));
3452	printf("<%s %s %s> %s %s SCSI-%s device %s\n",
3453	       vendor, product, revision,
3454	       SID_IS_REMOVABLE(inq_data) ? "Removable" : "Fixed",
3455	       dtype, rstr, qtype);
3456}
3457
3458/*
3459 * Table of syncrates that don't follow the "divisible by 4"
3460 * rule. This table will be expanded in future SCSI specs.
3461 */
3462static struct {
3463	u_int period_factor;
3464	u_int period;	/* in 100ths of ns */
3465} scsi_syncrates[] = {
3466	{ 0x08, 625 },	/* FAST-160 */
3467	{ 0x09, 1250 },	/* FAST-80 */
3468	{ 0x0a, 2500 },	/* FAST-40 40MHz */
3469	{ 0x0b, 3030 },	/* FAST-40 33MHz */
3470	{ 0x0c, 5000 }	/* FAST-20 */
3471};
3472
3473/*
3474 * Return the frequency in kHz corresponding to the given
3475 * sync period factor.
3476 */
3477u_int
3478scsi_calc_syncsrate(u_int period_factor)
3479{
3480	int i;
3481	int num_syncrates;
3482
3483	/*
3484	 * It's a bug if period is zero, but if it is anyway, don't
3485	 * die with a divide fault- instead return something which
3486	 * 'approximates' async
3487	 */
3488	if (period_factor == 0) {
3489		return (3300);
3490	}
3491
3492	num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
3493	/* See if the period is in the "exception" table */
3494	for (i = 0; i < num_syncrates; i++) {
3495
3496		if (period_factor == scsi_syncrates[i].period_factor) {
3497			/* Period in kHz */
3498			return (100000000 / scsi_syncrates[i].period);
3499		}
3500	}
3501
3502	/*
3503	 * Wasn't in the table, so use the standard
3504	 * 4 times conversion.
3505	 */
3506	return (10000000 / (period_factor * 4 * 10));
3507}
3508
3509/*
3510 * Return the SCSI sync parameter that corresponsd to
3511 * the passed in period in 10ths of ns.
3512 */
3513u_int
3514scsi_calc_syncparam(u_int period)
3515{
3516	int i;
3517	int num_syncrates;
3518
3519	if (period == 0)
3520		return (~0);	/* Async */
3521
3522	/* Adjust for exception table being in 100ths. */
3523	period *= 10;
3524	num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
3525	/* See if the period is in the "exception" table */
3526	for (i = 0; i < num_syncrates; i++) {
3527
3528		if (period <= scsi_syncrates[i].period) {
3529			/* Period in 100ths of ns */
3530			return (scsi_syncrates[i].period_factor);
3531		}
3532	}
3533
3534	/*
3535	 * Wasn't in the table, so use the standard
3536	 * 1/4 period in ns conversion.
3537	 */
3538	return (period/400);
3539}
3540
3541void
3542scsi_test_unit_ready(struct ccb_scsiio *csio, u_int32_t retries,
3543		     void (*cbfcnp)(struct cam_periph *, union ccb *),
3544		     u_int8_t tag_action, u_int8_t sense_len, u_int32_t timeout)
3545{
3546	struct scsi_test_unit_ready *scsi_cmd;
3547
3548	cam_fill_csio(csio,
3549		      retries,
3550		      cbfcnp,
3551		      CAM_DIR_NONE,
3552		      tag_action,
3553		      /*data_ptr*/NULL,
3554		      /*dxfer_len*/0,
3555		      sense_len,
3556		      sizeof(*scsi_cmd),
3557		      timeout);
3558
3559	scsi_cmd = (struct scsi_test_unit_ready *)&csio->cdb_io.cdb_bytes;
3560	bzero(scsi_cmd, sizeof(*scsi_cmd));
3561	scsi_cmd->opcode = TEST_UNIT_READY;
3562}
3563
3564void
3565scsi_request_sense(struct ccb_scsiio *csio, u_int32_t retries,
3566		   void (*cbfcnp)(struct cam_periph *, union ccb *),
3567		   void *data_ptr, u_int8_t dxfer_len, u_int8_t tag_action,
3568		   u_int8_t sense_len, u_int32_t timeout)
3569{
3570	struct scsi_request_sense *scsi_cmd;
3571
3572	cam_fill_csio(csio,
3573		      retries,
3574		      cbfcnp,
3575		      CAM_DIR_IN,
3576		      tag_action,
3577		      data_ptr,
3578		      dxfer_len,
3579		      sense_len,
3580		      sizeof(*scsi_cmd),
3581		      timeout);
3582
3583	scsi_cmd = (struct scsi_request_sense *)&csio->cdb_io.cdb_bytes;
3584	bzero(scsi_cmd, sizeof(*scsi_cmd));
3585	scsi_cmd->opcode = REQUEST_SENSE;
3586	scsi_cmd->length = dxfer_len;
3587}
3588
3589void
3590scsi_inquiry(struct ccb_scsiio *csio, u_int32_t retries,
3591	     void (*cbfcnp)(struct cam_periph *, union ccb *),
3592	     u_int8_t tag_action, u_int8_t *inq_buf, u_int32_t inq_len,
3593	     int evpd, u_int8_t page_code, u_int8_t sense_len,
3594	     u_int32_t timeout)
3595{
3596	struct scsi_inquiry *scsi_cmd;
3597
3598	cam_fill_csio(csio,
3599		      retries,
3600		      cbfcnp,
3601		      /*flags*/CAM_DIR_IN,
3602		      tag_action,
3603		      /*data_ptr*/inq_buf,
3604		      /*dxfer_len*/inq_len,
3605		      sense_len,
3606		      sizeof(*scsi_cmd),
3607		      timeout);
3608
3609	scsi_cmd = (struct scsi_inquiry *)&csio->cdb_io.cdb_bytes;
3610	bzero(scsi_cmd, sizeof(*scsi_cmd));
3611	scsi_cmd->opcode = INQUIRY;
3612	if (evpd) {
3613		scsi_cmd->byte2 |= SI_EVPD;
3614		scsi_cmd->page_code = page_code;
3615	}
3616	/*
3617	 * A 'transfer units' count of 256 is coded as
3618	 * zero for all commands with a single byte count
3619	 * field.
3620	 */
3621	if (inq_len == 256)
3622		inq_len = 0;
3623	scsi_cmd->length = inq_len;
3624}
3625
3626void
3627scsi_mode_sense(struct ccb_scsiio *csio, u_int32_t retries,
3628		void (*cbfcnp)(struct cam_periph *, union ccb *),
3629		u_int8_t tag_action, int dbd, u_int8_t page_code,
3630		u_int8_t page, u_int8_t *param_buf, u_int32_t param_len,
3631		u_int8_t sense_len, u_int32_t timeout)
3632{
3633
3634	scsi_mode_sense_len(csio, retries, cbfcnp, tag_action, dbd,
3635			    page_code, page, param_buf, param_len, 0,
3636			    sense_len, timeout);
3637}
3638
3639void
3640scsi_mode_sense_len(struct ccb_scsiio *csio, u_int32_t retries,
3641		    void (*cbfcnp)(struct cam_periph *, union ccb *),
3642		    u_int8_t tag_action, int dbd, u_int8_t page_code,
3643		    u_int8_t page, u_int8_t *param_buf, u_int32_t param_len,
3644		    int minimum_cmd_size, u_int8_t sense_len, u_int32_t timeout)
3645{
3646	u_int8_t cdb_len;
3647
3648	/*
3649	 * Use the smallest possible command to perform the operation.
3650	 */
3651	if ((param_len < 256)
3652	 && (minimum_cmd_size < 10)) {
3653		/*
3654		 * We can fit in a 6 byte cdb.
3655		 */
3656		struct scsi_mode_sense_6 *scsi_cmd;
3657
3658		scsi_cmd = (struct scsi_mode_sense_6 *)&csio->cdb_io.cdb_bytes;
3659		bzero(scsi_cmd, sizeof(*scsi_cmd));
3660		scsi_cmd->opcode = MODE_SENSE_6;
3661		if (dbd != 0)
3662			scsi_cmd->byte2 |= SMS_DBD;
3663		scsi_cmd->page = page_code | page;
3664		scsi_cmd->length = param_len;
3665		cdb_len = sizeof(*scsi_cmd);
3666	} else {
3667		/*
3668		 * Need a 10 byte cdb.
3669		 */
3670		struct scsi_mode_sense_10 *scsi_cmd;
3671
3672		scsi_cmd = (struct scsi_mode_sense_10 *)&csio->cdb_io.cdb_bytes;
3673		bzero(scsi_cmd, sizeof(*scsi_cmd));
3674		scsi_cmd->opcode = MODE_SENSE_10;
3675		if (dbd != 0)
3676			scsi_cmd->byte2 |= SMS_DBD;
3677		scsi_cmd->page = page_code | page;
3678		scsi_ulto2b(param_len, scsi_cmd->length);
3679		cdb_len = sizeof(*scsi_cmd);
3680	}
3681	cam_fill_csio(csio,
3682		      retries,
3683		      cbfcnp,
3684		      CAM_DIR_IN,
3685		      tag_action,
3686		      param_buf,
3687		      param_len,
3688		      sense_len,
3689		      cdb_len,
3690		      timeout);
3691}
3692
3693void
3694scsi_mode_select(struct ccb_scsiio *csio, u_int32_t retries,
3695		 void (*cbfcnp)(struct cam_periph *, union ccb *),
3696		 u_int8_t tag_action, int scsi_page_fmt, int save_pages,
3697		 u_int8_t *param_buf, u_int32_t param_len, u_int8_t sense_len,
3698		 u_int32_t timeout)
3699{
3700	scsi_mode_select_len(csio, retries, cbfcnp, tag_action,
3701			     scsi_page_fmt, save_pages, param_buf,
3702			     param_len, 0, sense_len, timeout);
3703}
3704
3705void
3706scsi_mode_select_len(struct ccb_scsiio *csio, u_int32_t retries,
3707		     void (*cbfcnp)(struct cam_periph *, union ccb *),
3708		     u_int8_t tag_action, int scsi_page_fmt, int save_pages,
3709		     u_int8_t *param_buf, u_int32_t param_len,
3710		     int minimum_cmd_size, u_int8_t sense_len,
3711		     u_int32_t timeout)
3712{
3713	u_int8_t cdb_len;
3714
3715	/*
3716	 * Use the smallest possible command to perform the operation.
3717	 */
3718	if ((param_len < 256)
3719	 && (minimum_cmd_size < 10)) {
3720		/*
3721		 * We can fit in a 6 byte cdb.
3722		 */
3723		struct scsi_mode_select_6 *scsi_cmd;
3724
3725		scsi_cmd = (struct scsi_mode_select_6 *)&csio->cdb_io.cdb_bytes;
3726		bzero(scsi_cmd, sizeof(*scsi_cmd));
3727		scsi_cmd->opcode = MODE_SELECT_6;
3728		if (scsi_page_fmt != 0)
3729			scsi_cmd->byte2 |= SMS_PF;
3730		if (save_pages != 0)
3731			scsi_cmd->byte2 |= SMS_SP;
3732		scsi_cmd->length = param_len;
3733		cdb_len = sizeof(*scsi_cmd);
3734	} else {
3735		/*
3736		 * Need a 10 byte cdb.
3737		 */
3738		struct scsi_mode_select_10 *scsi_cmd;
3739
3740		scsi_cmd =
3741		    (struct scsi_mode_select_10 *)&csio->cdb_io.cdb_bytes;
3742		bzero(scsi_cmd, sizeof(*scsi_cmd));
3743		scsi_cmd->opcode = MODE_SELECT_10;
3744		if (scsi_page_fmt != 0)
3745			scsi_cmd->byte2 |= SMS_PF;
3746		if (save_pages != 0)
3747			scsi_cmd->byte2 |= SMS_SP;
3748		scsi_ulto2b(param_len, scsi_cmd->length);
3749		cdb_len = sizeof(*scsi_cmd);
3750	}
3751	cam_fill_csio(csio,
3752		      retries,
3753		      cbfcnp,
3754		      CAM_DIR_OUT,
3755		      tag_action,
3756		      param_buf,
3757		      param_len,
3758		      sense_len,
3759		      cdb_len,
3760		      timeout);
3761}
3762
3763void
3764scsi_log_sense(struct ccb_scsiio *csio, u_int32_t retries,
3765	       void (*cbfcnp)(struct cam_periph *, union ccb *),
3766	       u_int8_t tag_action, u_int8_t page_code, u_int8_t page,
3767	       int save_pages, int ppc, u_int32_t paramptr,
3768	       u_int8_t *param_buf, u_int32_t param_len, u_int8_t sense_len,
3769	       u_int32_t timeout)
3770{
3771	struct scsi_log_sense *scsi_cmd;
3772	u_int8_t cdb_len;
3773
3774	scsi_cmd = (struct scsi_log_sense *)&csio->cdb_io.cdb_bytes;
3775	bzero(scsi_cmd, sizeof(*scsi_cmd));
3776	scsi_cmd->opcode = LOG_SENSE;
3777	scsi_cmd->page = page_code | page;
3778	if (save_pages != 0)
3779		scsi_cmd->byte2 |= SLS_SP;
3780	if (ppc != 0)
3781		scsi_cmd->byte2 |= SLS_PPC;
3782	scsi_ulto2b(paramptr, scsi_cmd->paramptr);
3783	scsi_ulto2b(param_len, scsi_cmd->length);
3784	cdb_len = sizeof(*scsi_cmd);
3785
3786	cam_fill_csio(csio,
3787		      retries,
3788		      cbfcnp,
3789		      /*flags*/CAM_DIR_IN,
3790		      tag_action,
3791		      /*data_ptr*/param_buf,
3792		      /*dxfer_len*/param_len,
3793		      sense_len,
3794		      cdb_len,
3795		      timeout);
3796}
3797
3798void
3799scsi_log_select(struct ccb_scsiio *csio, u_int32_t retries,
3800		void (*cbfcnp)(struct cam_periph *, union ccb *),
3801		u_int8_t tag_action, u_int8_t page_code, int save_pages,
3802		int pc_reset, u_int8_t *param_buf, u_int32_t param_len,
3803		u_int8_t sense_len, u_int32_t timeout)
3804{
3805	struct scsi_log_select *scsi_cmd;
3806	u_int8_t cdb_len;
3807
3808	scsi_cmd = (struct scsi_log_select *)&csio->cdb_io.cdb_bytes;
3809	bzero(scsi_cmd, sizeof(*scsi_cmd));
3810	scsi_cmd->opcode = LOG_SELECT;
3811	scsi_cmd->page = page_code & SLS_PAGE_CODE;
3812	if (save_pages != 0)
3813		scsi_cmd->byte2 |= SLS_SP;
3814	if (pc_reset != 0)
3815		scsi_cmd->byte2 |= SLS_PCR;
3816	scsi_ulto2b(param_len, scsi_cmd->length);
3817	cdb_len = sizeof(*scsi_cmd);
3818
3819	cam_fill_csio(csio,
3820		      retries,
3821		      cbfcnp,
3822		      /*flags*/CAM_DIR_OUT,
3823		      tag_action,
3824		      /*data_ptr*/param_buf,
3825		      /*dxfer_len*/param_len,
3826		      sense_len,
3827		      cdb_len,
3828		      timeout);
3829}
3830
3831/*
3832 * Prevent or allow the user to remove the media
3833 */
3834void
3835scsi_prevent(struct ccb_scsiio *csio, u_int32_t retries,
3836	     void (*cbfcnp)(struct cam_periph *, union ccb *),
3837	     u_int8_t tag_action, u_int8_t action,
3838	     u_int8_t sense_len, u_int32_t timeout)
3839{
3840	struct scsi_prevent *scsi_cmd;
3841
3842	cam_fill_csio(csio,
3843		      retries,
3844		      cbfcnp,
3845		      /*flags*/CAM_DIR_NONE,
3846		      tag_action,
3847		      /*data_ptr*/NULL,
3848		      /*dxfer_len*/0,
3849		      sense_len,
3850		      sizeof(*scsi_cmd),
3851		      timeout);
3852
3853	scsi_cmd = (struct scsi_prevent *)&csio->cdb_io.cdb_bytes;
3854	bzero(scsi_cmd, sizeof(*scsi_cmd));
3855	scsi_cmd->opcode = PREVENT_ALLOW;
3856	scsi_cmd->how = action;
3857}
3858
3859/* XXX allow specification of address and PMI bit and LBA */
3860void
3861scsi_read_capacity(struct ccb_scsiio *csio, u_int32_t retries,
3862		   void (*cbfcnp)(struct cam_periph *, union ccb *),
3863		   u_int8_t tag_action,
3864		   struct scsi_read_capacity_data *rcap_buf,
3865		   u_int8_t sense_len, u_int32_t timeout)
3866{
3867	struct scsi_read_capacity *scsi_cmd;
3868
3869	cam_fill_csio(csio,
3870		      retries,
3871		      cbfcnp,
3872		      /*flags*/CAM_DIR_IN,
3873		      tag_action,
3874		      /*data_ptr*/(u_int8_t *)rcap_buf,
3875		      /*dxfer_len*/sizeof(*rcap_buf),
3876		      sense_len,
3877		      sizeof(*scsi_cmd),
3878		      timeout);
3879
3880	scsi_cmd = (struct scsi_read_capacity *)&csio->cdb_io.cdb_bytes;
3881	bzero(scsi_cmd, sizeof(*scsi_cmd));
3882	scsi_cmd->opcode = READ_CAPACITY;
3883}
3884
3885void
3886scsi_read_capacity_16(struct ccb_scsiio *csio, uint32_t retries,
3887		      void (*cbfcnp)(struct cam_periph *, union ccb *),
3888		      uint8_t tag_action, uint64_t lba, int reladr, int pmi,
3889		      struct scsi_read_capacity_data_long *rcap_buf,
3890		      uint8_t sense_len, uint32_t timeout)
3891{
3892	struct scsi_read_capacity_16 *scsi_cmd;
3893
3894
3895	cam_fill_csio(csio,
3896		      retries,
3897		      cbfcnp,
3898		      /*flags*/CAM_DIR_IN,
3899		      tag_action,
3900		      /*data_ptr*/(u_int8_t *)rcap_buf,
3901		      /*dxfer_len*/sizeof(*rcap_buf),
3902		      sense_len,
3903		      sizeof(*scsi_cmd),
3904		      timeout);
3905	scsi_cmd = (struct scsi_read_capacity_16 *)&csio->cdb_io.cdb_bytes;
3906	bzero(scsi_cmd, sizeof(*scsi_cmd));
3907	scsi_cmd->opcode = SERVICE_ACTION_IN;
3908	scsi_cmd->service_action = SRC16_SERVICE_ACTION;
3909	scsi_u64to8b(lba, scsi_cmd->addr);
3910	scsi_ulto4b(sizeof(*rcap_buf), scsi_cmd->alloc_len);
3911	if (pmi)
3912		reladr |= SRC16_PMI;
3913	if (reladr)
3914		reladr |= SRC16_RELADR;
3915}
3916
3917void
3918scsi_report_luns(struct ccb_scsiio *csio, u_int32_t retries,
3919		 void (*cbfcnp)(struct cam_periph *, union ccb *),
3920		 u_int8_t tag_action, u_int8_t select_report,
3921		 struct scsi_report_luns_data *rpl_buf, u_int32_t alloc_len,
3922		 u_int8_t sense_len, u_int32_t timeout)
3923{
3924	struct scsi_report_luns *scsi_cmd;
3925
3926	cam_fill_csio(csio,
3927		      retries,
3928		      cbfcnp,
3929		      /*flags*/CAM_DIR_IN,
3930		      tag_action,
3931		      /*data_ptr*/(u_int8_t *)rpl_buf,
3932		      /*dxfer_len*/alloc_len,
3933		      sense_len,
3934		      sizeof(*scsi_cmd),
3935		      timeout);
3936	scsi_cmd = (struct scsi_report_luns *)&csio->cdb_io.cdb_bytes;
3937	bzero(scsi_cmd, sizeof(*scsi_cmd));
3938	scsi_cmd->opcode = REPORT_LUNS;
3939	scsi_cmd->select_report = select_report;
3940	scsi_ulto4b(alloc_len, scsi_cmd->length);
3941}
3942
3943/*
3944 * Syncronize the media to the contents of the cache for
3945 * the given lba/count pair.  Specifying 0/0 means sync
3946 * the whole cache.
3947 */
3948void
3949scsi_synchronize_cache(struct ccb_scsiio *csio, u_int32_t retries,
3950		       void (*cbfcnp)(struct cam_periph *, union ccb *),
3951		       u_int8_t tag_action, u_int32_t begin_lba,
3952		       u_int16_t lb_count, u_int8_t sense_len,
3953		       u_int32_t timeout)
3954{
3955	struct scsi_sync_cache *scsi_cmd;
3956
3957	cam_fill_csio(csio,
3958		      retries,
3959		      cbfcnp,
3960		      /*flags*/CAM_DIR_NONE,
3961		      tag_action,
3962		      /*data_ptr*/NULL,
3963		      /*dxfer_len*/0,
3964		      sense_len,
3965		      sizeof(*scsi_cmd),
3966		      timeout);
3967
3968	scsi_cmd = (struct scsi_sync_cache *)&csio->cdb_io.cdb_bytes;
3969	bzero(scsi_cmd, sizeof(*scsi_cmd));
3970	scsi_cmd->opcode = SYNCHRONIZE_CACHE;
3971	scsi_ulto4b(begin_lba, scsi_cmd->begin_lba);
3972	scsi_ulto2b(lb_count, scsi_cmd->lb_count);
3973}
3974
3975void
3976scsi_read_write(struct ccb_scsiio *csio, u_int32_t retries,
3977		void (*cbfcnp)(struct cam_periph *, union ccb *),
3978		u_int8_t tag_action, int readop, u_int8_t byte2,
3979		int minimum_cmd_size, u_int64_t lba, u_int32_t block_count,
3980		u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
3981		u_int32_t timeout)
3982{
3983	u_int8_t cdb_len;
3984	/*
3985	 * Use the smallest possible command to perform the operation
3986	 * as some legacy hardware does not support the 10 byte commands.
3987	 * If any of the bits in byte2 is set, we have to go with a larger
3988	 * command.
3989	 */
3990	if ((minimum_cmd_size < 10)
3991	 && ((lba & 0x1fffff) == lba)
3992	 && ((block_count & 0xff) == block_count)
3993	 && (byte2 == 0)) {
3994		/*
3995		 * We can fit in a 6 byte cdb.
3996		 */
3997		struct scsi_rw_6 *scsi_cmd;
3998
3999		scsi_cmd = (struct scsi_rw_6 *)&csio->cdb_io.cdb_bytes;
4000		scsi_cmd->opcode = readop ? READ_6 : WRITE_6;
4001		scsi_ulto3b(lba, scsi_cmd->addr);
4002		scsi_cmd->length = block_count & 0xff;
4003		scsi_cmd->control = 0;
4004		cdb_len = sizeof(*scsi_cmd);
4005
4006		CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE,
4007			  ("6byte: %x%x%x:%d:%d\n", scsi_cmd->addr[0],
4008			   scsi_cmd->addr[1], scsi_cmd->addr[2],
4009			   scsi_cmd->length, dxfer_len));
4010	} else if ((minimum_cmd_size < 12)
4011		&& ((block_count & 0xffff) == block_count)
4012		&& ((lba & 0xffffffff) == lba)) {
4013		/*
4014		 * Need a 10 byte cdb.
4015		 */
4016		struct scsi_rw_10 *scsi_cmd;
4017
4018		scsi_cmd = (struct scsi_rw_10 *)&csio->cdb_io.cdb_bytes;
4019		scsi_cmd->opcode = readop ? READ_10 : WRITE_10;
4020		scsi_cmd->byte2 = byte2;
4021		scsi_ulto4b(lba, scsi_cmd->addr);
4022		scsi_cmd->reserved = 0;
4023		scsi_ulto2b(block_count, scsi_cmd->length);
4024		scsi_cmd->control = 0;
4025		cdb_len = sizeof(*scsi_cmd);
4026
4027		CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE,
4028			  ("10byte: %x%x%x%x:%x%x: %d\n", scsi_cmd->addr[0],
4029			   scsi_cmd->addr[1], scsi_cmd->addr[2],
4030			   scsi_cmd->addr[3], scsi_cmd->length[0],
4031			   scsi_cmd->length[1], dxfer_len));
4032	} else if ((minimum_cmd_size < 16)
4033		&& ((block_count & 0xffffffff) == block_count)
4034		&& ((lba & 0xffffffff) == lba)) {
4035		/*
4036		 * The block count is too big for a 10 byte CDB, use a 12
4037		 * byte CDB.
4038		 */
4039		struct scsi_rw_12 *scsi_cmd;
4040
4041		scsi_cmd = (struct scsi_rw_12 *)&csio->cdb_io.cdb_bytes;
4042		scsi_cmd->opcode = readop ? READ_12 : WRITE_12;
4043		scsi_cmd->byte2 = byte2;
4044		scsi_ulto4b(lba, scsi_cmd->addr);
4045		scsi_cmd->reserved = 0;
4046		scsi_ulto4b(block_count, scsi_cmd->length);
4047		scsi_cmd->control = 0;
4048		cdb_len = sizeof(*scsi_cmd);
4049
4050		CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE,
4051			  ("12byte: %x%x%x%x:%x%x%x%x: %d\n", scsi_cmd->addr[0],
4052			   scsi_cmd->addr[1], scsi_cmd->addr[2],
4053			   scsi_cmd->addr[3], scsi_cmd->length[0],
4054			   scsi_cmd->length[1], scsi_cmd->length[2],
4055			   scsi_cmd->length[3], dxfer_len));
4056	} else {
4057		/*
4058		 * 16 byte CDB.  We'll only get here if the LBA is larger
4059		 * than 2^32, or if the user asks for a 16 byte command.
4060		 */
4061		struct scsi_rw_16 *scsi_cmd;
4062
4063		scsi_cmd = (struct scsi_rw_16 *)&csio->cdb_io.cdb_bytes;
4064		scsi_cmd->opcode = readop ? READ_16 : WRITE_16;
4065		scsi_cmd->byte2 = byte2;
4066		scsi_u64to8b(lba, scsi_cmd->addr);
4067		scsi_cmd->reserved = 0;
4068		scsi_ulto4b(block_count, scsi_cmd->length);
4069		scsi_cmd->control = 0;
4070		cdb_len = sizeof(*scsi_cmd);
4071	}
4072	cam_fill_csio(csio,
4073		      retries,
4074		      cbfcnp,
4075		      /*flags*/readop ? CAM_DIR_IN : CAM_DIR_OUT,
4076		      tag_action,
4077		      data_ptr,
4078		      dxfer_len,
4079		      sense_len,
4080		      cdb_len,
4081		      timeout);
4082}
4083
4084void
4085scsi_start_stop(struct ccb_scsiio *csio, u_int32_t retries,
4086		void (*cbfcnp)(struct cam_periph *, union ccb *),
4087		u_int8_t tag_action, int start, int load_eject,
4088		int immediate, u_int8_t sense_len, u_int32_t timeout)
4089{
4090	struct scsi_start_stop_unit *scsi_cmd;
4091	int extra_flags = 0;
4092
4093	scsi_cmd = (struct scsi_start_stop_unit *)&csio->cdb_io.cdb_bytes;
4094	bzero(scsi_cmd, sizeof(*scsi_cmd));
4095	scsi_cmd->opcode = START_STOP_UNIT;
4096	if (start != 0) {
4097		scsi_cmd->how |= SSS_START;
4098		/* it takes a lot of power to start a drive */
4099		extra_flags |= CAM_HIGH_POWER;
4100	}
4101	if (load_eject != 0)
4102		scsi_cmd->how |= SSS_LOEJ;
4103	if (immediate != 0)
4104		scsi_cmd->byte2 |= SSS_IMMED;
4105
4106	cam_fill_csio(csio,
4107		      retries,
4108		      cbfcnp,
4109		      /*flags*/CAM_DIR_NONE | extra_flags,
4110		      tag_action,
4111		      /*data_ptr*/NULL,
4112		      /*dxfer_len*/0,
4113		      sense_len,
4114		      sizeof(*scsi_cmd),
4115		      timeout);
4116
4117}
4118
4119
4120/*
4121 * Try make as good a match as possible with
4122 * available sub drivers
4123 */
4124int
4125scsi_inquiry_match(caddr_t inqbuffer, caddr_t table_entry)
4126{
4127	struct scsi_inquiry_pattern *entry;
4128	struct scsi_inquiry_data *inq;
4129
4130	entry = (struct scsi_inquiry_pattern *)table_entry;
4131	inq = (struct scsi_inquiry_data *)inqbuffer;
4132
4133	if (((SID_TYPE(inq) == entry->type)
4134	  || (entry->type == T_ANY))
4135	 && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE
4136				   : entry->media_type & SIP_MEDIA_FIXED)
4137	 && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0)
4138	 && (cam_strmatch(inq->product, entry->product,
4139			  sizeof(inq->product)) == 0)
4140	 && (cam_strmatch(inq->revision, entry->revision,
4141			  sizeof(inq->revision)) == 0)) {
4142		return (0);
4143	}
4144        return (-1);
4145}
4146
4147/*
4148 * Try make as good a match as possible with
4149 * available sub drivers
4150 */
4151int
4152scsi_static_inquiry_match(caddr_t inqbuffer, caddr_t table_entry)
4153{
4154	struct scsi_static_inquiry_pattern *entry;
4155	struct scsi_inquiry_data *inq;
4156
4157	entry = (struct scsi_static_inquiry_pattern *)table_entry;
4158	inq = (struct scsi_inquiry_data *)inqbuffer;
4159
4160	if (((SID_TYPE(inq) == entry->type)
4161	  || (entry->type == T_ANY))
4162	 && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE
4163				   : entry->media_type & SIP_MEDIA_FIXED)
4164	 && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0)
4165	 && (cam_strmatch(inq->product, entry->product,
4166			  sizeof(inq->product)) == 0)
4167	 && (cam_strmatch(inq->revision, entry->revision,
4168			  sizeof(inq->revision)) == 0)) {
4169		return (0);
4170	}
4171        return (-1);
4172}
4173
4174#ifdef _KERNEL
4175static void
4176init_scsi_delay(void)
4177{
4178	int delay;
4179
4180	delay = SCSI_DELAY;
4181	TUNABLE_INT_FETCH("kern.cam.scsi_delay", &delay);
4182
4183	if (set_scsi_delay(delay) != 0) {
4184		printf("cam: invalid value for tunable kern.cam.scsi_delay\n");
4185		set_scsi_delay(SCSI_DELAY);
4186	}
4187}
4188SYSINIT(scsi_delay, SI_SUB_TUNABLES, SI_ORDER_ANY, init_scsi_delay, NULL);
4189
4190static int
4191sysctl_scsi_delay(SYSCTL_HANDLER_ARGS)
4192{
4193	int error, delay;
4194
4195	delay = scsi_delay;
4196	error = sysctl_handle_int(oidp, &delay, 0, req);
4197	if (error != 0 || req->newptr == NULL)
4198		return (error);
4199	return (set_scsi_delay(delay));
4200}
4201SYSCTL_PROC(_kern_cam, OID_AUTO, scsi_delay, CTLTYPE_INT|CTLFLAG_RW,
4202    0, 0, sysctl_scsi_delay, "I",
4203    "Delay to allow devices to settle after a SCSI bus reset (ms)");
4204
4205static int
4206set_scsi_delay(int delay)
4207{
4208	/*
4209         * If someone sets this to 0, we assume that they want the
4210         * minimum allowable bus settle delay.
4211	 */
4212	if (delay == 0) {
4213		printf("cam: using minimum scsi_delay (%dms)\n",
4214		    SCSI_MIN_DELAY);
4215		delay = SCSI_MIN_DELAY;
4216	}
4217	if (delay < SCSI_MIN_DELAY)
4218		return (EINVAL);
4219	scsi_delay = delay;
4220	return (0);
4221}
4222#endif /* _KERNEL */
4223