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