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