Make SCSI_DELAY setable at boot time and runtime via the
[dragonfly.git] / sys / bus / cam / scsi / scsi_all.c
1 /*
2  * Implementation of Utility functions for all SCSI device types.
3  *
4  * Copyright (c) 1997, 1998 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  * $FreeBSD: src/sys/cam/scsi/scsi_all.c,v 1.14.2.11 2003/10/30 15:06:35 thomas Exp $
30  * $DragonFly: src/sys/bus/cam/scsi/scsi_all.c,v 1.20 2007/11/24 19:19:43 pavalos Exp $
31  */
32
33 #include <sys/param.h>
34
35 #ifdef _KERNEL
36
37 #include <opt_scsi.h>
38 #include <sys/systm.h>
39 #include <sys/libkern.h>
40 #include <sys/kernel.h>
41 #include <sys/sysctl.h>
42
43 #else
44
45 #include <errno.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49
50 #define ksnprintf       snprintf        /* ick, userland uses us too */
51 #define kprintf         printf
52 #endif
53
54 #include "../cam.h"
55 #include "../cam_ccb.h"
56 #include "../cam_xpt.h"
57 #include "scsi_all.h"
58 #include <sys/sbuf.h>
59 #ifndef _KERNEL
60 #include <sys/camlib.h>
61
62 #ifndef FALSE
63 #define FALSE   0
64 #endif /* FALSE */
65 #ifndef TRUE
66 #define TRUE    1
67 #endif /* TRUE */
68 #define ERESTART        -1              /* restart syscall */
69 #define EJUSTRETURN     -2              /* don't modify regs, just return */
70 #endif /* !_KERNEL */
71
72 /*
73  * This is the default number of seconds we wait for devices to settle
74  * after a SCSI bus reset.
75  */
76 #ifndef SCSI_DELAY
77 #define SCSI_DELAY 2000
78 #endif
79 /*
80  * All devices need _some_ sort of bus settle delay, so we'll set it to
81  * a minimum value of 100ms.
82  */
83 #ifndef SCSI_MIN_DELAY
84 #define SCSI_MIN_DELAY 100
85 #endif
86 /*
87  * Make sure the user isn't using seconds instead of milliseconds.
88  */
89 #if (SCSI_DELAY < SCSI_MIN_DELAY)
90 #error "SCSI_DELAY is in milliseconds, not seconds!  Please use a larger value"
91 #endif
92
93 int scsi_delay;
94
95 static int      ascentrycomp(const void *key, const void *member);
96 static int      senseentrycomp(const void *key, const void *member);
97 static void     fetchtableentries(int sense_key, int asc, int ascq,
98                                   struct scsi_inquiry_data *,
99                                   const struct sense_key_table_entry **,
100                                   const struct asc_table_entry **);
101 #ifdef _KERNEL
102 static void     init_scsi_delay(void);
103 static int      sysctl_scsi_delay(SYSCTL_HANDLER_ARGS);
104 static int      set_scsi_delay(int delay);
105 #endif
106
107 #if !defined(SCSI_NO_OP_STRINGS)
108
109 #define D 0x001
110 #define T 0x002
111 #define L 0x004
112 #define P 0x008
113 #define W 0x010
114 #define R 0x020
115 #define S 0x040
116 #define O 0x080
117 #define M 0x100
118 #define C 0x200
119 #define A 0x400
120 #define E 0x800
121
122 #define ALL 0xFFF
123
124 static struct op_table_entry plextor_cd_ops[] = {
125         {0xD8, R, "CD-DA READ"}
126 };
127
128 static struct scsi_op_quirk_entry scsi_op_quirk_table[] = {
129         {
130                 /*
131                  * I believe that 0xD8 is the Plextor proprietary command
132                  * to read CD-DA data.  I'm not sure which Plextor CDROM
133                  * models support the command, though.  I know for sure
134                  * that the 4X, 8X, and 12X models do, and presumably the
135                  * 12-20X does.  I don't know about any earlier models,
136                  * though.  If anyone has any more complete information,
137                  * feel free to change this quirk entry.
138                  */
139                 {T_CDROM, SIP_MEDIA_REMOVABLE, "PLEXTOR", "CD-ROM PX*", "*"},
140                 sizeof(plextor_cd_ops)/sizeof(struct op_table_entry),
141                 plextor_cd_ops
142         }
143 };
144
145 static struct op_table_entry scsi_op_codes[] = {
146 /*
147  * From: ftp://ftp.symbios.com/pub/standards/io/t10/drafts/spc/op-num.txt
148  * Modifications by Kenneth Merry (ken@FreeBSD.ORG)
149  *
150  * Note:  order is important in this table, scsi_op_desc() currently
151  * depends on the opcodes in the table being in order to save search time.
152  */
153 /*  
154  * File: OP-NUM.TXT
155  *
156  * SCSI Operation Codes
157  * Numeric Sorted Listing
158  * as of 11/13/96
159  * 
160  *     D - DIRECT ACCESS DEVICE (SBC)                    device column key
161  *     .T - SEQUENTIAL ACCESS DEVICE (SSC)              -------------------
162  *     . L - PRINTER DEVICE (SSC)                       M = Mandatory
163  *     .  P - PROCESSOR DEVICE (SPC)                    O = Optional
164  *     .  .W - WRITE ONCE READ MULTIPLE DEVICE (SBC)    V = Vendor specific
165  *     .  . R - CD DEVICE (MMC)                         R = Reserved
166  *     .  .  S - SCANNER DEVICE (SGC)                   Z = Obsolete
167  *     .  .  .O - OPTICAL MEMORY DEVICE (SBC)
168  *     .  .  . M - MEDIA CHANGER DEVICE (SMC)
169  *     .  .  .  C - COMMUNICATION DEVICE (SSC)
170  *     .  .  .  .A - STORAGE ARRAY DEVICE (SCC)
171  *     .  .  .  . E - ENCLOSURE SERVICES DEVICE (SES)
172  * OP  DTLPWRSOMCAE  Description
173  * --  ------------  ---------------------------------------------------- */
174 /* 00  MMMMMMMMMMMM  TEST UNIT READY */
175 {0x00, ALL,             "TEST UNIT READY"},
176
177 /* 01   M            REWIND */
178 {0x01, T,           "REWIND"},
179 /* 01  Z V ZO ZO     REZERO UNIT */
180 {0x01, D|L|W|O|M,   "REZERO UNIT"},
181
182 /* 02  VVVVVV  V   */
183
184 /* 03  MMMMMMMMMMMM  REQUEST SENSE */
185 {0x03, ALL,         "REQUEST SENSE"},
186
187 /* 04  M    O O      FORMAT UNIT */
188 {0x04, D|R|O,       "FORMAT UNIT"},
189 /* 04   O            FORMAT MEDIUM */
190 {0x04, T,           "FORMAT MEDIUM"},
191 /* 04    O           FORMAT */
192 {0x04, L,           "FORMAT"},
193
194 /* 05  VMVVVV  V     READ BLOCK LIMITS */
195 {0x05, T,           "READ BLOCK LIMITS"},
196
197 /* 06  VVVVVV  V   */
198
199 /* 07  OVV O  OV     REASSIGN BLOCKS */
200 {0x07, D|W|O,       "REASSIGN BLOCKS"},
201 /* 07          O     INITIALIZE ELEMENT STATUS */
202 {0x07, M,           "INITIALIZE ELEMENT STATUS"},
203
204 /* 08  OMV OO OV     READ(06) */
205 {0x08, D|T|W|R|O,   "READ(06)"},
206 /* 08     O          RECEIVE */
207 {0x08, P,           "RECEIVE"},
208 /* 08           M    GET MESSAGE(06) */
209 {0x08, C,           "GET MESSAGE(06)"},
210
211 /* 09  VVVVVV  V   */
212
213 /* 0A  OM  O  OV     WRITE(06) */
214 {0x0A, D|T|W|O, "WRITE(06)"},
215 /* 0A     M          SEND(06) */
216 {0x0A, P,           "SEND(06)"},
217 /* 0A           M    SEND MESSAGE(06) */
218 {0x0A, C,           "SEND MESSAGE(06)"},
219 /* 0A    M           PRINT */
220 {0x0A, L,           "PRINT"},
221
222 /* 0B  Z   ZO ZV     SEEK(06) */
223 {0x0B, D|W|R|O,     "SEEK(06)"},
224 /* 0B    O           SLEW AND PRINT */
225 {0x0B, L,           "SLEW AND PRINT"},
226
227 /* 0C  VVVVVV  V   */
228 /* 0D  VVVVVV  V   */
229 /* 0E  VVVVVV  V   */
230 /* 0F  VOVVVV  V     READ REVERSE */
231 {0x0F, T,           "READ REVERSE"},
232
233 /* 10  VM VVV        WRITE FILEMARKS */
234 {0x10, T,           "WRITE FILEMARKS"},
235 /* 10    O O         SYNCHRONIZE BUFFER */
236 {0x10, L|W,         "SYNCHRONIZE BUFFER"},
237
238 /* 11  VMVVVV        SPACE */
239 {0x11, T,           "SPACE"},
240
241 /* 12  MMMMMMMMMMMM  INQUIRY */
242 {0x12, ALL,         "INQUIRY"},
243
244 /* 13  VOVVVV        VERIFY(06) */
245 {0x13, T,           "VERIFY(06)"},
246
247 /* 14  VOOVVV        RECOVER BUFFERED DATA */
248 {0x14, T|L,         "RECOVER BUFFERED DATA"},
249
250 /* 15  OMO OOOOOOOO  MODE SELECT(06) */
251 {0x15, ALL & ~(P),    "MODE SELECT(06)"},
252
253 /* 16  MMMOMMMM   O  RESERVE(06) */
254 {0x16, D|T|L|P|W|R|S|O|E, "RESERVE(06)"},
255 /* 16          M     RESERVE ELEMENT(06) */
256 {0x16, M,           "RESERVE ELEMENT(06)"},
257
258 /* 17  MMMOMMMM   O  RELEASE(06) */
259 {0x17, ALL & ~(M|C|A), "RELEASE(06)"},
260 /* 17          M     RELEASE ELEMENT(06) */
261 {0x17, M,           "RELEASE ELEMENT(06)"},
262
263 /* 18  OOOOOOOO      COPY */
264 {0x18, ALL & ~(M|C|A|E), "COPY"},
265
266 /* 19  VMVVVV        ERASE */
267 {0x19, T,           "ERASE"},
268
269 /* 1A  OMO OOOOOOOO  MODE SENSE(06) */
270 {0x1A, ALL & ~(P),  "MODE SENSE(06)"},
271
272 /* 1B  O   OM O      STOP START UNIT */
273 {0x1B, D|W|R|O,     "STOP START UNIT"},
274 /* 1B   O            LOAD UNLOAD */
275 {0x1B, T,           "LOAD UNLOAD"},
276 /* 1B        O       SCAN */
277 {0x1B, S,           "SCAN"},
278 /* 1B    O           STOP PRINT */
279 {0x1B, L,           "STOP PRINT"},
280
281 /* 1C  OOOOOOOOOO M  RECEIVE DIAGNOSTIC RESULTS */
282 {0x1C, ALL & ~(A),  "RECEIVE DIAGNOSTIC RESULTS"},
283
284 /* 1D  MMMMMMMMMMMM  SEND DIAGNOSTIC */
285 {0x1D, ALL,         "SEND DIAGNOSTIC"},
286
287 /* 1E  OO  OM OO     PREVENT ALLOW MEDIUM REMOVAL */
288 {0x1E, D|T|W|R|O|M, "PREVENT ALLOW MEDIUM REMOVAL"},
289
290 /* 1F */
291 /* 20  V   VV V */
292 /* 21  V   VV V */
293 /* 22  V   VV V */
294 /* 23  V   VV V */
295
296 /* 24  V   VVM       SET WINDOW */
297 {0x24, S,           "SET WINDOW"},
298
299 /* 25  M   M  M      READ CAPACITY */
300 {0x25, D|W|O,       "READ CAPACITY"},
301 /* 25       M        READ CD RECORDED CAPACITY */
302 {0x25, R,           "READ CD RECORDED CAPACITY"},
303 /* 25        O       GET WINDOW */
304 {0x25, S,           "GET WINDOW"},
305
306 /* 26  V   VV */
307 /* 27  V   VV */
308
309 /* 28  M   MMMM      READ(10) */
310 {0x28, D|W|R|S|O,   "READ(10)"},
311 /* 28           O    GET MESSAGE(10) */
312 {0x28, C,           "GET MESSAGE(10)"},
313
314 /* 29  V   VV O      READ GENERATION */
315 {0x29, O,           "READ GENERATION"},
316
317 /* 2A  M   MM M      WRITE(10) */
318 {0x2A, D|W|R|O,     "WRITE(10)"},
319 /* 2A        O       SEND(10) */
320 {0x2A, S,           "SEND(10)"},
321 /* 2A           O    SEND MESSAGE(10) */
322 {0x2A, C,           "SEND MESSAGE(10)"},
323
324 /* 2B  O   OM O      SEEK(10) */
325 {0x2B, D|W|R|O,     "SEEK(10)"},
326 /* 2B   O            LOCATE */
327 {0x2B, T,           "LOCATE"},
328 /* 2B          O     POSITION TO ELEMENT */
329 {0x2B, M,           "POSITION TO ELEMENT"},
330
331 /* 2C  V      O      ERASE(10) */
332 {0x2C, O,           "ERASE(10)"},
333
334 /* 2D  V   O  O      READ UPDATED BLOCK */
335 {0x2D, W|O,         "READ UPDATED BLOCK"},
336
337 /* 2E  O   O  O      WRITE AND VERIFY(10) */
338 {0x2E, D|W|O,       "WRITE AND VERIFY(10)"},
339
340 /* 2F  O   OO O      VERIFY(10) */
341 {0x2F, D|W|R|O,     "VERIFY(10)"},
342
343 /* 30  Z   ZO Z      SEARCH DATA HIGH(10) */
344 {0x30, D|W|R|O,     "SEARCH DATA HIGH(10)"},
345
346 /* 31  Z   ZO Z      SEARCH DATA EQUAL(10) */
347 {0x31, D|W|R|O,     "SEARCH DATA EQUAL(10)"},
348 /* 31        O       OBJECT POSITION */
349 {0x31, S,           "OBJECT POSITION"},
350
351 /* 32  Z   ZO Z      SEARCH DATA LOW(10) */
352 {0x32, D|W|R|O,     "SEARCH DATA LOW(10"},
353
354 /* 33  O   OO O      SET LIMITS(10) */
355 {0x33, D|W|R|O,     "SET LIMITS(10)"},
356
357 /* 34  O   OO O      PRE-FETCH */
358 {0x34, D|W|R|O,     "PRE-FETCH"},
359 /* 34   O            READ POSITION */
360 {0x34, T,           "READ POSITION"},
361 /* 34        O       GET DATA BUFFER STATUS */
362 {0x34, S,           "GET DATA BUFFER STATUS"},
363
364 /* 35  O   OM O      SYNCHRONIZE CACHE */
365 {0x35, D|W|R|O,     "SYNCHRONIZE CACHE"},
366
367 /* 36  O   OO O      LOCK UNLOCK CACHE */
368 {0x36, D|W|R|O,     "LOCK UNLOCK CACHE"},
369
370 /* 37  O      O      READ DEFECT DATA(10) */
371 {0x37, D|O,         "READ DEFECT DATA(10)"},
372
373 /* 38      O  O      MEDIUM SCAN */
374 {0x38, W|O,         "MEDIUM SCAN"},
375
376 /* 39  OOOOOOOO      COMPARE */
377 {0x39, ALL & ~(M|C|A|E), "COMPARE"},
378
379 /* 3A  OOOOOOOO      COPY AND VERIFY */
380 {0x3A, ALL & ~(M|C|A|E), "COPY AND VERIFY"},
381
382 /* 3B  OOOOOOOOOO O  WRITE BUFFER */
383 {0x3B, ALL & ~(A),  "WRITE BUFFER"},
384
385 /* 3C  OOOOOOOOOO    READ BUFFER */
386 {0x3C, ALL & ~(A|E),"READ BUFFER"},
387
388 /* 3D      O  O      UPDATE BLOCK */
389 {0x3D, W|O,         "UPDATE BLOCK"},
390
391 /* 3E  O   OO O      READ LONG */
392 {0x3E, D|W|R|O,     "READ LONG"},
393
394 /* 3F  O   O  O      WRITE LONG */
395 {0x3F, D|W|O,       "WRITE LONG"},
396
397 /* 40  OOOOOOOOOO    CHANGE DEFINITION */
398 {0x40, ALL & ~(A|E),"CHANGE DEFINITION"},
399
400 /* 41  O             WRITE SAME */
401 {0x41, D,           "WRITE SAME"},
402
403 /* 42       M        READ SUB-CHANNEL */
404 {0x42, R,           "READ SUB-CHANNEL"}, 
405
406 /* 43       M        READ TOC/PMA/ATIP {MMC Proposed} */
407 {0x43, R,           "READ TOC/PMA/ATIP {MMC Proposed}"},
408
409 /* 44   M            REPORT DENSITY SUPPORT */
410 {0x44, T,           "REPORT DENSITY SUPPORT"},
411 /* 44       M        READ HEADER */
412 {0x44, R,           "READ HEADER"},
413
414 /* 45       O        PLAY AUDIO(10) */
415 {0x45, R,           "PLAY AUDIO(10)"},
416
417 /* 46 */
418
419 /* 47       O        PLAY AUDIO MSF */
420 {0x47, R,           "PLAY AUDIO MSF"},
421
422 /* 48       O        PLAY AUDIO TRACK INDEX */
423 {0x48, R,           "PLAY AUDIO TRACK INDEX"},
424
425 /* 49       O        PLAY TRACK RELATIVE(10) */
426 {0x49, R,           "PLAY TRACK RELATIVE(10)"},
427
428 /* 4A */
429
430 /* 4B       O        PAUSE/RESUME */
431 {0x4B, R,           "PAUSE/RESUME"},
432
433 /* 4C  OOOOOOOOOOO   LOG SELECT */
434 {0x4C, ALL & ~(E),  "LOG SELECT"},
435
436 /* 4D  OOOOOOOOOOO   LOG SENSE */
437 {0x4D, ALL & ~(E),  "LOG SENSE"},
438
439 /* 4E       O        STOP PLAY/SCAN {MMC Proposed} */
440 {0x4E, R,           "STOP PLAY/SCAN {MMC Proposed}"},
441
442 /* 4F */
443
444 /* 50  O             XDWRITE(10) */
445 {0x50, D,           "XDWRITE(10)"},
446
447 /* 51  O             XPWRITE(10) */
448 {0x51, D,           "XPWRITE(10)"},
449 /* 51       M        READ DISC INFORMATION {MMC Proposed} */
450 {0x51, R,           "READ DISC INFORMATION {MMC Proposed}"},
451
452 /* 52  O             XDREAD(10) */
453 {0x52, D,           "XDREAD(10)"},
454 /* 52       M        READ TRACK INFORMATION {MMC Proposed} */
455 {0x52, R,           "READ TRACK INFORMATION {MMC Proposed}"},
456
457 /* 53       M        RESERVE TRACK {MMC Proposed} */
458 {0x53, R,           "RESERVE TRACK {MMC Proposed}"},
459
460 /* 54       O        SEND OPC INFORMATION {MMC Proposed} */
461 {0x54, R,           "SEND OPC INFORMATION {MMC Proposed}"},
462
463 /* 55  OOO OOOOOOOO  MODE SELECT(10) */
464 {0x55, ALL & ~(P),  "MODE SELECT(10)"},
465
466 /* 56  MMMOMMMM   O  RESERVE(10) */
467 {0x56, ALL & ~(M|C|A), "RESERVE(10)"},
468 /* 56          M     RESERVE ELEMENT(10) */
469 {0x56, M,           "RESERVE ELEMENT(10)"},
470
471 /* 57  MMMOMMMM   O  RELEASE(10) */
472 {0x57, ALL & ~(M|C|A), "RELEASE(10"},
473 /* 57          M     RELEASE ELEMENT(10) */
474 {0x57, M,           "RELEASE ELEMENT(10)"},
475
476 /* 58       O        REPAIR TRACK {MMC Proposed} */
477 {0x58, R,           "REPAIR TRACK {MMC Proposed}"},
478
479 /* 59       O        READ MASTER CUE {MMC Proposed} */
480 {0x59, R,           "READ MASTER CUE {MMC Proposed}"},
481
482 /* 5A  OOO OOOOOOOO  MODE SENSE(10) */
483 {0x5A, ALL & ~(P),  "MODE SENSE(10)"},
484
485 /* 5B       M        CLOSE TRACK/SESSION {MMC Proposed} */
486 {0x5B, R,           "CLOSE TRACK/SESSION {MMC Proposed}"},
487
488 /* 5C       O        READ BUFFER CAPACITY {MMC Proposed} */
489 {0x5C, R,           "READ BUFFER CAPACITY {MMC Proposed}"},
490
491 /* 5D       O        SEND CUE SHEET {MMC Proposed} */
492 {0x5D, R,           "SEND CUE SHEET {MMC Proposed}"},
493
494 /* 5E  OOOOOOOOO  O  PERSISTENT RESERVE IN */
495 {0x5E, ALL & ~(C|A),"PERSISTENT RESERVE IN"},
496
497 /* 5F  OOOOOOOOO  O  PERSISTENT RESERVE OUT */
498 {0x5F, ALL & ~(C|A),"PERSISTENT RESERVE OUT"},
499
500 /* 80  O             XDWRITE EXTENDED(16) */
501 {0x80, D,           "XDWRITE EXTENDED(16)"},
502
503 /* 81  O             REBUILD(16) */
504 {0x81, D,           "REBUILD(16)"},
505
506 /* 82  O             REGENERATE(16) */
507 {0x82, D,           "REGENERATE(16)"},
508
509 /* 83 */
510 /* 84 */
511 /* 85 */
512 /* 86 */
513 /* 87 */
514 /* 88  MM  OO O    O   READ(16) */
515 {0x88, D|T|W|R|O,     "READ(16)"},
516 /* 89 */
517 /* 8A  OM  O  O    O   WRITE(16) */
518 {0x8A, D|T|W|R|O,     "WRITE(16)"},
519 /* 8B */
520 /* 8C */
521 /* 8D */
522 /* 8E */
523 /* 8F */
524 /* 90 */
525 /* 91 */
526 /* 92 */
527 /* 93 */
528 /* 94 */
529 /* 95 */
530 /* 96 */
531 /* 97 */
532 /* 98 */
533 /* 99 */
534 /* 9A */
535 /* 9B */
536 /* 9C */
537 /* 9D */
538 /* XXX KDM ALL for these?  op-num.txt defines them for none.. */
539 /* 9E                  SERVICE ACTION IN(16) */
540 {0x9E, ALL,           "SERVICE ACTION IN(16)"},
541 /* 9F                  SERVICE ACTION OUT(16) */
542 {0x9F, ALL,           "SERVICE ACTION OUT(16)"},
543
544 /* A0  OOOOOOOOOOO   REPORT LUNS */
545 {0xA0, ALL & ~(E),  "REPORT LUNS"},
546
547 /* A1       O        BLANK {MMC Proposed} */
548 {0xA1, R,           "BLANK {MMC Proposed}"},
549
550 /* A2       O        WRITE CD MSF {MMC Proposed} */
551 {0xA2, R,           "WRITE CD MSF {MMC Proposed}"},
552
553 /* A3            M   MAINTENANCE (IN) */
554 {0xA3, A,           "MAINTENANCE (IN)"},
555
556 /* A4            O   MAINTENANCE (OUT) */
557 {0xA4, A,           "MAINTENANCE (OUT)"},
558
559 /* A5   O      M     MOVE MEDIUM */
560 {0xA5, T|M,         "MOVE MEDIUM"},
561 /* A5       O        PLAY AUDIO(12) */
562 {0xA5, R,           "PLAY AUDIO(12)"},
563
564 /* A6          O     EXCHANGE MEDIUM */
565 {0xA6, M,           "EXCHANGE MEDIUM"},
566 /* A6       O        LOAD/UNLOAD CD {MMC Proposed} */
567 {0xA6, R,           "LOAD/UNLOAD CD {MMC Proposed}"},
568
569 /* A7  OO  OO OO     MOVE MEDIUM ATTACHED */
570 {0xA7, D|T|W|R|O|M, "MOVE MEDIUM ATTACHED"},
571
572 /* A8  O   OM O      READ(12) */
573 {0xA8,D|W|R|O,      "READ(12)"},
574 /* A8           O    GET MESSAGE(12) */
575 {0xA8, C,           "GET MESSAGE(12)"},
576
577 /* A9       O        PLAY TRACK RELATIVE(12) */
578 {0xA9, R,           "PLAY TRACK RELATIVE(12)"},
579
580 /* AA  O   O  O      WRITE(12) */
581 {0xAA,D|W|O,        "WRITE(12)"},
582 /* AA       O        WRITE CD(12) {MMC Proposed} */
583 {0xAA, R,           "WRITE CD(12) {MMC Proposed}"},
584 /* AA           O    SEND MESSAGE(12) */
585 {0xAA, C,           "SEND MESSAGE(12)"},
586
587 /* AB */
588
589 /* AC         O      ERASE(12) */
590 {0xAC, O,           "ERASE(12)"},
591
592 /* AD */
593
594 /* AE      O  O      WRITE AND VERIFY(12) */
595 {0xAE, W|O,         "WRITE AND VERIFY(12)"},
596
597 /* AF      OO O      VERIFY(12) */
598 {0xAF, W|R|O,       "VERIFY(12)"},
599
600 /* B0      ZO Z      SEARCH DATA HIGH(12) */
601 {0xB0, W|R|O,       "SEARCH DATA HIGH(12)"},
602
603 /* B1      ZO Z      SEARCH DATA EQUAL(12) */
604 {0xB1, W|R|O,       "SEARCH DATA EQUAL(12)"},
605
606 /* B2      ZO Z      SEARCH DATA LOW(12) */
607 {0xB2, W|R|O,       "SEARCH DATA LOW(12)"},
608
609 /* B3      OO O      SET LIMITS(12) */
610 {0xB3, W|R|O,       "SET LIMITS(12)"},
611
612 /* B4  OO  OO OO     READ ELEMENT STATUS ATTACHED */
613 {0xB4, D|T|W|R|O|M, "READ ELEMENT STATUS ATTACHED"},
614
615 /* B5          O     REQUEST VOLUME ELEMENT ADDRESS */
616 {0xB5, M,           "REQUEST VOLUME ELEMENT ADDRESS"},
617
618 /* B6          O     SEND VOLUME TAG */
619 {0xB6, M,           "SEND VOLUME TAG"},
620
621 /* B7         O      READ DEFECT DATA(12) */
622 {0xB7, O,           "READ DEFECT DATA(12)"},
623
624 /* B8   O      M     READ ELEMENT STATUS */
625 {0xB8, T|M,         "READ ELEMENT STATUS"},
626 /* B8       O        SET CD SPEED {MMC Proposed} */
627 {0xB8, R,           "SET CD SPEED {MMC Proposed}"},
628
629 /* B9       M        READ CD MSF {MMC Proposed} */
630 {0xB9, R,           "READ CD MSF {MMC Proposed}"},
631
632 /* BA       O        SCAN {MMC Proposed} */
633 {0xBA, R,           "SCAN {MMC Proposed}"},
634 /* BA            M   REDUNDANCY GROUP (IN) */
635 {0xBA, A,           "REDUNDANCY GROUP (IN)"},
636
637 /* BB       O        SET CD-ROM SPEED {proposed} */
638 {0xBB, R,           "SET CD-ROM SPEED {proposed}"},
639 /* BB            O   REDUNDANCY GROUP (OUT) */
640 {0xBB, A,           "REDUNDANCY GROUP (OUT)"},
641
642 /* BC       O        PLAY CD {MMC Proposed} */
643 {0xBC, R,           "PLAY CD {MMC Proposed}"},
644 /* BC            M   SPARE (IN) */
645 {0xBC, A,           "SPARE (IN)"},
646
647 /* BD       M        MECHANISM STATUS {MMC Proposed} */
648 {0xBD, R,           "MECHANISM STATUS {MMC Proposed}"},
649 /* BD            O   SPARE (OUT) */
650 {0xBD, A,           "SPARE (OUT)"},
651
652 /* BE       O        READ CD {MMC Proposed} */
653 {0xBE, R,           "READ CD {MMC Proposed}"},
654 /* BE            M   VOLUME SET (IN) */
655 {0xBE, A,           "VOLUME SET (IN)"},
656
657 /* BF            O   VOLUME SET (OUT) */
658 {0xBF, A,           "VOLUME SET (OUT)"}
659 };
660
661 const char *
662 scsi_op_desc(u_int16_t opcode, struct scsi_inquiry_data *inq_data)
663 {
664         caddr_t match;
665         int i, j;
666         u_int16_t opmask;
667         u_int16_t pd_type;
668         int       num_ops[2];
669         struct op_table_entry *table[2];
670         int num_tables;
671
672         pd_type = SID_TYPE(inq_data);
673
674         match = cam_quirkmatch((caddr_t)inq_data,
675                                (caddr_t)scsi_op_quirk_table,
676                                sizeof(scsi_op_quirk_table)/
677                                sizeof(*scsi_op_quirk_table),
678                                sizeof(*scsi_op_quirk_table),
679                                scsi_inquiry_match);
680
681         if (match != NULL) {
682                 table[0] = ((struct scsi_op_quirk_entry *)match)->op_table;
683                 num_ops[0] = ((struct scsi_op_quirk_entry *)match)->num_ops;
684                 table[1] = scsi_op_codes;
685                 num_ops[1] = sizeof(scsi_op_codes)/sizeof(scsi_op_codes[0]);
686                 num_tables = 2;
687         } else {
688                 /*      
689                  * If this is true, we have a vendor specific opcode that
690                  * wasn't covered in the quirk table.
691                  */
692                 if ((opcode > 0xBF) || ((opcode > 0x5F) && (opcode < 0x80)))
693                         return("Vendor Specific Command");
694
695                 table[0] = scsi_op_codes;
696                 num_ops[0] = sizeof(scsi_op_codes)/sizeof(scsi_op_codes[0]);
697                 num_tables = 1;
698         }
699
700         /* RBC is 'Simplified' Direct Access Device */
701         if (pd_type == T_RBC)
702                 pd_type = T_DIRECT;
703
704         opmask = 1 << pd_type;
705
706         for (j = 0; j < num_tables; j++) {
707                 for (i = 0;i < num_ops[j] && table[j][i].opcode <= opcode; i++){
708                         if ((table[j][i].opcode == opcode) 
709                          && ((table[j][i].opmask & opmask) != 0))
710                                 return(table[j][i].desc);
711                 }
712         }
713         
714         /*
715          * If we can't find a match for the command in the table, we just
716          * assume it's a vendor specifc command.
717          */
718         return("Vendor Specific Command");
719
720 }
721
722 #else /* SCSI_NO_OP_STRINGS */
723
724 const char *
725 scsi_op_desc(u_int16_t opcode, struct scsi_inquiry_data *inq_data)
726 {
727         return("");
728 }
729
730 #endif
731
732
733 #include <sys/param.h>
734
735 #if !defined(SCSI_NO_SENSE_STRINGS)
736 #define SST(asc, ascq, action, desc) \
737         asc, ascq, action, desc
738 #else 
739 const char empty_string[] = "";
740
741 #define SST(asc, ascq, action, desc) \
742         asc, ascq, action, empty_string
743 #endif 
744
745 const struct sense_key_table_entry sense_key_table[] =
746 {
747         { SSD_KEY_NO_SENSE, SS_NOP, "NO SENSE" },
748         { SSD_KEY_RECOVERED_ERROR, SS_NOP|SSQ_PRINT_SENSE, "RECOVERED ERROR" },
749         {
750           SSD_KEY_NOT_READY, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY,
751           "NOT READY"
752         },
753         { SSD_KEY_MEDIUM_ERROR, SS_RDEF, "MEDIUM ERROR" },
754         { SSD_KEY_HARDWARE_ERROR, SS_RDEF, "HARDWARE FAILURE" },
755         { SSD_KEY_ILLEGAL_REQUEST, SS_FATAL|EINVAL, "ILLEGAL REQUEST" },
756         { SSD_KEY_UNIT_ATTENTION, SS_FATAL|ENXIO, "UNIT ATTENTION" },
757         { SSD_KEY_DATA_PROTECT, SS_FATAL|EACCES, "DATA PROTECT" },
758         { SSD_KEY_BLANK_CHECK, SS_FATAL|ENOSPC, "BLANK CHECK" },
759         { SSD_KEY_Vendor_Specific, SS_FATAL|EIO, "Vendor Specific" },
760         { SSD_KEY_COPY_ABORTED, SS_FATAL|EIO, "COPY ABORTED" },
761         { SSD_KEY_ABORTED_COMMAND, SS_RDEF, "ABORTED COMMAND" },
762         { SSD_KEY_EQUAL, SS_NOP, "EQUAL" },
763         { SSD_KEY_VOLUME_OVERFLOW, SS_FATAL|EIO, "VOLUME OVERFLOW" },
764         { SSD_KEY_MISCOMPARE, SS_NOP, "MISCOMPARE" },
765         { SSD_KEY_RESERVED, SS_FATAL|EIO, "RESERVED" }
766 };
767
768 const int sense_key_table_size =
769     sizeof(sense_key_table)/sizeof(sense_key_table[0]);
770
771 static struct asc_table_entry quantum_fireball_entries[] = {
772         {SST(0x04, 0x0b, SS_START|SSQ_DECREMENT_COUNT|ENXIO, 
773              "Logical unit not ready, initializing cmd. required")}
774 };
775
776 static struct asc_table_entry sony_mo_entries[] = {
777         {SST(0x04, 0x00, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
778              "Logical unit not ready, cause not reportable")}
779 };
780
781 static struct scsi_sense_quirk_entry sense_quirk_table[] = {
782         {
783                 /*
784                  * The Quantum Fireball ST and SE like to return 0x04 0x0b when
785                  * they really should return 0x04 0x02.  0x04,0x0b isn't
786                  * defined in any SCSI spec, and it isn't mentioned in the
787                  * hardware manual for these drives.
788                  */
789                 {T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "FIREBALL S*", "*"},
790                 /*num_sense_keys*/0,
791                 sizeof(quantum_fireball_entries)/sizeof(struct asc_table_entry),
792                 /*sense key entries*/NULL,
793                 quantum_fireball_entries
794         },
795         {
796                 /*
797                  * This Sony MO drive likes to return 0x04, 0x00 when it
798                  * isn't spun up.
799                  */
800                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "SONY", "SMO-*", "*"},
801                 /*num_sense_keys*/0,
802                 sizeof(sony_mo_entries)/sizeof(struct asc_table_entry),
803                 /*sense key entries*/NULL,
804                 sony_mo_entries
805         }
806 };
807
808 const int sense_quirk_table_size =
809     sizeof(sense_quirk_table)/sizeof(sense_quirk_table[0]);
810
811 static struct asc_table_entry asc_table[] = {
812 /*
813  * From File: ASC-NUM.TXT
814  * SCSI ASC/ASCQ Assignments
815  * Numeric Sorted Listing
816  * as of  5/12/97
817  *
818  * D - DIRECT ACCESS DEVICE (SBC)                     device column key
819  * .T - SEQUENTIAL ACCESS DEVICE (SSC)               -------------------
820  * . L - PRINTER DEVICE (SSC)                           blank = reserved
821  * .  P - PROCESSOR DEVICE (SPC)                     not blank = allowed
822  * .  .W - WRITE ONCE READ MULTIPLE DEVICE (SBC)
823  * .  . R - CD DEVICE (MMC)
824  * .  .  S - SCANNER DEVICE (SGC)
825  * .  .  .O - OPTICAL MEMORY DEVICE (SBC)
826  * .  .  . M - MEDIA CHANGER DEVICE (SMC)
827  * .  .  .  C - COMMUNICATION DEVICE (SSC)
828  * .  .  .  .A - STORAGE ARRAY DEVICE (SCC)
829  * .  .  .  . E - ENCLOSURE SERVICES DEVICE (SES)
830  * DTLPWRSOMCAE        ASC   ASCQ  Action  Description
831  * ------------        ----  ----  ------  -----------------------------------*/
832 /* DTLPWRSOMCAE */{SST(0x00, 0x00, SS_NOP,
833                         "No additional sense information") },
834 /*  T    S      */{SST(0x00, 0x01, SS_RDEF,
835                         "Filemark detected") },
836 /*  T    S      */{SST(0x00, 0x02, SS_RDEF,
837                         "End-of-partition/medium detected") },
838 /*  T           */{SST(0x00, 0x03, SS_RDEF,
839                         "Setmark detected") },
840 /*  T    S      */{SST(0x00, 0x04, SS_RDEF,
841                         "Beginning-of-partition/medium detected") },
842 /*  T    S      */{SST(0x00, 0x05, SS_RDEF,
843                         "End-of-data detected") },
844 /* DTLPWRSOMCAE */{SST(0x00, 0x06, SS_RDEF,
845                         "I/O process terminated") },
846 /*      R       */{SST(0x00, 0x11, SS_FATAL|EBUSY,
847                         "Audio play operation in progress") },
848 /*      R       */{SST(0x00, 0x12, SS_NOP,
849                         "Audio play operation paused") },
850 /*      R       */{SST(0x00, 0x13, SS_NOP,
851                         "Audio play operation successfully completed") },
852 /*      R       */{SST(0x00, 0x14, SS_RDEF,
853                         "Audio play operation stopped due to error") },
854 /*      R       */{SST(0x00, 0x15, SS_NOP,
855                         "No current audio status to return") },
856 /* DTLPWRSOMCAE */{SST(0x00, 0x16, SS_FATAL|EBUSY,
857                         "Operation in progress") },
858 /* DTL WRSOM AE */{SST(0x00, 0x17, SS_RDEF,
859                         "Cleaning requested") },
860 /* D   W  O     */{SST(0x01, 0x00, SS_RDEF,
861                         "No index/sector signal") },
862 /* D   WR OM    */{SST(0x02, 0x00, SS_RDEF,
863                         "No seek complete") },
864 /* DTL W SO     */{SST(0x03, 0x00, SS_RDEF,
865                         "Peripheral device write fault") },
866 /*  T           */{SST(0x03, 0x01, SS_RDEF,
867                         "No write current") },
868 /*  T           */{SST(0x03, 0x02, SS_RDEF,
869                         "Excessive write errors") },
870 /* DTLPWRSOMCAE */{SST(0x04, 0x00, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EIO,
871                         "Logical unit not ready, cause not reportable") },
872 /* DTLPWRSOMCAE */{SST(0x04, 0x01, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY,
873                         "Logical unit is in process of becoming ready") },
874 /* DTLPWRSOMCAE */{SST(0x04, 0x02, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
875                         "Logical unit not ready, initializing cmd. required") },
876 /* DTLPWRSOMCAE */{SST(0x04, 0x03, SS_FATAL|ENXIO,
877                         "Logical unit not ready, manual intervention required")},
878 /* DTL    O     */{SST(0x04, 0x04, SS_FATAL|EBUSY,
879                         "Logical unit not ready, format in progress") },
880 /* DT  W  OMCA  */{SST(0x04, 0x05, SS_FATAL|EBUSY,
881                         "Logical unit not ready, rebuild in progress") },
882 /* DT  W  OMCA  */{SST(0x04, 0x06, SS_FATAL|EBUSY,
883                         "Logical unit not ready, recalculation in progress") },
884 /* DTLPWRSOMCAE */{SST(0x04, 0x07, SS_FATAL|EBUSY,
885                         "Logical unit not ready, operation in progress") },
886 /*      R       */{SST(0x04, 0x08, SS_FATAL|EBUSY,
887                         "Logical unit not ready, long write in progress") },
888 /* DTL WRSOMCAE */{SST(0x05, 0x00, SS_RDEF,
889                         "Logical unit does not respond to selection") },
890 /* D   WR OM    */{SST(0x06, 0x00, SS_RDEF,
891                         "No reference position found") },
892 /* DTL WRSOM    */{SST(0x07, 0x00, SS_RDEF,
893                         "Multiple peripheral devices selected") },
894 /* DTL WRSOMCAE */{SST(0x08, 0x00, SS_RDEF,
895                         "Logical unit communication failure") },
896 /* DTL WRSOMCAE */{SST(0x08, 0x01, SS_RDEF,
897                         "Logical unit communication time-out") },
898 /* DTL WRSOMCAE */{SST(0x08, 0x02, SS_RDEF,
899                         "Logical unit communication parity error") },
900 /* DT   R OM    */{SST(0x08, 0x03, SS_RDEF,
901                         "Logical unit communication crc error (ultra-dma/32)")},
902 /* DT  WR O     */{SST(0x09, 0x00, SS_RDEF,
903                         "Track following error") },
904 /*     WR O     */{SST(0x09, 0x01, SS_RDEF,
905                         "Tracking servo failure") },
906 /*     WR O     */{SST(0x09, 0x02, SS_RDEF,
907                         "Focus servo failure") },
908 /*     WR O     */{SST(0x09, 0x03, SS_RDEF,
909                         "Spindle servo failure") },
910 /* DT  WR O     */{SST(0x09, 0x04, SS_RDEF,
911                         "Head select fault") },
912 /* DTLPWRSOMCAE */{SST(0x0A, 0x00, SS_FATAL|ENOSPC,
913                         "Error log overflow") },
914 /* DTLPWRSOMCAE */{SST(0x0B, 0x00, SS_RDEF,
915                         "Warning") },
916 /* DTLPWRSOMCAE */{SST(0x0B, 0x01, SS_RDEF,
917                         "Specified temperature exceeded") },
918 /* DTLPWRSOMCAE */{SST(0x0B, 0x02, SS_RDEF,
919                         "Enclosure degraded") },
920 /*  T   RS      */{SST(0x0C, 0x00, SS_RDEF,
921                         "Write error") },
922 /* D   W  O     */{SST(0x0C, 0x01, SS_NOP|SSQ_PRINT_SENSE,
923                         "Write error - recovered with auto reallocation") },
924 /* D   W  O     */{SST(0x0C, 0x02, SS_RDEF,
925                         "Write error - auto reallocation failed") },
926 /* D   W  O     */{SST(0x0C, 0x03, SS_RDEF,
927                         "Write error - recommend reassignment") },
928 /* DT  W  O     */{SST(0x0C, 0x04, SS_RDEF,
929                         "Compression check miscompare error") },
930 /* DT  W  O     */{SST(0x0C, 0x05, SS_RDEF,
931                         "Data expansion occurred during compression") },
932 /* DT  W  O     */{SST(0x0C, 0x06, SS_RDEF,
933                         "Block not compressible") },
934 /*      R       */{SST(0x0C, 0x07, SS_RDEF,
935                         "Write error - recovery needed") },
936 /*      R       */{SST(0x0C, 0x08, SS_RDEF,
937                         "Write error - recovery failed") },
938 /*      R       */{SST(0x0C, 0x09, SS_RDEF,
939                         "Write error - loss of streaming") },
940 /*      R       */{SST(0x0C, 0x0A, SS_RDEF,
941                         "Write error - padding blocks added") },
942 /* D   W  O     */{SST(0x10, 0x00, SS_RDEF,
943                         "ID CRC or ECC error") },
944 /* DT  WRSO     */{SST(0x11, 0x00, SS_RDEF,
945                         "Unrecovered read error") },
946 /* DT  W SO     */{SST(0x11, 0x01, SS_RDEF,
947                         "Read retries exhausted") },
948 /* DT  W SO     */{SST(0x11, 0x02, SS_RDEF,
949                         "Error too long to correct") },
950 /* DT  W SO     */{SST(0x11, 0x03, SS_RDEF,
951                         "Multiple read errors") },
952 /* D   W  O     */{SST(0x11, 0x04, SS_RDEF,
953                         "Unrecovered read error - auto reallocate failed") },
954 /*     WR O     */{SST(0x11, 0x05, SS_RDEF,
955                         "L-EC uncorrectable error") },
956 /*     WR O     */{SST(0x11, 0x06, SS_RDEF,
957                         "CIRC unrecovered error") },
958 /*     W  O     */{SST(0x11, 0x07, SS_RDEF,
959                         "Data re-synchronization error") },
960 /*  T           */{SST(0x11, 0x08, SS_RDEF,
961                         "Incomplete block read") },
962 /*  T           */{SST(0x11, 0x09, SS_RDEF,
963                         "No gap found") },
964 /* DT     O     */{SST(0x11, 0x0A, SS_RDEF,
965                         "Miscorrected error") },
966 /* D   W  O     */{SST(0x11, 0x0B, SS_RDEF,
967                         "Unrecovered read error - recommend reassignment") },
968 /* D   W  O     */{SST(0x11, 0x0C, SS_RDEF,
969                         "Unrecovered read error - recommend rewrite the data")},
970 /* DT  WR O     */{SST(0x11, 0x0D, SS_RDEF,
971                         "De-compression CRC error") },
972 /* DT  WR O     */{SST(0x11, 0x0E, SS_RDEF,
973                         "Cannot decompress using declared algorithm") },
974 /*      R       */{SST(0x11, 0x0F, SS_RDEF,
975                         "Error reading UPC/EAN number") },
976 /*      R       */{SST(0x11, 0x10, SS_RDEF,
977                         "Error reading ISRC number") },
978 /*      R       */{SST(0x11, 0x11, SS_RDEF,
979                         "Read error - loss of streaming") },
980 /* D   W  O     */{SST(0x12, 0x00, SS_RDEF,
981                         "Address mark not found for id field") },
982 /* D   W  O     */{SST(0x13, 0x00, SS_RDEF,
983                         "Address mark not found for data field") },
984 /* DTL WRSO     */{SST(0x14, 0x00, SS_RDEF,
985                         "Recorded entity not found") },
986 /* DT  WR O     */{SST(0x14, 0x01, SS_RDEF,
987                         "Record not found") },
988 /*  T           */{SST(0x14, 0x02, SS_RDEF,
989                         "Filemark or setmark not found") },
990 /*  T           */{SST(0x14, 0x03, SS_RDEF,
991                         "End-of-data not found") },
992 /*  T           */{SST(0x14, 0x04, SS_RDEF,
993                         "Block sequence error") },
994 /* DT  W  O     */{SST(0x14, 0x05, SS_RDEF,
995                         "Record not found - recommend reassignment") },
996 /* DT  W  O     */{SST(0x14, 0x06, SS_RDEF,
997                         "Record not found - data auto-reallocated") },
998 /* DTL WRSOM    */{SST(0x15, 0x00, SS_RDEF,
999                         "Random positioning error") },
1000 /* DTL WRSOM    */{SST(0x15, 0x01, SS_RDEF,
1001                         "Mechanical positioning error") },
1002 /* DT  WR O     */{SST(0x15, 0x02, SS_RDEF,
1003                         "Positioning error detected by read of medium") },
1004 /* D   W  O     */{SST(0x16, 0x00, SS_RDEF,
1005                         "Data synchronization mark error") },
1006 /* D   W  O     */{SST(0x16, 0x01, SS_RDEF,
1007                         "Data sync error - data rewritten") },
1008 /* D   W  O     */{SST(0x16, 0x02, SS_RDEF,
1009                         "Data sync error - recommend rewrite") },
1010 /* D   W  O     */{SST(0x16, 0x03, SS_NOP|SSQ_PRINT_SENSE,
1011                         "Data sync error - data auto-reallocated") },
1012 /* D   W  O     */{SST(0x16, 0x04, SS_RDEF,
1013                         "Data sync error - recommend reassignment") },
1014 /* DT  WRSO     */{SST(0x17, 0x00, SS_NOP|SSQ_PRINT_SENSE,
1015                         "Recovered data with no error correction applied") },
1016 /* DT  WRSO     */{SST(0x17, 0x01, SS_NOP|SSQ_PRINT_SENSE,
1017                         "Recovered data with retries") },
1018 /* DT  WR O     */{SST(0x17, 0x02, SS_NOP|SSQ_PRINT_SENSE,
1019                         "Recovered data with positive head offset") },
1020 /* DT  WR O     */{SST(0x17, 0x03, SS_NOP|SSQ_PRINT_SENSE,
1021                         "Recovered data with negative head offset") },
1022 /*     WR O     */{SST(0x17, 0x04, SS_NOP|SSQ_PRINT_SENSE,
1023                         "Recovered data with retries and/or CIRC applied") },
1024 /* D   WR O     */{SST(0x17, 0x05, SS_NOP|SSQ_PRINT_SENSE,
1025                         "Recovered data using previous sector id") },
1026 /* D   W  O     */{SST(0x17, 0x06, SS_NOP|SSQ_PRINT_SENSE,
1027                         "Recovered data without ECC - data auto-reallocated") },
1028 /* D   W  O     */{SST(0x17, 0x07, SS_NOP|SSQ_PRINT_SENSE,
1029                         "Recovered data without ECC - recommend reassignment")},
1030 /* D   W  O     */{SST(0x17, 0x08, SS_NOP|SSQ_PRINT_SENSE,
1031                         "Recovered data without ECC - recommend rewrite") },
1032 /* D   W  O     */{SST(0x17, 0x09, SS_NOP|SSQ_PRINT_SENSE,
1033                         "Recovered data without ECC - data rewritten") },
1034 /* D   W  O     */{SST(0x18, 0x00, SS_NOP|SSQ_PRINT_SENSE,
1035                         "Recovered data with error correction applied") },
1036 /* D   WR O     */{SST(0x18, 0x01, SS_NOP|SSQ_PRINT_SENSE,
1037                         "Recovered data with error corr. & retries applied") },
1038 /* D   WR O     */{SST(0x18, 0x02, SS_NOP|SSQ_PRINT_SENSE,
1039                         "Recovered data - data auto-reallocated") },
1040 /*      R       */{SST(0x18, 0x03, SS_NOP|SSQ_PRINT_SENSE,
1041                         "Recovered data with CIRC") },
1042 /*      R       */{SST(0x18, 0x04, SS_NOP|SSQ_PRINT_SENSE,
1043                         "Recovered data with L-EC") },
1044 /* D   WR O     */{SST(0x18, 0x05, SS_NOP|SSQ_PRINT_SENSE,
1045                         "Recovered data - recommend reassignment") },
1046 /* D   WR O     */{SST(0x18, 0x06, SS_NOP|SSQ_PRINT_SENSE,
1047                         "Recovered data - recommend rewrite") },
1048 /* D   W  O     */{SST(0x18, 0x07, SS_NOP|SSQ_PRINT_SENSE,
1049                         "Recovered data with ECC - data rewritten") },
1050 /* D      O     */{SST(0x19, 0x00, SS_RDEF,
1051                         "Defect list error") },
1052 /* D      O     */{SST(0x19, 0x01, SS_RDEF,
1053                         "Defect list not available") },
1054 /* D      O     */{SST(0x19, 0x02, SS_RDEF,
1055                         "Defect list error in primary list") },
1056 /* D      O     */{SST(0x19, 0x03, SS_RDEF,
1057                         "Defect list error in grown list") },
1058 /* DTLPWRSOMCAE */{SST(0x1A, 0x00, SS_RDEF,
1059                         "Parameter list length error") },
1060 /* DTLPWRSOMCAE */{SST(0x1B, 0x00, SS_RDEF,
1061                         "Synchronous data transfer error") },
1062 /* D      O     */{SST(0x1C, 0x00, SS_RDEF,
1063                         "Defect list not found") },
1064 /* D      O     */{SST(0x1C, 0x01, SS_RDEF,
1065                         "Primary defect list not found") },
1066 /* D      O     */{SST(0x1C, 0x02, SS_RDEF,
1067                         "Grown defect list not found") },
1068 /* D   W  O     */{SST(0x1D, 0x00, SS_FATAL,
1069                         "Miscompare during verify operation" )},
1070 /* D   W  O     */{SST(0x1E, 0x00, SS_NOP|SSQ_PRINT_SENSE,
1071                         "Recovered id with ecc correction") },
1072 /* D      O     */{SST(0x1F, 0x00, SS_RDEF,
1073                         "Partial defect list transfer") },
1074 /* DTLPWRSOMCAE */{SST(0x20, 0x00, SS_FATAL|EINVAL,
1075                         "Invalid command operation code") },
1076 /* DT  WR OM    */{SST(0x21, 0x00, SS_FATAL|EINVAL,
1077                         "Logical block address out of range" )},
1078 /* DT  WR OM    */{SST(0x21, 0x01, SS_FATAL|EINVAL,
1079                         "Invalid element address") },
1080 /* D            */{SST(0x22, 0x00, SS_FATAL|EINVAL,
1081                         "Illegal function") }, /* Deprecated. Use 20 00, 24 00, or 26 00 instead */
1082 /* DTLPWRSOMCAE */{SST(0x24, 0x00, SS_FATAL|EINVAL,
1083                         "Invalid field in CDB") },
1084 /* DTLPWRSOMCAE */{SST(0x25, 0x00, SS_FATAL|ENXIO,
1085                         "Logical unit not supported") },
1086 /* DTLPWRSOMCAE */{SST(0x26, 0x00, SS_FATAL|EINVAL,
1087                         "Invalid field in parameter list") },
1088 /* DTLPWRSOMCAE */{SST(0x26, 0x01, SS_FATAL|EINVAL,
1089                         "Parameter not supported") },
1090 /* DTLPWRSOMCAE */{SST(0x26, 0x02, SS_FATAL|EINVAL,
1091                         "Parameter value invalid") },
1092 /* DTLPWRSOMCAE */{SST(0x26, 0x03, SS_FATAL|EINVAL,
1093                         "Threshold parameters not supported") },
1094 /* DTLPWRSOMCAE */{SST(0x26, 0x04, SS_FATAL|EINVAL,
1095                         "Invalid release of active persistent reservation") },
1096 /* DT  W  O     */{SST(0x27, 0x00, SS_FATAL|EACCES,
1097                         "Write protected") },
1098 /* DT  W  O     */{SST(0x27, 0x01, SS_FATAL|EACCES,
1099                         "Hardware write protected") },
1100 /* DT  W  O     */{SST(0x27, 0x02, SS_FATAL|EACCES,
1101                         "Logical unit software write protected") },
1102 /*  T           */{SST(0x27, 0x03, SS_FATAL|EACCES,
1103                         "Associated write protect") },
1104 /*  T           */{SST(0x27, 0x04, SS_FATAL|EACCES,
1105                         "Persistent write protect") },
1106 /*  T           */{SST(0x27, 0x05, SS_FATAL|EACCES,
1107                         "Permanent write protect") },
1108 /* DTLPWRSOMCAE */{SST(0x28, 0x00, SS_FATAL|ENXIO,
1109                         "Not ready to ready change, medium may have changed") },
1110 /* DTLPWRSOMCAE */{SST(0x28, 0x01, SS_FATAL|ENXIO,
1111                         "Import or export element accessed") },
1112 /*
1113  * XXX JGibbs - All of these should use the same errno, but I don't think
1114  * ENXIO is the correct choice.  Should we borrow from the networking
1115  * errnos?  ECONNRESET anyone?
1116  */
1117 /* DTLPWRSOMCAE */{SST(0x29, 0x00, SS_FATAL|ENXIO,
1118                         "Power on, reset, or bus device reset occurred") },
1119 /* DTLPWRSOMCAE */{SST(0x29, 0x01, SS_RDEF,
1120                         "Power on occurred") },
1121 /* DTLPWRSOMCAE */{SST(0x29, 0x02, SS_RDEF,
1122                         "Scsi bus reset occurred") },
1123 /* DTLPWRSOMCAE */{SST(0x29, 0x03, SS_RDEF,
1124                         "Bus device reset function occurred") },
1125 /* DTLPWRSOMCAE */{SST(0x29, 0x04, SS_RDEF,
1126                         "Device internal reset") },
1127 /* DTLPWRSOMCAE */{SST(0x29, 0x05, SS_RDEF,
1128                         "Transceiver mode changed to single-ended") },
1129 /* DTLPWRSOMCAE */{SST(0x29, 0x06, SS_RDEF,
1130                         "Transceiver mode changed to LVD") },
1131 /* DTL WRSOMCAE */{SST(0x2A, 0x00, SS_RDEF,
1132                         "Parameters changed") },
1133 /* DTL WRSOMCAE */{SST(0x2A, 0x01, SS_RDEF,
1134                         "Mode parameters changed") },
1135 /* DTL WRSOMCAE */{SST(0x2A, 0x02, SS_RDEF,
1136                         "Log parameters changed") },
1137 /* DTLPWRSOMCAE */{SST(0x2A, 0x03, SS_RDEF,
1138                         "Reservations preempted") },
1139 /* DTLPWRSO C   */{SST(0x2B, 0x00, SS_RDEF,
1140                         "Copy cannot execute since host cannot disconnect") },
1141 /* DTLPWRSOMCAE */{SST(0x2C, 0x00, SS_RDEF,
1142                         "Command sequence error") },
1143 /*       S      */{SST(0x2C, 0x01, SS_RDEF,
1144                         "Too many windows specified") },
1145 /*       S      */{SST(0x2C, 0x02, SS_RDEF,
1146                         "Invalid combination of windows specified") },
1147 /*      R       */{SST(0x2C, 0x03, SS_RDEF,
1148                         "Current program area is not empty") },
1149 /*      R       */{SST(0x2C, 0x04, SS_RDEF,
1150                         "Current program area is empty") },
1151 /*  T           */{SST(0x2D, 0x00, SS_RDEF,
1152                         "Overwrite error on update in place") },
1153 /* DTLPWRSOMCAE */{SST(0x2F, 0x00, SS_RDEF,
1154                         "Commands cleared by another initiator") },
1155 /* DT  WR OM    */{SST(0x30, 0x00, SS_RDEF,
1156                         "Incompatible medium installed") },
1157 /* DT  WR O     */{SST(0x30, 0x01, SS_RDEF,
1158                         "Cannot read medium - unknown format") },
1159 /* DT  WR O     */{SST(0x30, 0x02, SS_RDEF,
1160                         "Cannot read medium - incompatible format") },
1161 /* DT           */{SST(0x30, 0x03, SS_RDEF,
1162                         "Cleaning cartridge installed") },
1163 /* DT  WR O     */{SST(0x30, 0x04, SS_RDEF,
1164                         "Cannot write medium - unknown format") },
1165 /* DT  WR O     */{SST(0x30, 0x05, SS_RDEF,
1166                         "Cannot write medium - incompatible format") },
1167 /* DT  W  O     */{SST(0x30, 0x06, SS_RDEF,
1168                         "Cannot format medium - incompatible medium") },
1169 /* DTL WRSOM AE */{SST(0x30, 0x07, SS_RDEF,
1170                         "Cleaning failure") },
1171 /*      R       */{SST(0x30, 0x08, SS_RDEF,
1172                         "Cannot write - application code mismatch") },
1173 /*      R       */{SST(0x30, 0x09, SS_RDEF,
1174                         "Current session not fixated for append") },
1175 /* DT  WR O     */{SST(0x31, 0x00, SS_RDEF,
1176                         "Medium format corrupted") },
1177 /* D L  R O     */{SST(0x31, 0x01, SS_RDEF,
1178                         "Format command failed") },
1179 /* D   W  O     */{SST(0x32, 0x00, SS_RDEF,
1180                         "No defect spare location available") },
1181 /* D   W  O     */{SST(0x32, 0x01, SS_RDEF,
1182                         "Defect list update failure") },
1183 /*  T           */{SST(0x33, 0x00, SS_RDEF,
1184                         "Tape length error") },
1185 /* DTLPWRSOMCAE */{SST(0x34, 0x00, SS_RDEF,
1186                         "Enclosure failure") },
1187 /* DTLPWRSOMCAE */{SST(0x35, 0x00, SS_RDEF,
1188                         "Enclosure services failure") },
1189 /* DTLPWRSOMCAE */{SST(0x35, 0x01, SS_RDEF,
1190                         "Unsupported enclosure function") },
1191 /* DTLPWRSOMCAE */{SST(0x35, 0x02, SS_RDEF,
1192                         "Enclosure services unavailable") },
1193 /* DTLPWRSOMCAE */{SST(0x35, 0x03, SS_RDEF,
1194                         "Enclosure services transfer failure") },
1195 /* DTLPWRSOMCAE */{SST(0x35, 0x04, SS_RDEF,
1196                         "Enclosure services transfer refused") },
1197 /*   L          */{SST(0x36, 0x00, SS_RDEF,
1198                         "Ribbon, ink, or toner failure") },
1199 /* DTL WRSOMCAE */{SST(0x37, 0x00, SS_RDEF,
1200                         "Rounded parameter") },
1201 /* DTL WRSOMCAE */{SST(0x39, 0x00, SS_RDEF,
1202                         "Saving parameters not supported") },
1203 /* DTL WRSOM    */{SST(0x3A, 0x00, SS_FATAL|ENXIO,
1204                         "Medium not present") },
1205 /* DT  WR OM    */{SST(0x3A, 0x01, SS_FATAL|ENXIO,
1206                         "Medium not present - tray closed") },
1207 /* DT  WR OM    */{SST(0x3A, 0x02, SS_FATAL|ENXIO,
1208                         "Medium not present - tray open") },
1209 /*  TL          */{SST(0x3B, 0x00, SS_RDEF,
1210                         "Sequential positioning error") },
1211 /*  T           */{SST(0x3B, 0x01, SS_RDEF,
1212                         "Tape position error at beginning-of-medium") },
1213 /*  T           */{SST(0x3B, 0x02, SS_RDEF,
1214                         "Tape position error at end-of-medium") },
1215 /*   L          */{SST(0x3B, 0x03, SS_RDEF,
1216                         "Tape or electronic vertical forms unit not ready") },
1217 /*   L          */{SST(0x3B, 0x04, SS_RDEF,
1218                         "Slew failure") },
1219 /*   L          */{SST(0x3B, 0x05, SS_RDEF,
1220                         "Paper jam") },
1221 /*   L          */{SST(0x3B, 0x06, SS_RDEF,
1222                         "Failed to sense top-of-form") },
1223 /*   L          */{SST(0x3B, 0x07, SS_RDEF,
1224                         "Failed to sense bottom-of-form") },
1225 /*  T           */{SST(0x3B, 0x08, SS_RDEF,
1226                         "Reposition error") },
1227 /*       S      */{SST(0x3B, 0x09, SS_RDEF,
1228                         "Read past end of medium") },
1229 /*       S      */{SST(0x3B, 0x0A, SS_RDEF,
1230                         "Read past beginning of medium") },
1231 /*       S      */{SST(0x3B, 0x0B, SS_RDEF,
1232                         "Position past end of medium") },
1233 /*  T    S      */{SST(0x3B, 0x0C, SS_RDEF,
1234                         "Position past beginning of medium") },
1235 /* DT  WR OM    */{SST(0x3B, 0x0D, SS_FATAL|ENOSPC,
1236                         "Medium destination element full") },
1237 /* DT  WR OM    */{SST(0x3B, 0x0E, SS_RDEF,
1238                         "Medium source element empty") },
1239 /*      R       */{SST(0x3B, 0x0F, SS_RDEF,
1240                         "End of medium reached") },
1241 /* DT  WR OM    */{SST(0x3B, 0x11, SS_RDEF,
1242                         "Medium magazine not accessible") },
1243 /* DT  WR OM    */{SST(0x3B, 0x12, SS_RDEF,
1244                         "Medium magazine removed") },
1245 /* DT  WR OM    */{SST(0x3B, 0x13, SS_RDEF,
1246                         "Medium magazine inserted") },
1247 /* DT  WR OM    */{SST(0x3B, 0x14, SS_RDEF,
1248                         "Medium magazine locked") },
1249 /* DT  WR OM    */{SST(0x3B, 0x15, SS_RDEF,
1250                         "Medium magazine unlocked") },
1251 /* DTLPWRSOMCAE */{SST(0x3D, 0x00, SS_RDEF,
1252                         "Invalid bits in identify message") },
1253 /* DTLPWRSOMCAE */{SST(0x3E, 0x00, SS_RDEF,
1254                         "Logical unit has not self-configured yet") },
1255 /* DTLPWRSOMCAE */{SST(0x3E, 0x01, SS_RDEF,
1256                         "Logical unit failure") },
1257 /* DTLPWRSOMCAE */{SST(0x3E, 0x02, SS_RDEF,
1258                         "Timeout on logical unit") },
1259 /* DTLPWRSOMCAE */{SST(0x3F, 0x00, SS_RDEF,
1260                         "Target operating conditions have changed") },
1261 /* DTLPWRSOMCAE */{SST(0x3F, 0x01, SS_RDEF,
1262                         "Microcode has been changed") },
1263 /* DTLPWRSOMC   */{SST(0x3F, 0x02, SS_RDEF,
1264                         "Changed operating definition") },
1265 /* DTLPWRSOMCAE */{SST(0x3F, 0x03, SS_RDEF,
1266                         "Inquiry data has changed") },
1267 /* DT  WR OMCAE */{SST(0x3F, 0x04, SS_RDEF,
1268                         "Component device attached") },
1269 /* DT  WR OMCAE */{SST(0x3F, 0x05, SS_RDEF,
1270                         "Device identifier changed") },
1271 /* DT  WR OMCAE */{SST(0x3F, 0x06, SS_RDEF,
1272                         "Redundancy group created or modified") },
1273 /* DT  WR OMCAE */{SST(0x3F, 0x07, SS_RDEF,
1274                         "Redundancy group deleted") },
1275 /* DT  WR OMCAE */{SST(0x3F, 0x08, SS_RDEF,
1276                         "Spare created or modified") },
1277 /* DT  WR OMCAE */{SST(0x3F, 0x09, SS_RDEF,
1278                         "Spare deleted") },
1279 /* DT  WR OMCAE */{SST(0x3F, 0x0A, SS_RDEF,
1280                         "Volume set created or modified") },
1281 /* DT  WR OMCAE */{SST(0x3F, 0x0B, SS_RDEF,
1282                         "Volume set deleted") },
1283 /* DT  WR OMCAE */{SST(0x3F, 0x0C, SS_RDEF,
1284                         "Volume set deassigned") },
1285 /* DT  WR OMCAE */{SST(0x3F, 0x0D, SS_RDEF,
1286                         "Volume set reassigned") },
1287 /* D            */{SST(0x40, 0x00, SS_RDEF,
1288                         "Ram failure") }, /* deprecated - use 40 NN instead */
1289 /* DTLPWRSOMCAE */{SST(0x40, 0x80, SS_RDEF,
1290                         "Diagnostic failure: ASCQ = Component ID") },
1291 /* DTLPWRSOMCAE */{SST(0x40, 0xFF, SS_RDEF|SSQ_RANGE,
1292                         NULL) },/* Range 0x80->0xFF */
1293 /* D            */{SST(0x41, 0x00, SS_RDEF,
1294                         "Data path failure") }, /* deprecated - use 40 NN instead */
1295 /* D            */{SST(0x42, 0x00, SS_RDEF,
1296                         "Power-on or self-test failure") }, /* deprecated - use 40 NN instead */
1297 /* DTLPWRSOMCAE */{SST(0x43, 0x00, SS_RDEF,
1298                         "Message error") },
1299 /* DTLPWRSOMCAE */{SST(0x44, 0x00, SS_RDEF,
1300                         "Internal target failure") },
1301 /* DTLPWRSOMCAE */{SST(0x45, 0x00, SS_RDEF,
1302                         "Select or reselect failure") },
1303 /* DTLPWRSOMC   */{SST(0x46, 0x00, SS_RDEF,
1304                         "Unsuccessful soft reset") },
1305 /* DTLPWRSOMCAE */{SST(0x47, 0x00, SS_RDEF,
1306                         "SCSI parity error") },
1307 /* DTLPWRSOMCAE */{SST(0x48, 0x00, SS_RDEF,
1308                         "Initiator detected error message received") },
1309 /* DTLPWRSOMCAE */{SST(0x49, 0x00, SS_RDEF,
1310                         "Invalid message error") },
1311 /* DTLPWRSOMCAE */{SST(0x4A, 0x00, SS_RDEF,
1312                         "Command phase error") },
1313 /* DTLPWRSOMCAE */{SST(0x4B, 0x00, SS_RDEF,
1314                         "Data phase error") },
1315 /* DTLPWRSOMCAE */{SST(0x4C, 0x00, SS_RDEF,
1316                         "Logical unit failed self-configuration") },
1317 /* DTLPWRSOMCAE */{SST(0x4D, 0x00, SS_RDEF,
1318                         "Tagged overlapped commands: ASCQ = Queue tag ID") },
1319 /* DTLPWRSOMCAE */{SST(0x4D, 0xFF, SS_RDEF|SSQ_RANGE,
1320                         NULL)}, /* Range 0x00->0xFF */
1321 /* DTLPWRSOMCAE */{SST(0x4E, 0x00, SS_RDEF,
1322                         "Overlapped commands attempted") },
1323 /*  T           */{SST(0x50, 0x00, SS_RDEF,
1324                         "Write append error") },
1325 /*  T           */{SST(0x50, 0x01, SS_RDEF,
1326                         "Write append position error") },
1327 /*  T           */{SST(0x50, 0x02, SS_RDEF,
1328                         "Position error related to timing") },
1329 /*  T     O     */{SST(0x51, 0x00, SS_RDEF,
1330                         "Erase failure") },
1331 /*  T           */{SST(0x52, 0x00, SS_RDEF,
1332                         "Cartridge fault") },
1333 /* DTL WRSOM    */{SST(0x53, 0x00, SS_RDEF,
1334                         "Media load or eject failed") },
1335 /*  T           */{SST(0x53, 0x01, SS_RDEF,
1336                         "Unload tape failure") },
1337 /* DT  WR OM    */{SST(0x53, 0x02, SS_RDEF,
1338                         "Medium removal prevented") },
1339 /*    P         */{SST(0x54, 0x00, SS_RDEF,
1340                         "Scsi to host system interface failure") },
1341 /*    P         */{SST(0x55, 0x00, SS_RDEF,
1342                         "System resource failure") },
1343 /* D      O     */{SST(0x55, 0x01, SS_FATAL|ENOSPC,
1344                         "System buffer full") },
1345 /*      R       */{SST(0x57, 0x00, SS_RDEF,
1346                         "Unable to recover table-of-contents") },
1347 /*        O     */{SST(0x58, 0x00, SS_RDEF,
1348                         "Generation does not exist") },
1349 /*        O     */{SST(0x59, 0x00, SS_RDEF,
1350                         "Updated block read") },
1351 /* DTLPWRSOM    */{SST(0x5A, 0x00, SS_RDEF,
1352                         "Operator request or state change input") },
1353 /* DT  WR OM    */{SST(0x5A, 0x01, SS_RDEF,
1354                         "Operator medium removal request") },
1355 /* DT  W  O     */{SST(0x5A, 0x02, SS_RDEF,
1356                         "Operator selected write protect") },
1357 /* DT  W  O     */{SST(0x5A, 0x03, SS_RDEF,
1358                         "Operator selected write permit") },
1359 /* DTLPWRSOM    */{SST(0x5B, 0x00, SS_RDEF,
1360                         "Log exception") },
1361 /* DTLPWRSOM    */{SST(0x5B, 0x01, SS_RDEF,
1362                         "Threshold condition met") },
1363 /* DTLPWRSOM    */{SST(0x5B, 0x02, SS_RDEF,
1364                         "Log counter at maximum") },
1365 /* DTLPWRSOM    */{SST(0x5B, 0x03, SS_RDEF,
1366                         "Log list codes exhausted") },
1367 /* D      O     */{SST(0x5C, 0x00, SS_RDEF,
1368                         "RPL status change") },
1369 /* D      O     */{SST(0x5C, 0x01, SS_NOP|SSQ_PRINT_SENSE,
1370                         "Spindles synchronized") },
1371 /* D      O     */{SST(0x5C, 0x02, SS_RDEF,
1372                         "Spindles not synchronized") },
1373 /* DTLPWRSOMCAE */{SST(0x5D, 0x00, SS_RDEF,
1374                         "Failure prediction threshold exceeded") },
1375 /* DTLPWRSOMCAE */{SST(0x5D, 0xFF, SS_RDEF,
1376                         "Failure prediction threshold exceeded (false)") },
1377 /* DTLPWRSO CA  */{SST(0x5E, 0x00, SS_RDEF,
1378                         "Low power condition on") },
1379 /* DTLPWRSO CA  */{SST(0x5E, 0x01, SS_RDEF,
1380                         "Idle condition activated by timer") },
1381 /* DTLPWRSO CA  */{SST(0x5E, 0x02, SS_RDEF,
1382                         "Standby condition activated by timer") },
1383 /* DTLPWRSO CA  */{SST(0x5E, 0x03, SS_RDEF,
1384                         "Idle condition activated by command") },
1385 /* DTLPWRSO CA  */{SST(0x5E, 0x04, SS_RDEF,
1386                         "Standby condition activated by command") },
1387 /*       S      */{SST(0x60, 0x00, SS_RDEF,
1388                         "Lamp failure") },
1389 /*       S      */{SST(0x61, 0x00, SS_RDEF,
1390                         "Video acquisition error") },
1391 /*       S      */{SST(0x61, 0x01, SS_RDEF,
1392                         "Unable to acquire video") },
1393 /*       S      */{SST(0x61, 0x02, SS_RDEF,
1394                         "Out of focus") },
1395 /*       S      */{SST(0x62, 0x00, SS_RDEF,
1396                         "Scan head positioning error") },
1397 /*      R       */{SST(0x63, 0x00, SS_RDEF,
1398                         "End of user area encountered on this track") },
1399 /*      R       */{SST(0x63, 0x01, SS_FATAL|ENOSPC,
1400                         "Packet does not fit in available space") },
1401 /*      R       */{SST(0x64, 0x00, SS_RDEF,
1402                         "Illegal mode for this track") },
1403 /*      R       */{SST(0x64, 0x01, SS_RDEF,
1404                         "Invalid packet size") },
1405 /* DTLPWRSOMCAE */{SST(0x65, 0x00, SS_RDEF,
1406                         "Voltage fault") },
1407 /*       S      */{SST(0x66, 0x00, SS_RDEF,
1408                         "Automatic document feeder cover up") },
1409 /*       S      */{SST(0x66, 0x01, SS_RDEF,
1410                         "Automatic document feeder lift up") },
1411 /*       S      */{SST(0x66, 0x02, SS_RDEF,
1412                         "Document jam in automatic document feeder") },
1413 /*       S      */{SST(0x66, 0x03, SS_RDEF,
1414                         "Document miss feed automatic in document feeder") },
1415 /*           A  */{SST(0x67, 0x00, SS_RDEF,
1416                         "Configuration failure") },
1417 /*           A  */{SST(0x67, 0x01, SS_RDEF,
1418                         "Configuration of incapable logical units failed") },
1419 /*           A  */{SST(0x67, 0x02, SS_RDEF,
1420                         "Add logical unit failed") },
1421 /*           A  */{SST(0x67, 0x03, SS_RDEF,
1422                         "Modification of logical unit failed") },
1423 /*           A  */{SST(0x67, 0x04, SS_RDEF,
1424                         "Exchange of logical unit failed") },
1425 /*           A  */{SST(0x67, 0x05, SS_RDEF,
1426                         "Remove of logical unit failed") },
1427 /*           A  */{SST(0x67, 0x06, SS_RDEF,
1428                         "Attachment of logical unit failed") },
1429 /*           A  */{SST(0x67, 0x07, SS_RDEF,
1430                         "Creation of logical unit failed") },
1431 /*           A  */{SST(0x68, 0x00, SS_RDEF,
1432                         "Logical unit not configured") },
1433 /*           A  */{SST(0x69, 0x00, SS_RDEF,
1434                         "Data loss on logical unit") },
1435 /*           A  */{SST(0x69, 0x01, SS_RDEF,
1436                         "Multiple logical unit failures") },
1437 /*           A  */{SST(0x69, 0x02, SS_RDEF,
1438                         "Parity/data mismatch") },
1439 /*           A  */{SST(0x6A, 0x00, SS_RDEF,
1440                         "Informational, refer to log") },
1441 /*           A  */{SST(0x6B, 0x00, SS_RDEF,
1442                         "State change has occurred") },
1443 /*           A  */{SST(0x6B, 0x01, SS_RDEF,
1444                         "Redundancy level got better") },
1445 /*           A  */{SST(0x6B, 0x02, SS_RDEF,
1446                         "Redundancy level got worse") },
1447 /*           A  */{SST(0x6C, 0x00, SS_RDEF,
1448                         "Rebuild failure occurred") },
1449 /*           A  */{SST(0x6D, 0x00, SS_RDEF,
1450                         "Recalculate failure occurred") },
1451 /*           A  */{SST(0x6E, 0x00, SS_RDEF,
1452                         "Command to logical unit failed") },
1453 /*  T           */{SST(0x70, 0x00, SS_RDEF,
1454                         "Decompression exception short: ASCQ = Algorithm ID") },
1455 /*  T           */{SST(0x70, 0xFF, SS_RDEF|SSQ_RANGE,
1456                         NULL) }, /* Range 0x00 -> 0xFF */
1457 /*  T           */{SST(0x71, 0x00, SS_RDEF,
1458                         "Decompression exception long: ASCQ = Algorithm ID") },
1459 /*  T           */{SST(0x71, 0xFF, SS_RDEF|SSQ_RANGE,
1460                         NULL) }, /* Range 0x00 -> 0xFF */       
1461 /*      R       */{SST(0x72, 0x00, SS_RDEF,
1462                         "Session fixation error") },
1463 /*      R       */{SST(0x72, 0x01, SS_RDEF,
1464                         "Session fixation error writing lead-in") },
1465 /*      R       */{SST(0x72, 0x02, SS_RDEF,
1466                         "Session fixation error writing lead-out") },
1467 /*      R       */{SST(0x72, 0x03, SS_RDEF,
1468                         "Session fixation error - incomplete track in session") },
1469 /*      R       */{SST(0x72, 0x04, SS_RDEF,
1470                         "Empty or partially written reserved track") },
1471 /*      R       */{SST(0x73, 0x00, SS_RDEF,
1472                         "CD control error") },
1473 /*      R       */{SST(0x73, 0x01, SS_RDEF,
1474                         "Power calibration area almost full") },
1475 /*      R       */{SST(0x73, 0x02, SS_FATAL|ENOSPC,
1476                         "Power calibration area is full") },
1477 /*      R       */{SST(0x73, 0x03, SS_RDEF,
1478                         "Power calibration area error") },
1479 /*      R       */{SST(0x73, 0x04, SS_RDEF,
1480                         "Program memory area update failure") },
1481 /*      R       */{SST(0x73, 0x05, SS_RDEF,
1482                         "program memory area is full") }
1483 };
1484
1485 const int asc_table_size = sizeof(asc_table)/sizeof(asc_table[0]);
1486
1487 struct asc_key
1488 {
1489         int asc;
1490         int ascq;
1491 };
1492
1493 static int
1494 ascentrycomp(const void *key, const void *member)
1495 {
1496         int asc;
1497         int ascq;
1498         const struct asc_table_entry *table_entry;
1499
1500         asc = ((const struct asc_key *)key)->asc;
1501         ascq = ((const struct asc_key *)key)->ascq;
1502         table_entry = (const struct asc_table_entry *)member;
1503
1504         if (asc >= table_entry->asc) {
1505
1506                 if (asc > table_entry->asc)
1507                         return (1);
1508
1509                 if (ascq <= table_entry->ascq) {
1510                         /* Check for ranges */
1511                         if (ascq == table_entry->ascq
1512                          || ((table_entry->action & SSQ_RANGE) != 0
1513                            && ascq >= (table_entry - 1)->ascq))
1514                                 return (0);
1515                         return (-1);
1516                 }
1517                 return (1);
1518         }
1519         return (-1);
1520 }
1521
1522 static int
1523 senseentrycomp(const void *key, const void *member)
1524 {
1525         int sense_key;
1526         const struct sense_key_table_entry *table_entry;
1527
1528         sense_key = *((const int *)key);
1529         table_entry = (const struct sense_key_table_entry *)member;
1530
1531         if (sense_key >= table_entry->sense_key) {
1532                 if (sense_key == table_entry->sense_key)
1533                         return (0);
1534                 return (1);
1535         }
1536         return (-1);
1537 }
1538
1539 static void
1540 fetchtableentries(int sense_key, int asc, int ascq,
1541                   struct scsi_inquiry_data *inq_data,
1542                   const struct sense_key_table_entry **sense_entry,
1543                   const struct asc_table_entry **asc_entry)
1544 {
1545         caddr_t match;
1546         const struct asc_table_entry *asc_tables[2];
1547         const struct sense_key_table_entry *sense_tables[2];
1548         struct asc_key asc_ascq;
1549         size_t asc_tables_size[2];
1550         size_t sense_tables_size[2];
1551         int num_asc_tables;
1552         int num_sense_tables;
1553         int i;
1554
1555         /* Default to failure */
1556         *sense_entry = NULL;
1557         *asc_entry = NULL;
1558         match = NULL;
1559         if (inq_data != NULL)
1560                 match = cam_quirkmatch((caddr_t)inq_data,
1561                                        (caddr_t)sense_quirk_table,
1562                                        sense_quirk_table_size,
1563                                        sizeof(*sense_quirk_table),
1564                                        scsi_inquiry_match);
1565
1566         if (match != NULL) {
1567                 struct scsi_sense_quirk_entry *quirk;
1568
1569                 quirk = (struct scsi_sense_quirk_entry *)match;
1570                 asc_tables[0] = quirk->asc_info;
1571                 asc_tables_size[0] = quirk->num_ascs;
1572                 asc_tables[1] = asc_table;
1573                 asc_tables_size[1] = asc_table_size;
1574                 num_asc_tables = 2;
1575                 sense_tables[0] = quirk->sense_key_info;
1576                 sense_tables_size[0] = quirk->num_sense_keys;
1577                 sense_tables[1] = sense_key_table;
1578                 sense_tables_size[1] = sense_key_table_size;
1579                 num_sense_tables = 2;
1580         } else {
1581                 asc_tables[0] = asc_table;
1582                 asc_tables_size[0] = asc_table_size;
1583                 num_asc_tables = 1;
1584                 sense_tables[0] = sense_key_table;
1585                 sense_tables_size[0] = sense_key_table_size;
1586                 num_sense_tables = 1;
1587         }
1588
1589         asc_ascq.asc = asc;
1590         asc_ascq.ascq = ascq;
1591         for (i = 0; i < num_asc_tables; i++) {
1592                 void *found_entry;
1593
1594                 found_entry = bsearch(&asc_ascq, asc_tables[i],
1595                                       asc_tables_size[i],
1596                                       sizeof(**asc_tables),
1597                                       ascentrycomp);
1598
1599                 if (found_entry) {
1600                         *asc_entry = (struct asc_table_entry *)found_entry;
1601                         break;
1602                 }
1603         }
1604
1605         for (i = 0; i < num_sense_tables; i++) {
1606                 void *found_entry;
1607
1608                 found_entry = bsearch(&sense_key, sense_tables[i],
1609                                       sense_tables_size[i],
1610                                       sizeof(**sense_tables),
1611                                       senseentrycomp);
1612
1613                 if (found_entry) {
1614                         *sense_entry =
1615                             (struct sense_key_table_entry *)found_entry;
1616                         break;
1617                 }
1618         }
1619 }
1620
1621 void
1622 scsi_sense_desc(int sense_key, int asc, int ascq,
1623                 struct scsi_inquiry_data *inq_data,
1624                 const char **sense_key_desc, const char **asc_desc)
1625 {
1626         const struct asc_table_entry *asc_entry;
1627         const struct sense_key_table_entry *sense_entry;
1628
1629         fetchtableentries(sense_key, asc, ascq,
1630                           inq_data,
1631                           &sense_entry,
1632                           &asc_entry);
1633
1634         *sense_key_desc = sense_entry->desc;
1635
1636         if (asc_entry != NULL)
1637                 *asc_desc = asc_entry->desc;
1638         else if (asc >= 0x80 && asc <= 0xff)
1639                 *asc_desc = "Vendor Specific ASC";
1640         else if (ascq >= 0x80 && ascq <= 0xff)
1641                 *asc_desc = "Vendor Specific ASCQ";
1642         else
1643                 *asc_desc = "Reserved ASC/ASCQ pair";
1644 }
1645
1646 /*
1647  * Given sense and device type information, return the appropriate action.
1648  * If we do not understand the specific error as identified by the ASC/ASCQ
1649  * pair, fall back on the more generic actions derived from the sense key.
1650  */
1651 scsi_sense_action
1652 scsi_error_action(struct ccb_scsiio *csio, struct scsi_inquiry_data *inq_data,
1653                   u_int32_t sense_flags)
1654 {
1655         const struct asc_table_entry *asc_entry;
1656         const struct sense_key_table_entry *sense_entry;
1657         int error_code, sense_key, asc, ascq;
1658         scsi_sense_action action;
1659
1660         scsi_extract_sense(&csio->sense_data, &error_code,
1661                            &sense_key, &asc, &ascq);
1662
1663         if (error_code == SSD_DEFERRED_ERROR) {
1664                 /*
1665                  * XXX dufault@FreeBSD.org
1666                  * This error doesn't relate to the command associated
1667                  * with this request sense.  A deferred error is an error
1668                  * for a command that has already returned GOOD status
1669                  * (see SCSI2 8.2.14.2).
1670                  *
1671                  * By my reading of that section, it looks like the current
1672                  * command has been cancelled, we should now clean things up
1673                  * (hopefully recovering any lost data) and then retry the
1674                  * current command.  There are two easy choices, both wrong:
1675                  *
1676                  * 1. Drop through (like we had been doing), thus treating
1677                  *    this as if the error were for the current command and
1678                  *    return and stop the current command.
1679                  *
1680                  * 2. Issue a retry (like I made it do) thus hopefully
1681                  *    recovering the current transfer, and ignoring the
1682                  *    fact that we've dropped a command.
1683                  *
1684                  * These should probably be handled in a device specific
1685                  * sense handler or punted back up to a user mode daemon
1686                  */
1687                 action = SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE;
1688         } else {
1689                 fetchtableentries(sense_key, asc, ascq,
1690                                   inq_data,
1691                                   &sense_entry,
1692                                   &asc_entry);
1693
1694                 /*
1695                  * Override the 'No additional Sense' entry (0,0)
1696                  * with the error action of the sense key.
1697                  */
1698                 if (asc_entry != NULL
1699                  && (asc != 0 || ascq != 0))
1700                         action = asc_entry->action;
1701                 else
1702                         action = sense_entry->action;
1703
1704                 if (sense_key == SSD_KEY_RECOVERED_ERROR) {
1705                         /*
1706                          * The action succeeded but the device wants
1707                          * the user to know that some recovery action
1708                          * was required.
1709                          */
1710                         action &= ~(SS_MASK|SSQ_MASK|SS_ERRMASK);
1711                         action |= SS_NOP|SSQ_PRINT_SENSE;
1712                 } else if (sense_key == SSD_KEY_ILLEGAL_REQUEST) {
1713                         if ((sense_flags & SF_QUIET_IR) != 0)
1714                                 action &= ~SSQ_PRINT_SENSE;
1715                 } else if (sense_key == SSD_KEY_UNIT_ATTENTION) {
1716                         if ((sense_flags & SF_RETRY_UA) != 0
1717                          && (action & SS_MASK) == SS_FAIL) {
1718                                 action &= ~(SS_MASK|SSQ_MASK);
1719                                 action |= SS_RETRY|SSQ_DECREMENT_COUNT|
1720                                           SSQ_PRINT_SENSE;
1721                         }
1722                 }
1723         }
1724 #ifdef KERNEL
1725         if (bootverbose)
1726                 sense_flags |= SF_PRINT_ALWAYS;
1727 #endif
1728         if ((sense_flags & SF_PRINT_ALWAYS) != 0)
1729                 action |= SSQ_PRINT_SENSE;
1730         else if ((sense_flags & SF_NO_PRINT) != 0)
1731                 action &= ~SSQ_PRINT_SENSE;
1732
1733         return (action);
1734 }
1735
1736 char *
1737 scsi_cdb_string(u_int8_t *cdb_ptr, char *cdb_string, size_t len)
1738 {
1739         u_int8_t cdb_len;
1740         int i;
1741
1742         if (cdb_ptr == NULL)
1743                 return("");
1744
1745         /* Silence warnings */
1746         cdb_len = 0;
1747
1748         /*
1749          * This is taken from the SCSI-3 draft spec.
1750          * (T10/1157D revision 0.3)
1751          * The top 3 bits of an opcode are the group code.  The next 5 bits
1752          * are the command code.
1753          * Group 0:  six byte commands
1754          * Group 1:  ten byte commands
1755          * Group 2:  ten byte commands
1756          * Group 3:  reserved
1757          * Group 4:  sixteen byte commands
1758          * Group 5:  twelve byte commands
1759          * Group 6:  vendor specific
1760          * Group 7:  vendor specific
1761          */
1762         switch((*cdb_ptr >> 5) & 0x7) {
1763                 case 0:
1764                         cdb_len = 6;
1765                         break;
1766                 case 1:
1767                 case 2:
1768                         cdb_len = 10;
1769                         break;
1770                 case 3:
1771                 case 6:
1772                 case 7:
1773                         /* in this case, just print out the opcode */
1774                         cdb_len = 1;
1775                         break;
1776                 case 4:
1777                         cdb_len = 16;
1778                         break;
1779                 case 5:
1780                         cdb_len = 12;
1781                         break;
1782         }
1783         *cdb_string = '\0';
1784         for (i = 0; i < cdb_len; i++)
1785                 ksnprintf(cdb_string + strlen(cdb_string),
1786                           len - strlen(cdb_string), "%x ", cdb_ptr[i]);
1787
1788         return(cdb_string);
1789 }
1790
1791 const char *
1792 scsi_status_string(struct ccb_scsiio *csio)
1793 {
1794         switch(csio->scsi_status) {
1795         case SCSI_STATUS_OK:
1796                 return("OK");
1797         case SCSI_STATUS_CHECK_COND:
1798                 return("Check Condition");
1799         case SCSI_STATUS_BUSY:
1800                 return("Busy");
1801         case SCSI_STATUS_INTERMED:
1802                 return("Intermediate");
1803         case SCSI_STATUS_INTERMED_COND_MET:
1804                 return("Intermediate-Condition Met");
1805         case SCSI_STATUS_RESERV_CONFLICT:
1806                 return("Reservation Conflict");
1807         case SCSI_STATUS_CMD_TERMINATED:
1808                 return("Command Terminated");
1809         case SCSI_STATUS_QUEUE_FULL:
1810                 return("Queue Full");
1811         case SCSI_STATUS_ACA_ACTIVE:
1812                 return("ACA Active");
1813         case SCSI_STATUS_TASK_ABORTED:
1814                 return("Task Aborted");
1815         default: {
1816                 static char unkstr[64];
1817                 ksnprintf(unkstr, sizeof(unkstr), "Unknown %#x",
1818                           csio->scsi_status);
1819                 return(unkstr);
1820         }
1821         }
1822 }
1823
1824 /*
1825  * scsi_command_string() returns 0 for success and -1 for failure.
1826  */
1827 #ifdef _KERNEL
1828 int
1829 scsi_command_string(struct ccb_scsiio *csio, struct sbuf *sb)
1830 #else
1831 int
1832 scsi_command_string(struct cam_device *device, struct ccb_scsiio *csio,
1833                     struct sbuf *sb)
1834 #endif
1835 {
1836         struct scsi_inquiry_data *inq_data;
1837         char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
1838 #ifdef _KERNEL
1839         struct    ccb_getdev cgd;
1840 #endif
1841
1842 #ifdef _KERNEL
1843         /*
1844          * Get the device information.
1845          */
1846         xpt_setup_ccb(&cgd.ccb_h,
1847                       csio->ccb_h.path,
1848                       /*priority*/ 1);
1849         cgd.ccb_h.func_code = XPT_GDEV_TYPE;
1850         xpt_action((union ccb *)&cgd);
1851
1852         /*
1853          * If the device is unconfigured, just pretend that it is a hard
1854          * drive.  scsi_op_desc() needs this.
1855          */
1856         if (cgd.ccb_h.status == CAM_DEV_NOT_THERE)
1857                 cgd.inq_data.device = T_DIRECT;
1858
1859         inq_data = &cgd.inq_data;
1860
1861 #else /* !_KERNEL */
1862
1863         inq_data = &device->inq_data;
1864
1865 #endif /* _KERNEL/!_KERNEL */
1866
1867         if ((csio->ccb_h.flags & CAM_CDB_POINTER) != 0) {
1868                 sbuf_printf(sb, "%s. CDB: %s",
1869                             scsi_op_desc(csio->cdb_io.cdb_ptr[0], inq_data),
1870                             scsi_cdb_string(csio->cdb_io.cdb_ptr, cdb_str,
1871                                             sizeof(cdb_str)));
1872         } else {
1873                 sbuf_printf(sb, "%s. CDB: %s",
1874                             scsi_op_desc(csio->cdb_io.cdb_bytes[0], inq_data),
1875                             scsi_cdb_string(csio->cdb_io.cdb_bytes, cdb_str,
1876                                             sizeof(cdb_str)));
1877         }
1878
1879         return(0);
1880 }
1881
1882 /*
1883  * scsi_sense_sbuf() returns 0 for success and -1 for failure.
1884  */
1885 #ifdef _KERNEL
1886 int
1887 scsi_sense_sbuf(struct ccb_scsiio *csio, struct sbuf *sb,
1888                 scsi_sense_string_flags flags)
1889 #else /* !_KERNEL */
1890 int
1891 scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
1892                 struct sbuf *sb, scsi_sense_string_flags flags)
1893 #endif /* _KERNEL/!_KERNEL */
1894 {
1895         struct    scsi_sense_data *sense;
1896         struct    scsi_inquiry_data *inq_data;
1897 #ifdef _KERNEL
1898         struct    ccb_getdev cgd;
1899 #endif /* _KERNEL */
1900         u_int32_t info;
1901         int       error_code;
1902         int       sense_key;
1903         int       asc, ascq;
1904         char      path_str[64];
1905
1906 #ifndef _KERNEL
1907         if (device == NULL)
1908                 return(-1);
1909 #endif /* !_KERNEL */
1910         if ((csio == NULL) || (sb == NULL))
1911                 return(-1);
1912
1913         /*
1914          * If the CDB is a physical address, we can't deal with it..
1915          */
1916         if ((csio->ccb_h.flags & CAM_CDB_PHYS) != 0)
1917                 flags &= ~SSS_FLAG_PRINT_COMMAND;
1918
1919 #ifdef _KERNEL
1920         xpt_path_string(csio->ccb_h.path, path_str, sizeof(path_str));
1921 #else /* !_KERNEL */
1922         cam_path_string(device, path_str, sizeof(path_str));
1923 #endif /* _KERNEL/!_KERNEL */
1924
1925 #ifdef _KERNEL
1926         /*
1927          * Get the device information.
1928          */
1929         xpt_setup_ccb(&cgd.ccb_h,
1930                       csio->ccb_h.path,
1931                       /*priority*/ 1);
1932         cgd.ccb_h.func_code = XPT_GDEV_TYPE;
1933         xpt_action((union ccb *)&cgd);
1934
1935         /*
1936          * If the device is unconfigured, just pretend that it is a hard
1937          * drive.  scsi_op_desc() needs this.
1938          */
1939         if (cgd.ccb_h.status == CAM_DEV_NOT_THERE)
1940                 cgd.inq_data.device = T_DIRECT;
1941
1942         inq_data = &cgd.inq_data;
1943
1944 #else /* !_KERNEL */
1945
1946         inq_data = &device->inq_data;
1947
1948 #endif /* _KERNEL/!_KERNEL */
1949
1950         sense = NULL;
1951
1952         if (flags & SSS_FLAG_PRINT_COMMAND) {
1953
1954                 sbuf_cat(sb, path_str);
1955
1956 #ifdef _KERNEL
1957                 scsi_command_string(csio, sb);
1958 #else /* !_KERNEL */
1959                 scsi_command_string(device, csio, sb);
1960 #endif /* _KERNEL/!_KERNEL */
1961         }
1962
1963         /*
1964          * If the sense data is a physical pointer, forget it.
1965          */
1966         if (csio->ccb_h.flags & CAM_SENSE_PTR) {
1967                 if (csio->ccb_h.flags & CAM_SENSE_PHYS)
1968                         return(-1);
1969                 else {
1970                         /* 
1971                          * bcopy the pointer to avoid unaligned access
1972                          * errors on finicky architectures.  We don't
1973                          * ensure that the sense data is pointer aligned.
1974                          */
1975                         bcopy(&csio->sense_data, &sense, 
1976                               sizeof(struct scsi_sense_data *));
1977                 }
1978         } else {
1979                 /*
1980                  * If the physical sense flag is set, but the sense pointer
1981                  * is not also set, we assume that the user is an idiot and
1982                  * return.  (Well, okay, it could be that somehow, the
1983                  * entire csio is physical, but we would have probably core
1984                  * dumped on one of the bogus pointer deferences above
1985                  * already.)
1986                  */
1987                 if (csio->ccb_h.flags & CAM_SENSE_PHYS) 
1988                         return(-1);
1989                 else
1990                         sense = &csio->sense_data;
1991         }
1992
1993
1994         sbuf_cat(sb, path_str);
1995
1996         error_code = sense->error_code & SSD_ERRCODE;
1997         sense_key = sense->flags & SSD_KEY;
1998
1999         switch (error_code) {
2000         case SSD_DEFERRED_ERROR:
2001                 sbuf_printf(sb, "Deferred Error: ");
2002
2003                 /* FALLTHROUGH */
2004         case SSD_CURRENT_ERROR:
2005         {
2006                 const char *sense_key_desc;
2007                 const char *asc_desc;
2008
2009                 asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0;
2010                 ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0;
2011                 scsi_sense_desc(sense_key, asc, ascq, inq_data,
2012                                 &sense_key_desc, &asc_desc);
2013                 sbuf_cat(sb, sense_key_desc);
2014
2015                 info = scsi_4btoul(sense->info);
2016                 
2017                 if (sense->error_code & SSD_ERRCODE_VALID) {
2018
2019                         switch (sense_key) {
2020                         case SSD_KEY_NOT_READY:
2021                         case SSD_KEY_ILLEGAL_REQUEST:
2022                         case SSD_KEY_UNIT_ATTENTION:
2023                         case SSD_KEY_DATA_PROTECT:
2024                                 break;
2025                         case SSD_KEY_BLANK_CHECK:
2026                                 sbuf_printf(sb, " req sz: %d (decimal)", info);
2027                                 break;
2028                         default:
2029                                 if (info) {
2030                                         if (sense->flags & SSD_ILI) {
2031                                                 sbuf_printf(sb, " ILI (length "
2032                                                         "mismatch): %d", info);
2033                         
2034                                         } else {
2035                                                 sbuf_printf(sb, " info:%x",
2036                                                             info);
2037                                         }
2038                                 }
2039                         }
2040                 } else if (info) {
2041                         sbuf_printf(sb, " info?:%x", info);
2042                 }
2043
2044                 if (sense->extra_len >= 4) {
2045                         if (bcmp(sense->cmd_spec_info, "\0\0\0\0", 4)) {
2046                                 sbuf_printf(sb, " csi:%x,%x,%x,%x",
2047                                             sense->cmd_spec_info[0],
2048                                             sense->cmd_spec_info[1],
2049                                             sense->cmd_spec_info[2],
2050                                             sense->cmd_spec_info[3]);
2051                         }
2052                 }
2053
2054                 sbuf_printf(sb, " asc:%x,%x\n%s%s", asc, ascq,
2055                             path_str, asc_desc);
2056
2057                 if (sense->extra_len >= 7 && sense->fru) {
2058                         sbuf_printf(sb, " field replaceable unit: %x",
2059                                     sense->fru);
2060                 }
2061
2062                 if ((sense->extra_len >= 10)
2063                  && (sense->sense_key_spec[0] & SSD_SCS_VALID) != 0) {
2064                         switch(sense_key) {
2065                         case SSD_KEY_ILLEGAL_REQUEST: {
2066                                 int bad_command;
2067                                 char tmpstr2[40];
2068
2069                                 if (sense->sense_key_spec[0] & 0x40)
2070                                         bad_command = 1;
2071                                 else
2072                                         bad_command = 0;
2073
2074                                 tmpstr2[0] = '\0';
2075
2076                                 /* Bit pointer is valid */
2077                                 if (sense->sense_key_spec[0] & 0x08)
2078                                         ksnprintf(tmpstr2, sizeof(tmpstr2),
2079                                                  "bit %d",
2080                                                 sense->sense_key_spec[0] & 0x7);
2081                                         sbuf_printf(sb,
2082                                                    ": %s byte %d %s is invalid",
2083                                                     bad_command ?
2084                                                     "Command" : "Data",
2085                                                     scsi_2btoul(
2086                                                     &sense->sense_key_spec[1]),
2087                                                     tmpstr2);
2088                                 break;
2089                         }
2090                         case SSD_KEY_RECOVERED_ERROR:
2091                         case SSD_KEY_HARDWARE_ERROR:
2092                         case SSD_KEY_MEDIUM_ERROR:
2093                                 sbuf_printf(sb, " actual retry count: %d",
2094                                             scsi_2btoul(
2095                                             &sense->sense_key_spec[1]));
2096                                 break;
2097                         default:
2098                                 sbuf_printf(sb, " sks:%#x,%#x",
2099                                             sense->sense_key_spec[0],
2100                                             scsi_2btoul(
2101                                             &sense->sense_key_spec[1]));
2102                                 break;
2103                         }
2104                 }
2105                 break;
2106
2107         }
2108         default:
2109                 sbuf_printf(sb, "error code %d",
2110                             sense->error_code & SSD_ERRCODE);
2111
2112                 if (sense->error_code & SSD_ERRCODE_VALID) {
2113                         sbuf_printf(sb, " at block no. %d (decimal)",
2114                                     info = scsi_4btoul(sense->info));
2115                 }
2116         }
2117
2118         sbuf_printf(sb, "\n");
2119
2120         return(0);
2121 }
2122
2123 #ifdef _KERNEL
2124 char *
2125 scsi_sense_string(struct ccb_scsiio *csio, char *str, int str_len)
2126 #else /* !_KERNEL */
2127 char *
2128 scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
2129                   char *str, int str_len)
2130 #endif /* _KERNEL/!_KERNEL */
2131 {
2132         struct sbuf sb;
2133
2134         sbuf_new(&sb, str, str_len, 0);
2135
2136 #ifdef _KERNEL
2137         scsi_sense_sbuf(csio, &sb, SSS_FLAG_PRINT_COMMAND);
2138 #else /* !_KERNEL */
2139         scsi_sense_sbuf(device, csio, &sb, SSS_FLAG_PRINT_COMMAND);
2140 #endif /* _KERNEL/!_KERNEL */
2141
2142         sbuf_finish(&sb);
2143
2144         return(sbuf_data(&sb));
2145 }
2146
2147 #ifdef _KERNEL
2148 void
2149 scsi_sense_print(struct ccb_scsiio *csio)
2150 {
2151         struct sbuf sb;
2152         char str[512];
2153
2154         sbuf_new(&sb, str, sizeof(str), 0);
2155
2156         scsi_sense_sbuf(csio, &sb, SSS_FLAG_PRINT_COMMAND);
2157
2158         sbuf_finish(&sb);
2159
2160         kprintf("%s", sbuf_data(&sb));
2161 }
2162
2163 #else /* !_KERNEL */
2164 void
2165 scsi_sense_print(struct cam_device *device, struct ccb_scsiio *csio, 
2166                  FILE *ofile)
2167 {
2168         struct sbuf sb;
2169         char str[512];
2170
2171         if ((device == NULL) || (csio == NULL) || (ofile == NULL))
2172                 return;
2173
2174         sbuf_new(&sb, str, sizeof(str), 0);
2175
2176         scsi_sense_sbuf(device, csio, &sb, SSS_FLAG_PRINT_COMMAND);
2177
2178         sbuf_finish(&sb);
2179
2180         fprintf(ofile, "%s", sbuf_data(&sb));
2181 }
2182
2183 #endif /* _KERNEL/!_KERNEL */
2184
2185 /*
2186  * This function currently requires at least 36 bytes, or
2187  * SHORT_INQUIRY_LENGTH, worth of data to function properly.  If this
2188  * function needs more or less data in the future, another length should be
2189  * defined in scsi_all.h to indicate the minimum amount of data necessary
2190  * for this routine to function properly.
2191  */
2192 void
2193 scsi_print_inquiry(struct scsi_inquiry_data *inq_data)
2194 {
2195         u_int8_t type;
2196         char *dtype, *qtype;
2197         char vendor[16], product[48], revision[16], rstr[4];
2198
2199         type = SID_TYPE(inq_data);
2200
2201         /*
2202          * Figure out basic device type and qualifier.
2203          */
2204         if (SID_QUAL_IS_VENDOR_UNIQUE(inq_data)) {
2205                 qtype = "(vendor-unique qualifier)";
2206         } else {
2207                 switch (SID_QUAL(inq_data)) {
2208                 case SID_QUAL_LU_CONNECTED:
2209                         qtype = "";
2210                         break;
2211
2212                 case SID_QUAL_LU_OFFLINE:
2213                         qtype = "(offline)";
2214                         break;
2215
2216                 case SID_QUAL_RSVD:
2217                         qtype = "(reserved qualifier)";
2218                         break;
2219                 default:
2220                 case SID_QUAL_BAD_LU:
2221                         qtype = "(lun not supported)";
2222                         break;
2223                 }
2224         }
2225
2226         switch (type) {
2227         case T_DIRECT:
2228                 dtype = "Direct Access";
2229                 break;
2230         case T_SEQUENTIAL:
2231                 dtype = "Sequential Access";
2232                 break;
2233         case T_PRINTER:
2234                 dtype = "Printer";
2235                 break;
2236         case T_PROCESSOR:
2237                 dtype = "Processor";
2238                 break;
2239         case T_CDROM:
2240                 dtype = "CD-ROM";
2241                 break;
2242         case T_WORM:
2243                 dtype = "Worm";
2244                 break;
2245         case T_SCANNER:
2246                 dtype = "Scanner";
2247                 break;
2248         case T_OPTICAL:
2249                 dtype = "Optical";
2250                 break;
2251         case T_CHANGER:
2252                 dtype = "Changer";
2253                 break;
2254         case T_COMM:
2255                 dtype = "Communication";
2256                 break;
2257         case T_STORARRAY:
2258                 dtype = "Storage Array";
2259                 break;
2260         case T_ENCLOSURE:
2261                 dtype = "Enclosure Services";
2262                 break;
2263         case T_RBC:
2264                 dtype = "Simplified Direct Access";
2265                 break;
2266         case T_OCRW:
2267                 dtype = "Optical Card Read/Write";
2268                 break;
2269         case T_NODEVICE:
2270                 dtype = "Uninstalled";
2271         default:
2272                 dtype = "unknown";
2273                 break;
2274         }
2275
2276         cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor),
2277                    sizeof(vendor));
2278         cam_strvis(product, inq_data->product, sizeof(inq_data->product),
2279                    sizeof(product));
2280         cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision),
2281                    sizeof(revision));
2282
2283         if (SID_ANSI_REV(inq_data) == SCSI_REV_CCS)
2284                 bcopy("CCS", rstr, 4);
2285         else
2286                 ksnprintf(rstr, sizeof (rstr), "%d", SID_ANSI_REV(inq_data));
2287         kprintf("<%s %s %s> %s %s SCSI-%s device %s\n",
2288                vendor, product, revision,
2289                SID_IS_REMOVABLE(inq_data) ? "Removable" : "Fixed",
2290                dtype, rstr, qtype);
2291 }
2292
2293 /*
2294  * Table of syncrates that don't follow the "divisible by 4"
2295  * rule. This table will be expanded in future SCSI specs.
2296  */
2297 static struct {
2298         u_int period_factor;
2299         u_int period;   /* in 100ths of ns */
2300 } scsi_syncrates[] = {
2301         { 0x08, 625 },  /* FAST-160 */
2302         { 0x09, 1250 }, /* FAST-80 */
2303         { 0x0a, 2500 }, /* FAST-40 40MHz */
2304         { 0x0b, 3030 }, /* FAST-40 33MHz */
2305         { 0x0c, 5000 }  /* FAST-20 */
2306 };
2307
2308 /*
2309  * Return the frequency in kHz corresponding to the given
2310  * sync period factor.
2311  */
2312 u_int
2313 scsi_calc_syncsrate(u_int period_factor)
2314 {
2315         int i;
2316         int num_syncrates;
2317
2318         num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
2319         /* See if the period is in the "exception" table */
2320         for (i = 0; i < num_syncrates; i++) {
2321
2322                 if (period_factor == scsi_syncrates[i].period_factor) {
2323                         /* Period in kHz */
2324                         return (100000000 / scsi_syncrates[i].period);
2325                 }
2326         }
2327
2328         /*
2329          * Wasn't in the table, so use the standard
2330          * 4 times conversion.
2331          */
2332         return (10000000 / (period_factor * 4 * 10));
2333 }
2334
2335 /*
2336  * Return the SCSI sync parameter that corresponsd to
2337  * the passed in period in 10ths of ns.
2338  */
2339 u_int
2340 scsi_calc_syncparam(u_int period)
2341 {
2342         int i;
2343         int num_syncrates;
2344
2345         if (period == 0)
2346                 return (~0);    /* Async */
2347
2348         /* Adjust for exception table being in 100ths. */
2349         period *= 10;
2350         num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
2351         /* See if the period is in the "exception" table */
2352         for (i = 0; i < num_syncrates; i++) {
2353
2354                 if (period <= scsi_syncrates[i].period) {
2355                         /* Period in 100ths of ns */
2356                         return (scsi_syncrates[i].period_factor);
2357                 }
2358         }
2359
2360         /*
2361          * Wasn't in the table, so use the standard
2362          * 1/4 period in ns conversion.
2363          */
2364         return (period/400);
2365 }
2366
2367 void
2368 scsi_test_unit_ready(struct ccb_scsiio *csio, u_int32_t retries,
2369                      void (*cbfcnp)(struct cam_periph *, union ccb *),
2370                      u_int8_t tag_action, u_int8_t sense_len, u_int32_t timeout)
2371 {
2372         struct scsi_test_unit_ready *scsi_cmd;
2373
2374         cam_fill_csio(csio,
2375                       retries,
2376                       cbfcnp,
2377                       CAM_DIR_NONE,
2378                       tag_action,
2379                       /*data_ptr*/NULL,
2380                       /*dxfer_len*/0,
2381                       sense_len,
2382                       sizeof(*scsi_cmd),
2383                       timeout);
2384
2385         scsi_cmd = (struct scsi_test_unit_ready *)&csio->cdb_io.cdb_bytes;
2386         bzero(scsi_cmd, sizeof(*scsi_cmd));
2387         scsi_cmd->opcode = TEST_UNIT_READY;
2388 }
2389
2390 void
2391 scsi_request_sense(struct ccb_scsiio *csio, u_int32_t retries,
2392                    void (*cbfcnp)(struct cam_periph *, union ccb *),
2393                    void *data_ptr, u_int8_t dxfer_len, u_int8_t tag_action,
2394                    u_int8_t sense_len, u_int32_t timeout)
2395 {
2396         struct scsi_request_sense *scsi_cmd;
2397
2398         cam_fill_csio(csio,
2399                       retries,
2400                       cbfcnp,
2401                       CAM_DIR_IN,
2402                       tag_action,
2403                       data_ptr,
2404                       dxfer_len,
2405                       sense_len,
2406                       sizeof(*scsi_cmd),
2407                       timeout);
2408
2409         scsi_cmd = (struct scsi_request_sense *)&csio->cdb_io.cdb_bytes;
2410         bzero(scsi_cmd, sizeof(*scsi_cmd));
2411         scsi_cmd->opcode = REQUEST_SENSE;
2412         scsi_cmd->length = dxfer_len;
2413 }
2414
2415 void
2416 scsi_inquiry(struct ccb_scsiio *csio, u_int32_t retries,
2417              void (*cbfcnp)(struct cam_periph *, union ccb *),
2418              u_int8_t tag_action, u_int8_t *inq_buf, u_int32_t inq_len,
2419              int evpd, u_int8_t page_code, u_int8_t sense_len,
2420              u_int32_t timeout)
2421 {
2422         struct scsi_inquiry *scsi_cmd;
2423
2424         cam_fill_csio(csio,
2425                       retries,
2426                       cbfcnp,
2427                       /*flags*/CAM_DIR_IN,
2428                       tag_action,
2429                       /*data_ptr*/inq_buf,
2430                       /*dxfer_len*/inq_len,
2431                       sense_len,
2432                       sizeof(*scsi_cmd),
2433                       timeout);
2434
2435         scsi_cmd = (struct scsi_inquiry *)&csio->cdb_io.cdb_bytes;
2436         bzero(scsi_cmd, sizeof(*scsi_cmd));
2437         scsi_cmd->opcode = INQUIRY;
2438         if (evpd) {
2439                 scsi_cmd->byte2 |= SI_EVPD;
2440                 scsi_cmd->page_code = page_code;                
2441         }
2442         /*
2443          * A 'transfer units' count of 256 is coded as
2444          * zero for all commands with a single byte count
2445          * field. 
2446          */
2447         if (inq_len == 256)
2448                 inq_len = 0;
2449         scsi_cmd->length = inq_len;
2450 }
2451
2452 void
2453 scsi_mode_sense(struct ccb_scsiio *csio, u_int32_t retries,
2454                 void (*cbfcnp)(struct cam_periph *, union ccb *),
2455                 u_int8_t tag_action, int dbd, u_int8_t page_code,
2456                 u_int8_t page, u_int8_t *param_buf, u_int32_t param_len,
2457                 u_int8_t sense_len, u_int32_t timeout)
2458 {
2459         return(scsi_mode_sense_len(csio, retries, cbfcnp, tag_action, dbd,
2460                 page_code, page, param_buf, param_len, 0,
2461                 sense_len, timeout));
2462 }
2463
2464 void
2465 scsi_mode_sense_len(struct ccb_scsiio *csio, u_int32_t retries,
2466                     void (*cbfcnp)(struct cam_periph *, union ccb *),
2467                     u_int8_t tag_action, int dbd, u_int8_t page_code,
2468                     u_int8_t page, u_int8_t *param_buf, u_int32_t param_len,
2469                     int minimum_cmd_size, u_int8_t sense_len, u_int32_t timeout)
2470 {
2471         u_int8_t cdb_len;
2472
2473         /*
2474          * Use the smallest possible command to perform the operation.
2475          */
2476         if ((param_len < 256) && (minimum_cmd_size < 10)) {
2477                 /*
2478                  * We can fit in a 6 byte cdb.
2479                  */
2480                 struct scsi_mode_sense_6 *scsi_cmd;
2481
2482                 scsi_cmd = (struct scsi_mode_sense_6 *)&csio->cdb_io.cdb_bytes;
2483                 bzero(scsi_cmd, sizeof(*scsi_cmd));
2484                 scsi_cmd->opcode = MODE_SENSE_6;
2485                 if (dbd != 0)
2486                         scsi_cmd->byte2 |= SMS_DBD;
2487                 scsi_cmd->page = page_code | page;
2488                 scsi_cmd->length = param_len;
2489                 cdb_len = sizeof(*scsi_cmd);
2490         } else {
2491                 /*
2492                  * Need a 10 byte cdb.
2493                  */
2494                 struct scsi_mode_sense_10 *scsi_cmd;
2495
2496                 scsi_cmd = (struct scsi_mode_sense_10 *)&csio->cdb_io.cdb_bytes;
2497                 bzero(scsi_cmd, sizeof(*scsi_cmd));
2498                 scsi_cmd->opcode = MODE_SENSE_10;
2499                 if (dbd != 0)
2500                         scsi_cmd->byte2 |= SMS_DBD;
2501                 scsi_cmd->page = page_code | page;
2502                 scsi_ulto2b(param_len, scsi_cmd->length);
2503                 cdb_len = sizeof(*scsi_cmd);
2504         }
2505         cam_fill_csio(csio,
2506                       retries,
2507                       cbfcnp,
2508                       CAM_DIR_IN,
2509                       tag_action,
2510                       param_buf,
2511                       param_len,
2512                       sense_len,
2513                       cdb_len,
2514                       timeout);
2515 }
2516
2517 void
2518 scsi_mode_select(struct ccb_scsiio *csio, u_int32_t retries,
2519                  void (*cbfcnp)(struct cam_periph *, union ccb *),
2520                  u_int8_t tag_action, int scsi_page_fmt, int save_pages,
2521                  u_int8_t *param_buf, u_int32_t param_len, u_int8_t sense_len,
2522                  u_int32_t timeout)
2523 {
2524         return(scsi_mode_select_len(csio, retries, cbfcnp, tag_action,
2525                 scsi_page_fmt, save_pages, param_buf,
2526                 param_len, 0, sense_len, timeout));
2527 }
2528
2529 void
2530 scsi_mode_select_len(struct ccb_scsiio *csio, u_int32_t retries,
2531                     void (*cbfcnp)(struct cam_periph *, union ccb *),
2532                     u_int8_t tag_action, int scsi_page_fmt, int save_pages,
2533                     u_int8_t *param_buf, u_int32_t param_len,
2534                     int minimum_cmd_size, u_int8_t sense_len,
2535                     u_int32_t timeout)
2536 {
2537         u_int8_t cdb_len;
2538
2539         /*
2540          * Use the smallest possible command to perform the operation.
2541          */
2542         if ((param_len < 256) && (minimum_cmd_size < 10)) {
2543                 /*
2544                  * We can fit in a 6 byte cdb.
2545                  */
2546                 struct scsi_mode_select_6 *scsi_cmd;
2547
2548                 scsi_cmd = (struct scsi_mode_select_6 *)&csio->cdb_io.cdb_bytes;
2549                 bzero(scsi_cmd, sizeof(*scsi_cmd));
2550                 scsi_cmd->opcode = MODE_SELECT_6;
2551                 if (scsi_page_fmt != 0)
2552                         scsi_cmd->byte2 |= SMS_PF;
2553                 if (save_pages != 0)
2554                         scsi_cmd->byte2 |= SMS_SP;
2555                 scsi_cmd->length = param_len;
2556                 cdb_len = sizeof(*scsi_cmd);
2557         } else {
2558                 /*
2559                  * Need a 10 byte cdb.
2560                  */
2561                 struct scsi_mode_select_10 *scsi_cmd;
2562
2563                 scsi_cmd =
2564                     (struct scsi_mode_select_10 *)&csio->cdb_io.cdb_bytes;
2565                 bzero(scsi_cmd, sizeof(*scsi_cmd));
2566                 scsi_cmd->opcode = MODE_SELECT_10;
2567                 if (scsi_page_fmt != 0)
2568                         scsi_cmd->byte2 |= SMS_PF;
2569                 if (save_pages != 0)
2570                         scsi_cmd->byte2 |= SMS_SP;
2571                 scsi_ulto2b(param_len, scsi_cmd->length);
2572                 cdb_len = sizeof(*scsi_cmd);
2573         }
2574         cam_fill_csio(csio,
2575                       retries,
2576                       cbfcnp,
2577                       CAM_DIR_OUT,
2578                       tag_action,
2579                       param_buf,
2580                       param_len,
2581                       sense_len,
2582                       cdb_len,
2583                       timeout);
2584 }
2585
2586 void
2587 scsi_read_capacity_16(struct ccb_scsiio *csio, uint32_t retries,
2588                       void (*cbfcnp)(struct cam_periph *, union ccb *),
2589                       uint8_t tag_action, uint64_t lba, int reladr, int pmi,
2590                       struct scsi_read_capacity_data_long *rcap_buf,
2591                       uint8_t sense_len, uint32_t timeout)
2592 {
2593         struct scsi_read_capacity_16 *scsi_cmd;
2594
2595         cam_fill_csio(csio,
2596                       retries,
2597                       cbfcnp,
2598                       /*flags*/CAM_DIR_IN,
2599                       tag_action,
2600                       /*data_ptr*/(u_int8_t *)rcap_buf,
2601                       /*dxfer_len*/sizeof(*rcap_buf),
2602                       sense_len,
2603                       sizeof(*scsi_cmd),
2604                       timeout);
2605         scsi_cmd = (struct scsi_read_capacity_16 *)&csio->cdb_io.cdb_bytes;
2606         bzero(scsi_cmd, sizeof(*scsi_cmd));
2607         scsi_cmd->opcode = SERVICE_ACTION_IN;
2608         scsi_cmd->service_action = SRC16_SERVICE_ACTION;
2609         scsi_u64to8b(lba, scsi_cmd->addr);
2610         scsi_ulto4b(sizeof(*rcap_buf), scsi_cmd->alloc_len);
2611         if (pmi)
2612                reladr |= SRC16_PMI;
2613         if (reladr)
2614                reladr |= SRC16_RELADR;
2615 }
2616
2617 /*
2618  * Prevent or allow the user to remove the media
2619  */
2620 void
2621 scsi_prevent(struct ccb_scsiio *csio, u_int32_t retries,
2622              void (*cbfcnp)(struct cam_periph *, union ccb *),
2623              u_int8_t tag_action, u_int8_t action,
2624              u_int8_t sense_len, u_int32_t timeout)
2625 {
2626         struct scsi_prevent *scsi_cmd;
2627
2628         cam_fill_csio(csio,
2629                       retries,
2630                       cbfcnp,
2631                       /*flags*/CAM_DIR_NONE,
2632                       tag_action,
2633                       /*data_ptr*/NULL,
2634                       /*dxfer_len*/0,
2635                       sense_len,
2636                       sizeof(*scsi_cmd),
2637                       timeout);
2638
2639         scsi_cmd = (struct scsi_prevent *)&csio->cdb_io.cdb_bytes;
2640         bzero(scsi_cmd, sizeof(*scsi_cmd));
2641         scsi_cmd->opcode = PREVENT_ALLOW;
2642         scsi_cmd->how = action;
2643 }
2644
2645 /* XXX allow specification of address and PMI bit and LBA */
2646 void
2647 scsi_read_capacity(struct ccb_scsiio *csio, u_int32_t retries,
2648                    void (*cbfcnp)(struct cam_periph *, union ccb *),
2649                    u_int8_t tag_action,
2650                    struct scsi_read_capacity_data *rcap_buf,
2651                    u_int8_t sense_len, u_int32_t timeout)
2652 {
2653         struct scsi_read_capacity *scsi_cmd;
2654
2655         cam_fill_csio(csio,
2656                       retries,
2657                       cbfcnp,
2658                       /*flags*/CAM_DIR_IN,
2659                       tag_action,
2660                       /*data_ptr*/(u_int8_t *)rcap_buf,
2661                       /*dxfer_len*/sizeof(*rcap_buf),
2662                       sense_len,
2663                       sizeof(*scsi_cmd),
2664                       timeout);
2665
2666         scsi_cmd = (struct scsi_read_capacity *)&csio->cdb_io.cdb_bytes;
2667         bzero(scsi_cmd, sizeof(*scsi_cmd));
2668         scsi_cmd->opcode = READ_CAPACITY;
2669 }
2670
2671 void
2672 scsi_report_luns(struct ccb_scsiio *csio, u_int32_t retries,
2673                  void (*cbfcnp)(struct cam_periph *, union ccb *),
2674                  u_int8_t tag_action, struct scsi_report_luns_data *rpl_buf,
2675                  u_int32_t alloc_len, u_int8_t sense_len, u_int32_t timeout)
2676 {
2677         struct scsi_report_luns *scsi_cmd;
2678
2679         cam_fill_csio(csio,
2680                       retries,
2681                       cbfcnp,
2682                       /*flags*/CAM_DIR_IN,
2683                       tag_action,
2684                       /*data_ptr*/(u_int8_t *)rpl_buf,
2685                       /*dxfer_len*/alloc_len,
2686                       sense_len,
2687                       sizeof(*scsi_cmd),
2688                       timeout);
2689         scsi_cmd = (struct scsi_report_luns *)&csio->cdb_io.cdb_bytes;
2690         bzero(scsi_cmd, sizeof(*scsi_cmd));
2691         scsi_cmd->opcode = REPORT_LUNS;
2692         scsi_ulto4b(alloc_len, scsi_cmd->addr);
2693 }
2694
2695 /*
2696  * Syncronize the media to the contents of the cache for
2697  * the given lba/count pair.  Specifying 0/0 means sync
2698  * the whole cache.
2699  */
2700 void
2701 scsi_synchronize_cache(struct ccb_scsiio *csio, u_int32_t retries,
2702                        void (*cbfcnp)(struct cam_periph *, union ccb *),
2703                        u_int8_t tag_action, u_int32_t begin_lba,
2704                        u_int16_t lb_count, u_int8_t sense_len,
2705                        u_int32_t timeout)
2706 {
2707         struct scsi_sync_cache *scsi_cmd;
2708
2709         cam_fill_csio(csio,
2710                       retries,
2711                       cbfcnp,
2712                       /*flags*/CAM_DIR_NONE,
2713                       tag_action,
2714                       /*data_ptr*/NULL,
2715                       /*dxfer_len*/0,
2716                       sense_len,
2717                       sizeof(*scsi_cmd),
2718                       timeout);
2719
2720         scsi_cmd = (struct scsi_sync_cache *)&csio->cdb_io.cdb_bytes;
2721         bzero(scsi_cmd, sizeof(*scsi_cmd));
2722         scsi_cmd->opcode = SYNCHRONIZE_CACHE;
2723         scsi_ulto4b(begin_lba, scsi_cmd->begin_lba);
2724         scsi_ulto2b(lb_count, scsi_cmd->lb_count);
2725 }
2726
2727 void
2728 scsi_read_write(struct ccb_scsiio *csio, u_int32_t retries,
2729                 void (*cbfcnp)(struct cam_periph *, union ccb *),
2730                 u_int8_t tag_action, int readop, u_int8_t byte2,
2731                 int minimum_cmd_size, u_int64_t lba, u_int32_t block_count,
2732                 u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
2733                 u_int32_t timeout)
2734 {
2735         u_int8_t cdb_len;
2736
2737         /*
2738          * Use the smallest possible command to perform the operation
2739          * as some legacy hardware does not support the 10 byte commands.
2740          * If any of the bits in byte2 is set, we have to go with a larger
2741          * command.
2742          */
2743         if ((minimum_cmd_size < 10)
2744          && ((lba & 0x1fffff) == lba)
2745          && ((block_count & 0xff) == block_count)
2746          && (byte2 == 0)) {
2747                 /*
2748                  * We can fit in a 6 byte cdb.
2749                  */
2750                 struct scsi_rw_6 *scsi_cmd;
2751
2752                 scsi_cmd = (struct scsi_rw_6 *)&csio->cdb_io.cdb_bytes;
2753                 scsi_cmd->opcode = readop ? READ_6 : WRITE_6;
2754                 scsi_ulto3b(lba, scsi_cmd->addr);
2755                 scsi_cmd->length = block_count & 0xff;
2756                 scsi_cmd->control = 0;
2757                 cdb_len = sizeof(*scsi_cmd);
2758
2759                 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE,
2760                           ("6byte: %x%x%x:%d:%d\n", scsi_cmd->addr[0],
2761                            scsi_cmd->addr[1], scsi_cmd->addr[2],
2762                            scsi_cmd->length, dxfer_len));
2763         } else if ((minimum_cmd_size < 12)
2764                 && ((block_count & 0xffff) == block_count)
2765                 && ((lba & 0xffffffffU) == lba)) {
2766                 /*
2767                  * Need a 10 byte cdb.
2768                  */
2769                 struct scsi_rw_10 *scsi_cmd;
2770
2771                 scsi_cmd = (struct scsi_rw_10 *)&csio->cdb_io.cdb_bytes;
2772                 scsi_cmd->opcode = readop ? READ_10 : WRITE_10;
2773                 scsi_cmd->byte2 = byte2;
2774                 scsi_ulto4b(lba, scsi_cmd->addr);
2775                 scsi_cmd->reserved = 0;
2776                 scsi_ulto2b(block_count, scsi_cmd->length);
2777                 scsi_cmd->control = 0;
2778                 cdb_len = sizeof(*scsi_cmd);
2779
2780                 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE,
2781                           ("10byte: %x%x%x%x:%x%x: %d\n", scsi_cmd->addr[0],
2782                            scsi_cmd->addr[1], scsi_cmd->addr[2],
2783                            scsi_cmd->addr[3], scsi_cmd->length[0],
2784                            scsi_cmd->length[1], dxfer_len));
2785         } else if ((minimum_cmd_size < 16)
2786                 && ((block_count & 0xffffffffU) == block_count)
2787                 && ((lba & 0xffffffffU) == lba)) {
2788                 /* 
2789                  * The block count is too big for a 10 byte CDB, use a 12
2790                  * byte CDB.
2791                  */
2792                 struct scsi_rw_12 *scsi_cmd;
2793
2794                 scsi_cmd = (struct scsi_rw_12 *)&csio->cdb_io.cdb_bytes;
2795                 scsi_cmd->opcode = readop ? READ_12 : WRITE_12;
2796                 scsi_cmd->byte2 = byte2;
2797                 scsi_ulto4b(lba, scsi_cmd->addr);
2798                 scsi_cmd->reserved = 0;
2799                 scsi_ulto4b(block_count, scsi_cmd->length);
2800                 scsi_cmd->control = 0;
2801                 cdb_len = sizeof(*scsi_cmd);
2802
2803                 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE,
2804                           ("12byte: %x%x%x%x:%x%x%x%x: %d\n", scsi_cmd->addr[0],
2805                            scsi_cmd->addr[1], scsi_cmd->addr[2],
2806                            scsi_cmd->addr[3], scsi_cmd->length[0],
2807                            scsi_cmd->length[1], scsi_cmd->length[2],
2808                            scsi_cmd->length[3], dxfer_len));
2809         } else {
2810                 /*
2811                  * 16 byte CDB.  We'll only get here if the LBA is larger
2812                  * than 2^32, or if the user asks for a 16 byte command.
2813                  */
2814                 struct scsi_rw_16 *scsi_cmd;
2815
2816                 scsi_cmd = (struct scsi_rw_16 *)&csio->cdb_io.cdb_bytes;
2817                 scsi_cmd->opcode = readop ? READ_16 : WRITE_16;
2818                 scsi_cmd->byte2 = byte2;
2819                 scsi_u64to8b(lba, scsi_cmd->addr);
2820                 scsi_cmd->reserved = 0;
2821                 scsi_ulto4b(block_count, scsi_cmd->length);
2822                 scsi_cmd->control = 0;
2823                 cdb_len = sizeof(*scsi_cmd);
2824         }
2825         cam_fill_csio(csio,
2826                       retries,
2827                       cbfcnp,
2828                       /*flags*/readop ? CAM_DIR_IN : CAM_DIR_OUT,
2829                       tag_action,
2830                       data_ptr,
2831                       dxfer_len,
2832                       sense_len,
2833                       cdb_len,
2834                       timeout);
2835 }
2836
2837 void 
2838 scsi_start_stop(struct ccb_scsiio *csio, u_int32_t retries,
2839                 void (*cbfcnp)(struct cam_periph *, union ccb *),
2840                 u_int8_t tag_action, int start, int load_eject,
2841                 int immediate, u_int8_t sense_len, u_int32_t timeout)
2842 {
2843         struct scsi_start_stop_unit *scsi_cmd;
2844         int extra_flags = 0;
2845
2846         scsi_cmd = (struct scsi_start_stop_unit *)&csio->cdb_io.cdb_bytes;
2847         bzero(scsi_cmd, sizeof(*scsi_cmd));
2848         scsi_cmd->opcode = START_STOP_UNIT;
2849         if (start != 0) {
2850                 scsi_cmd->how |= SSS_START;
2851                 /* it takes a lot of power to start a drive */
2852                 extra_flags |= CAM_HIGH_POWER;
2853         }
2854         if (load_eject != 0)
2855                 scsi_cmd->how |= SSS_LOEJ;
2856         if (immediate != 0)
2857                 scsi_cmd->byte2 |= SSS_IMMED;
2858
2859         cam_fill_csio(csio,
2860                       retries,
2861                       cbfcnp,
2862                       /*flags*/CAM_DIR_NONE | extra_flags,
2863                       tag_action,
2864                       /*data_ptr*/NULL,
2865                       /*dxfer_len*/0,
2866                       sense_len,
2867                       sizeof(*scsi_cmd),
2868                       timeout);
2869
2870 }
2871
2872 void
2873 scsi_log_sense(struct ccb_scsiio *csio, u_int32_t retries,
2874                void (*cbfcnp)(struct cam_periph *, union ccb *),
2875                u_int8_t tag_action, u_int8_t page_code, u_int8_t page,
2876                int save_pages, int ppc, u_int32_t paramptr,
2877                u_int8_t *param_buf, u_int32_t param_len, u_int8_t sense_len,
2878                u_int32_t timeout)
2879 {
2880         struct scsi_log_sense *scsi_cmd;
2881         u_int8_t cdb_len;
2882
2883         scsi_cmd = (struct scsi_log_sense *)&csio->cdb_io.cdb_bytes;
2884         bzero(scsi_cmd, sizeof(*scsi_cmd));
2885         scsi_cmd->opcode = LOG_SENSE;
2886         scsi_cmd->page = page_code | page;
2887         if (save_pages != 0)
2888                 scsi_cmd->byte2 |= SLS_SP;
2889         if (ppc != 0)
2890                 scsi_cmd->byte2 |= SLS_PPC;
2891         scsi_ulto2b(paramptr, scsi_cmd->paramptr);
2892         scsi_ulto2b(param_len, scsi_cmd->length);
2893         cdb_len = sizeof(*scsi_cmd);
2894
2895         cam_fill_csio(csio,
2896                       retries,
2897                       cbfcnp,
2898                       /*flags*/CAM_DIR_IN,
2899                       tag_action,
2900                       /*data_ptr*/param_buf,
2901                       /*dxfer_len*/param_len,
2902                       sense_len,
2903                       cdb_len,
2904                       timeout);
2905 }
2906
2907 void
2908 scsi_log_select(struct ccb_scsiio *csio, u_int32_t retries,
2909                 void (*cbfcnp)(struct cam_periph *, union ccb *),
2910                 u_int8_t tag_action, u_int8_t page_code, int save_pages,
2911                 int pc_reset, u_int8_t *param_buf, u_int32_t param_len,
2912                 u_int8_t sense_len, u_int32_t timeout)
2913 {
2914         struct scsi_log_select *scsi_cmd;
2915         u_int8_t cdb_len;
2916
2917         scsi_cmd = (struct scsi_log_select *)&csio->cdb_io.cdb_bytes;
2918         bzero(scsi_cmd, sizeof(*scsi_cmd));
2919         scsi_cmd->opcode = LOG_SELECT;
2920         scsi_cmd->page = page_code & SLS_PAGE_CODE;
2921         if (save_pages != 0)
2922                 scsi_cmd->byte2 |= SLS_SP;
2923         if (pc_reset != 0)
2924                 scsi_cmd->byte2 |= SLS_PCR;
2925         scsi_ulto2b(param_len, scsi_cmd->length);
2926         cdb_len = sizeof(*scsi_cmd);
2927
2928         cam_fill_csio(csio,
2929                       retries,
2930                       cbfcnp,
2931                       /*flags*/CAM_DIR_OUT,
2932                       tag_action,
2933                       /*data_ptr*/param_buf,
2934                       /*dxfer_len*/param_len,
2935                       sense_len,
2936                       cdb_len,
2937                       timeout);
2938 }
2939
2940 /*      
2941  * Try make as good a match as possible with
2942  * available sub drivers
2943  */
2944 int
2945 scsi_inquiry_match(caddr_t inqbuffer, caddr_t table_entry)
2946 {
2947         struct scsi_inquiry_pattern *entry;
2948         struct scsi_inquiry_data *inq;
2949  
2950         entry = (struct scsi_inquiry_pattern *)table_entry;
2951         inq = (struct scsi_inquiry_data *)inqbuffer;
2952
2953         if (((SID_TYPE(inq) == entry->type)
2954           || (entry->type == T_ANY))
2955          && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE
2956                                    : entry->media_type & SIP_MEDIA_FIXED)
2957          && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0)
2958          && (cam_strmatch(inq->product, entry->product,
2959                           sizeof(inq->product)) == 0)
2960          && (cam_strmatch(inq->revision, entry->revision,
2961                           sizeof(inq->revision)) == 0)) {
2962                 return (0);
2963         }
2964         return (-1);
2965 }
2966
2967 #ifdef _KERNEL
2968 static void
2969 init_scsi_delay(void)
2970 {
2971         int delay;
2972
2973         delay = SCSI_DELAY;
2974         TUNABLE_INT_FETCH("kern.cam.scsi_delay", &delay);
2975
2976         if (set_scsi_delay(delay) != 0) {
2977                 kprintf("cam: invalid value for tunable kern.cam.scsi_delay\n");
2978                 set_scsi_delay(SCSI_DELAY);
2979         }
2980 }
2981 SYSINIT(scsi_delay, SI_BOOT1_TUNABLES, SI_ORDER_ANY, init_scsi_delay, NULL);
2982
2983 static int
2984 sysctl_scsi_delay(SYSCTL_HANDLER_ARGS)
2985 {
2986         int error, delay;
2987
2988         delay = scsi_delay;
2989         error = sysctl_handle_int(oidp, &delay, sizeof(delay), req);
2990         if (error != 0 || req->newptr == NULL)
2991                 return (error);
2992         return (set_scsi_delay(delay));
2993 }
2994 SYSCTL_PROC(_kern_cam, OID_AUTO, scsi_delay, CTLTYPE_INT|CTLFLAG_RW,
2995     0, 0, sysctl_scsi_delay, "I",
2996     "Delay to allow devices to settle after a SCSI bus reset (ms)");
2997
2998 static int
2999 set_scsi_delay(int delay)
3000 {
3001         /*
3002          * If someone sets this to 0, we assume that they want the
3003          * minimum allowable bus settle delay.
3004          */
3005         if (delay == 0) {
3006                 kprintf("cam: using minimum scsi_delay (%dms)\n",
3007                     SCSI_MIN_DELAY);
3008                 delay = SCSI_MIN_DELAY;
3009         }
3010         if (delay < SCSI_MIN_DELAY)
3011                 return (EINVAL);
3012         scsi_delay = delay;
3013         return (0);
3014 }
3015 #endif /* _KERNEL */
3016
3017 /*      
3018  * Try make as good a match as possible with
3019  * available sub drivers
3020  */
3021 int
3022 scsi_static_inquiry_match(caddr_t inqbuffer, caddr_t table_entry)
3023 {
3024         struct scsi_static_inquiry_pattern *entry;
3025         struct scsi_inquiry_data *inq;
3026  
3027         entry = (struct scsi_static_inquiry_pattern *)table_entry;
3028         inq = (struct scsi_inquiry_data *)inqbuffer;
3029
3030         if (((SID_TYPE(inq) == entry->type)
3031           || (entry->type == T_ANY))
3032          && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE
3033                                    : entry->media_type & SIP_MEDIA_FIXED)
3034          && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0)
3035          && (cam_strmatch(inq->product, entry->product,
3036                           sizeof(inq->product)) == 0)
3037          && (cam_strmatch(inq->revision, entry->revision,
3038                           sizeof(inq->revision)) == 0)) {
3039                 return (0);
3040         }
3041         return (-1);
3042 }