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

Cache object: bf92a8fbf6fd9bfdf9a2e280d4e01516


[ 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.