The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/cam/scsi/scsi_all.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 73b2d81c0d1b0153e8a2dd243d2aa473


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.