root/scsi/scsi_base.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. scsi_init
  2. scsi_deinit
  3. scsi_get_xs
  4. scsi_free_xs
  5. scsi_make_xs
  6. scsi_size
  7. scsi_test_unit_ready
  8. scsi_inquire
  9. scsi_inquire_vpd
  10. scsi_prevent
  11. scsi_start
  12. scsi_mode_sense
  13. scsi_mode_sense_big
  14. scsi_mode_sense_page
  15. scsi_mode_sense_big_page
  16. scsi_do_mode_sense
  17. scsi_mode_select
  18. scsi_mode_select_big
  19. scsi_report_luns
  20. scsi_done
  21. scsi_execute_xs
  22. scsi_scsi_cmd
  23. sc_err1
  24. scsi_delay
  25. scsi_interpret_sense
  26. sc_print_addr
  27. asc2ascii
  28. asc2ascii
  29. scsi_print_sense
  30. scsi_decode_sense
  31. show_scsi_xs
  32. show_scsi_cmd
  33. show_mem

    1 /*      $OpenBSD: scsi_base.c,v 1.122 2007/06/23 19:19:49 krw Exp $     */
    2 /*      $NetBSD: scsi_base.c,v 1.43 1997/04/02 02:29:36 mycroft Exp $   */
    3 
    4 /*
    5  * Copyright (c) 1994, 1995, 1997 Charles M. Hannum.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *      This product includes software developed by Charles M. Hannum.
   18  * 4. The name of the author may not be used to endorse or promote products
   19  *    derived from this software without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 /*
   34  * Originally written by Julian Elischer (julian@dialix.oz.au)
   35  * Detailed SCSI error printing Copyright 1997 by Matthew Jacob.
   36  */
   37 
   38 #include <sys/types.h>
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/kernel.h>
   42 #include <sys/buf.h>
   43 #include <sys/uio.h>
   44 #include <sys/malloc.h>
   45 #include <sys/errno.h>
   46 #include <sys/device.h>
   47 #include <sys/proc.h>
   48 #include <sys/pool.h>
   49 
   50 #include <scsi/scsi_all.h>
   51 #include <scsi/scsi_disk.h>
   52 #include <scsi/scsiconf.h>
   53 
   54 static __inline struct scsi_xfer *scsi_make_xs(struct scsi_link *,
   55     struct scsi_generic *, int cmdlen, u_char *data_addr,
   56     int datalen, int retries, int timeout, struct buf *, int flags);
   57 static __inline void asc2ascii(u_int8_t, u_int8_t ascq, char *result,
   58     size_t len);
   59 int     sc_err1(struct scsi_xfer *);
   60 int     scsi_interpret_sense(struct scsi_xfer *);
   61 char   *scsi_decode_sense(struct scsi_sense_data *, int);
   62 
   63 /* Values for flag parameter to scsi_decode_sense. */
   64 #define DECODE_SENSE_KEY        1
   65 #define DECODE_ASC_ASCQ         2
   66 #define DECODE_SKSV             3
   67 
   68 int                     scsi_running = 0;
   69 struct pool             scsi_xfer_pool;
   70 
   71 /*
   72  * Called when a scsibus is attached to initialize global data.
   73  */
   74 void
   75 scsi_init()
   76 {
   77         if (scsi_running++)
   78                 return;
   79 
   80 #if defined(SCSI_DELAY) && SCSI_DELAY > 0
   81         /* Historical. Older buses may need a moment to stabilize. */
   82         delay(1000000 * SCSI_DELAY);
   83 #endif
   84 
   85         /* Initialize the scsi_xfer pool. */
   86         pool_init(&scsi_xfer_pool, sizeof(struct scsi_xfer), 0,
   87             0, 0, "scxspl", NULL);
   88 }
   89 
   90 void
   91 scsi_deinit()
   92 {
   93         if (--scsi_running)
   94                 return;
   95 }
   96 
   97 /*
   98  * Get a scsi transfer structure for the caller. Charge the structure
   99  * to the device that is referenced by the sc_link structure. If the
  100  * sc_link structure has no 'credits' then the device already has the
  101  * maximum number or outstanding operations under way. In this stage,
  102  * wait on the structure so that when one is freed, we are awoken again
  103  * If the SCSI_NOSLEEP flag is set, then do not wait, but rather, return
  104  * a NULL pointer, signifying that no slots were available
  105  * Note in the link structure, that we are waiting on it.
  106  */
  107 
  108 struct scsi_xfer *
  109 scsi_get_xs(struct scsi_link *sc_link, int flags)
  110 {
  111         struct scsi_xfer                *xs;
  112         int                             s;
  113 
  114         SC_DEBUG(sc_link, SDEV_DB3, ("scsi_get_xs\n"));
  115 
  116         s = splbio();
  117         while (sc_link->openings == 0) {
  118                 SC_DEBUG(sc_link, SDEV_DB3, ("sleeping\n"));
  119                 if ((flags & SCSI_NOSLEEP) != 0) {
  120                         splx(s);
  121                         return (NULL);
  122                 }
  123                 sc_link->flags |= SDEV_WAITING;
  124                 if (tsleep(sc_link, PRIBIO|PCATCH, "getxs", 0)) {
  125                         /* Bail out on getting a signal. */
  126                         sc_link->flags &= ~SDEV_WAITING;
  127                         splx(s);
  128                         return (NULL);
  129                 }
  130         }
  131         SC_DEBUG(sc_link, SDEV_DB3, ("calling pool_get\n"));
  132         xs = pool_get(&scsi_xfer_pool,
  133             ((flags & SCSI_NOSLEEP) != 0 ? PR_NOWAIT : PR_WAITOK));
  134         if (xs != NULL) {
  135                 bzero(xs, sizeof(*xs));
  136                 sc_link->openings--;
  137                 xs->flags = flags;
  138         } else {
  139                 sc_print_addr(sc_link);
  140                 printf("cannot allocate scsi xs\n");
  141         }
  142         splx(s);
  143 
  144         SC_DEBUG(sc_link, SDEV_DB3, ("returning\n"));
  145 
  146         return (xs);
  147 }
  148 
  149 /*
  150  * Given a scsi_xfer struct, and a device (referenced through sc_link)
  151  * return the struct to the free pool and credit the device with it
  152  * If another process is waiting for an xs, do a wakeup, let it proceed
  153  */
  154 void
  155 scsi_free_xs(struct scsi_xfer *xs, int start)
  156 {
  157         struct scsi_link *sc_link = xs->sc_link;
  158 
  159         splassert(IPL_BIO);
  160 
  161         SC_DEBUG(sc_link, SDEV_DB3, ("scsi_free_xs\n"));
  162 
  163         pool_put(&scsi_xfer_pool, xs);
  164         sc_link->openings++;
  165 
  166         /* If someone is waiting for scsi_xfer, wake them up. */
  167         if ((sc_link->flags & SDEV_WAITING) != 0) {
  168                 sc_link->flags &= ~SDEV_WAITING;
  169                 wakeup(sc_link);
  170         } else if (start && sc_link->device->start) {
  171                 SC_DEBUG(sc_link, SDEV_DB2,
  172                     ("calling private start()\n"));
  173                 (*(sc_link->device->start)) (sc_link->device_softc);
  174         }
  175 }
  176 
  177 /*
  178  * Make a scsi_xfer, and return a pointer to it.
  179  */
  180 static __inline struct scsi_xfer *
  181 scsi_make_xs(struct scsi_link *sc_link, struct scsi_generic *scsi_cmd,
  182     int cmdlen, u_char *data_addr, int datalen, int retries, int timeout,
  183     struct buf *bp, int flags)
  184 {
  185         struct scsi_xfer                *xs;
  186 
  187         if ((xs = scsi_get_xs(sc_link, flags)) == NULL)
  188                 return (NULL);
  189 
  190         /*
  191          * Fill out the scsi_xfer structure.  We don't know whose context
  192          * the cmd is in, so copy it.
  193          */
  194         xs->sc_link = sc_link;
  195         bcopy(scsi_cmd, &xs->cmdstore, cmdlen);
  196         xs->cmd = &xs->cmdstore;
  197         xs->cmdlen = cmdlen;
  198         xs->data = data_addr;
  199         xs->datalen = datalen;
  200         xs->retries = retries;
  201         xs->timeout = timeout;
  202         xs->bp = bp;
  203 
  204         /*
  205          * Set the LUN in the CDB if it fits in the three bits available. This
  206          * may only be needed if we have an older device.  However, we also set
  207          * it for more modern SCSI devices "just in case".  The old code
  208          * assumed everything newer than SCSI-2 would not need it, but why risk
  209          * it?  This was the old conditional:
  210          *
  211          * if ((SCSISPC(sc_link->inqdata.version) <= 2))
  212          */
  213         xs->cmd->bytes[0] &= ~SCSI_CMD_LUN_MASK;
  214         if (sc_link->lun < 8)
  215                 xs->cmd->bytes[0] |= ((sc_link->lun << SCSI_CMD_LUN_SHIFT) &
  216                     SCSI_CMD_LUN_MASK);
  217 
  218         return (xs);
  219 }
  220 
  221 /*
  222  * Find out from the device what its capacity is.
  223  */
  224 daddr64_t
  225 scsi_size(struct scsi_link *sc_link, int flags, u_int32_t *blksize)
  226 {
  227         struct scsi_read_cap_data_16 rdcap16;
  228         struct scsi_read_capacity_16 rc16;
  229         struct scsi_read_cap_data rdcap;
  230         struct scsi_read_capacity rc;
  231         daddr64_t max_addr;
  232         int error;
  233 
  234         if (blksize != NULL)
  235                 *blksize = 0;
  236 
  237         /*
  238          * make up a scsi command and ask the scsi driver to do it for you.
  239          */
  240         bzero(&rc, sizeof(rc));
  241         bzero(&rdcap, sizeof(rdcap));
  242         rc.opcode = READ_CAPACITY;
  243 
  244         /*
  245          * If the command works, interpret the result as a 4 byte
  246          * number of blocks
  247          */
  248         error = scsi_scsi_cmd(sc_link, (struct scsi_generic *)&rc, sizeof(rc),
  249             (u_char *)&rdcap, sizeof(rdcap), 2, 20000, NULL,
  250             flags | SCSI_DATA_IN);
  251         if (error) {
  252                 SC_DEBUG(sc_link, SDEV_DB1, ("READ CAPACITY error (%#x)\n",
  253                     error));
  254                 return (0);
  255         }
  256 
  257         max_addr = _4btol(rdcap.addr);
  258         if (blksize != NULL)
  259                 *blksize = _4btol(rdcap.length);
  260 
  261         if (max_addr != 0xffffffff)
  262                 return (max_addr + 1);
  263 
  264         /*
  265          * The device has more than 2^32-1 sectors. Use 16-byte READ CAPACITY.
  266          */
  267          bzero(&rc16, sizeof(rc16));
  268          bzero(&rdcap16, sizeof(rdcap16));
  269          rc16.opcode = READ_CAPACITY_16;
  270          rc16.byte2 = SRC16_SERVICE_ACTION;
  271          _lto4b(sizeof(rdcap16), rc16.length);
  272 
  273         error = scsi_scsi_cmd(sc_link, (struct scsi_generic *)&rc16,
  274             sizeof(rc16), (u_char *)&rdcap16, sizeof(rdcap16), 2, 20000, NULL,
  275             flags | SCSI_DATA_IN);
  276         if (error) {
  277                 SC_DEBUG(sc_link, SDEV_DB1, ("READ CAPACITY 16 error (%#x)\n",
  278                     error));
  279                 return (0);
  280         }
  281 
  282         max_addr = _8btol(rdcap16.addr);
  283         if (blksize != NULL)
  284                 *blksize = _4btol(rdcap16.length);
  285 
  286         return (max_addr + 1);
  287 }
  288 
  289 /*
  290  * Get scsi driver to send a "are you ready?" command
  291  */
  292 int
  293 scsi_test_unit_ready(struct scsi_link *sc_link, int retries, int flags)
  294 {
  295         struct scsi_test_unit_ready             scsi_cmd;
  296 
  297         if (sc_link->quirks & ADEV_NOTUR)
  298                 return (0);
  299 
  300         bzero(&scsi_cmd, sizeof(scsi_cmd));
  301         scsi_cmd.opcode = TEST_UNIT_READY;
  302 
  303         return (scsi_scsi_cmd(sc_link, (struct scsi_generic *) &scsi_cmd,
  304             sizeof(scsi_cmd), 0, 0, retries, 10000, NULL, flags));
  305 }
  306 
  307 /*
  308  * Do a scsi operation asking a device what it is.
  309  * Use the scsi_cmd routine in the switch table.
  310  */
  311 int
  312 scsi_inquire(struct scsi_link *sc_link, struct scsi_inquiry_data *inqbuf,
  313     int flags)
  314 {
  315         struct scsi_inquiry                     scsi_cmd;
  316         int                                     length;
  317         int                                     error;
  318 
  319         bzero(&scsi_cmd, sizeof(scsi_cmd));
  320         scsi_cmd.opcode = INQUIRY;
  321 
  322         bzero(inqbuf, sizeof(*inqbuf));
  323 
  324         memset(&inqbuf->vendor, ' ', sizeof inqbuf->vendor);
  325         memset(&inqbuf->product, ' ', sizeof inqbuf->product);
  326         memset(&inqbuf->revision, ' ', sizeof inqbuf->revision);
  327         memset(&inqbuf->extra, ' ', sizeof inqbuf->extra);
  328 
  329         /*
  330          * Ask for only the basic 36 bytes of SCSI2 inquiry information. This
  331          * avoids problems with devices that choke trying to supply more.
  332          */
  333         length = SID_INQUIRY_HDR + SID_SCSI2_ALEN;
  334         _lto2b(length, scsi_cmd.length);
  335         error = scsi_scsi_cmd(sc_link, (struct scsi_generic *)&scsi_cmd,
  336             sizeof(scsi_cmd), (u_char *)inqbuf, length, 2, 10000, NULL,
  337             SCSI_DATA_IN | flags);
  338 
  339         return (error);
  340 }
  341 
  342 /*
  343  * Query a VPD inquiry page
  344  */
  345 int
  346 scsi_inquire_vpd(struct scsi_link *sc_link, void *buf, u_int buflen,
  347     u_int8_t page, int flags)
  348 {
  349         struct scsi_inquiry scsi_cmd;
  350         int error;
  351 
  352         bzero(&scsi_cmd, sizeof(scsi_cmd));
  353         scsi_cmd.opcode = INQUIRY;
  354         scsi_cmd.flags = SI_EVPD;
  355         scsi_cmd.pagecode = page;
  356         _lto2b(buflen, scsi_cmd.length);
  357 
  358         bzero(buf, buflen);
  359 
  360         error = scsi_scsi_cmd(sc_link, (struct scsi_generic *)&scsi_cmd,
  361             sizeof(scsi_cmd), buf, buflen, 2, 10000, NULL,
  362             SCSI_DATA_IN | flags);
  363  
  364         return (error);
  365 }
  366 
  367 /*
  368  * Prevent or allow the user to remove the media
  369  */
  370 int
  371 scsi_prevent(struct scsi_link *sc_link, int type, int flags)
  372 {
  373         struct scsi_prevent                     scsi_cmd;
  374 
  375         if (sc_link->quirks & ADEV_NODOORLOCK)
  376                 return (0);
  377 
  378         bzero(&scsi_cmd, sizeof(scsi_cmd));
  379         scsi_cmd.opcode = PREVENT_ALLOW;
  380         scsi_cmd.how = type;
  381 
  382         return (scsi_scsi_cmd(sc_link, (struct scsi_generic *)&scsi_cmd,
  383             sizeof(scsi_cmd), 0, 0, 2, 5000, NULL, flags));
  384 }
  385 
  386 /*
  387  * Get scsi driver to send a "start up" command
  388  */
  389 int
  390 scsi_start(struct scsi_link *sc_link, int type, int flags)
  391 {
  392         struct scsi_start_stop                  scsi_cmd;
  393 
  394         bzero(&scsi_cmd, sizeof(scsi_cmd));
  395         scsi_cmd.opcode = START_STOP;
  396         scsi_cmd.byte2 = 0x00;
  397         scsi_cmd.how = type;
  398 
  399         return (scsi_scsi_cmd(sc_link, (struct scsi_generic *)&scsi_cmd,
  400             sizeof(scsi_cmd), 0, 0, 2,
  401             type == SSS_START ? 30000 : 10000, NULL, flags));
  402 }
  403 
  404 int
  405 scsi_mode_sense(struct scsi_link *sc_link, int byte2, int page,
  406     struct scsi_mode_header *data, size_t len, int flags, int timeout)
  407 {
  408         struct scsi_mode_sense                  scsi_cmd;
  409         int                                     error;
  410 
  411         /*
  412          * Make sure the sense buffer is clean before we do the mode sense, so
  413          * that checks for bogus values of 0 will work in case the mode sense
  414          * fails.
  415          */
  416         bzero(data, len);
  417 
  418         bzero(&scsi_cmd, sizeof(scsi_cmd));
  419         scsi_cmd.opcode = MODE_SENSE;
  420         scsi_cmd.byte2 = byte2;
  421         scsi_cmd.page = page;
  422 
  423         if (len > 0xff)
  424                 len = 0xff;
  425         scsi_cmd.length = len;
  426 
  427         error = scsi_scsi_cmd(sc_link, (struct scsi_generic *)&scsi_cmd,
  428             sizeof(scsi_cmd), (u_char *)data, len, 4, timeout, NULL,
  429             flags | SCSI_DATA_IN);
  430 
  431         SC_DEBUG(sc_link, SDEV_DB2, ("scsi_mode_sense: page %#x, error = %d\n",
  432             page, error));
  433 
  434         return (error);
  435 }
  436 
  437 int
  438 scsi_mode_sense_big(struct scsi_link *sc_link, int byte2, int page,
  439     struct scsi_mode_header_big *data, size_t len, int flags, int timeout)
  440 {
  441         struct scsi_mode_sense_big              scsi_cmd;
  442         int                                     error;
  443 
  444         /*
  445          * Make sure the sense buffer is clean before we do the mode sense, so
  446          * that checks for bogus values of 0 will work in case the mode sense
  447          * fails.
  448          */
  449         bzero(data, len);
  450 
  451         bzero(&scsi_cmd, sizeof(scsi_cmd));
  452         scsi_cmd.opcode = MODE_SENSE_BIG;
  453         scsi_cmd.byte2 = byte2;
  454         scsi_cmd.page = page;
  455 
  456         if (len > 0xffff)
  457                 len = 0xffff;
  458         _lto2b(len, scsi_cmd.length);
  459 
  460         error = scsi_scsi_cmd(sc_link, (struct scsi_generic *)&scsi_cmd,
  461             sizeof(scsi_cmd), (u_char *)data, len, 4, timeout, NULL,
  462             flags | SCSI_DATA_IN);
  463 
  464         SC_DEBUG(sc_link, SDEV_DB2,
  465             ("scsi_mode_sense_big: page %#x, error = %d\n", page, error));
  466 
  467         return (error);
  468 }
  469 
  470 void *
  471 scsi_mode_sense_page(struct scsi_mode_header *hdr, const int page_len)
  472 {
  473         int                                     total_length, header_length;
  474 
  475         total_length = hdr->data_length + sizeof(hdr->data_length);
  476         header_length = sizeof(*hdr) + hdr->blk_desc_len;
  477 
  478         if ((total_length - header_length) < page_len)
  479                 return (NULL);
  480 
  481         return ((u_char *)hdr + header_length);
  482 }
  483 
  484 void *
  485 scsi_mode_sense_big_page(struct scsi_mode_header_big *hdr, const int page_len)
  486 {
  487         int                                     total_length, header_length;
  488 
  489         total_length = _2btol(hdr->data_length) + sizeof(hdr->data_length);
  490         header_length = sizeof(*hdr) + _2btol(hdr->blk_desc_len);
  491 
  492         if ((total_length - header_length) < page_len)
  493                 return (NULL);
  494 
  495         return ((u_char *)hdr + header_length);
  496 }
  497 
  498 int
  499 scsi_do_mode_sense(struct scsi_link *sc_link, int page,
  500     union scsi_mode_sense_buf *buf, void **page_data, u_int32_t *density,
  501     u_int64_t *block_count, u_int32_t *block_size, int page_len, int flags,
  502     int *big)
  503 {
  504         struct scsi_direct_blk_desc             *direct;
  505         struct scsi_blk_desc                    *general;
  506         int                                     error, blk_desc_len, offset;
  507 
  508         *page_data = NULL;
  509 
  510         if (density != NULL)
  511                 *density = 0;
  512         if (block_count != NULL)
  513                 *block_count = 0;
  514         if (block_size != NULL)
  515                 *block_size = 0;
  516         if (big != NULL)
  517                 *big = 0;
  518 
  519         if ((sc_link->flags & SDEV_ATAPI) == 0 ||
  520             (sc_link->inqdata.device & SID_TYPE) == T_SEQUENTIAL) {
  521                 /*
  522                  * Try 6 byte mode sense request first. Some devices don't
  523                  * distinguish between 6 and 10 byte MODE SENSE commands,
  524                  * returning 6 byte data for 10 byte requests. ATAPI tape
  525                  * drives use MODE SENSE (6) even though ATAPI uses 10 byte
  526                  * everything else. Don't bother with SMS_DBD. Check returned
  527                  * data length to ensure that at least a header (3 additional
  528                  * bytes) is returned.
  529                  */
  530                 error = scsi_mode_sense(sc_link, 0, page, &buf->hdr,
  531                     sizeof(*buf), flags, 20000);
  532                 if (error == 0) {
  533                         *page_data = scsi_mode_sense_page(&buf->hdr, page_len);
  534                         if (*page_data == NULL) {
  535                                 /*
  536                                  * XXX
  537                                  * Page data may be invalid (e.g. all zeros)
  538                                  * but we accept the device's word that this is
  539                                  * the best it can do. Some devices will freak
  540                                  * out if their word is not accepted and 
  541                                  * MODE_SENSE_BIG is attempted.
  542                                  */
  543                                 return (0);
  544                         }
  545                         offset = sizeof(struct scsi_mode_header);
  546                         blk_desc_len = buf->hdr.blk_desc_len;
  547                         goto blk_desc;
  548                 }
  549         }
  550 
  551         /*
  552          * Try 10 byte mode sense request. Don't bother with SMS_DBD or
  553          * SMS_LLBAA. Bail out if the returned information is less than
  554          * a big header in size (6 additional bytes).
  555          */
  556         error = scsi_mode_sense_big(sc_link, 0, page, &buf->hdr_big,
  557             sizeof(*buf), flags, 20000);
  558         if (error != 0)
  559                 return (error);
  560         if (_2btol(buf->hdr_big.data_length) < 6)
  561                 return (EIO);
  562 
  563         if (big != NULL)
  564                 *big = 1;
  565         offset = sizeof(struct scsi_mode_header_big);
  566         *page_data = scsi_mode_sense_big_page(&buf->hdr_big, page_len);
  567         blk_desc_len = _2btol(buf->hdr_big.blk_desc_len);
  568 
  569 blk_desc:
  570         /* Both scsi_blk_desc and scsi_direct_blk_desc are 8 bytes. */
  571         if (blk_desc_len == 0 || (blk_desc_len % 8 != 0))
  572                 return (0);
  573 
  574         switch (sc_link->inqdata.device & SID_TYPE) {
  575         case T_SEQUENTIAL:
  576                 /*
  577                  * XXX What other device types return general block descriptors?
  578                  */
  579                 general = (struct scsi_blk_desc *)&buf->buf[offset];
  580                 if (density != NULL)
  581                         *density = general->density;
  582                 if (block_size != NULL)
  583                         *block_size = _3btol(general->blklen);
  584                 if (block_count != NULL)
  585                         *block_count = (u_int64_t)_3btol(general->nblocks);
  586                 break;
  587 
  588         default:
  589                 direct = (struct scsi_direct_blk_desc *)&buf->buf[offset];
  590                 if (density != NULL)
  591                         *density = direct->density;
  592                 if (block_size != NULL)
  593                         *block_size = _3btol(direct->blklen);
  594                 if (block_count != NULL)
  595                         *block_count = (u_int64_t)_4btol(direct->nblocks);
  596                 break;
  597         }
  598 
  599         return (0);
  600 }
  601 
  602 int
  603 scsi_mode_select(struct scsi_link *sc_link, int byte2,
  604     struct scsi_mode_header *data, int flags, int timeout)
  605 {
  606         struct scsi_mode_select                 scsi_cmd;
  607         int                                     error;
  608 
  609         bzero(&scsi_cmd, sizeof(scsi_cmd));
  610         scsi_cmd.opcode = MODE_SELECT;
  611         scsi_cmd.byte2 = byte2;
  612         scsi_cmd.length = data->data_length + 1; /* 1 == sizeof(data_length) */
  613 
  614         /* Length is reserved when doing mode select so zero it. */
  615         data->data_length = 0;
  616 
  617         error = scsi_scsi_cmd(sc_link, (struct scsi_generic *)&scsi_cmd,
  618             sizeof(scsi_cmd), (u_char *)data, scsi_cmd.length, 4, timeout, NULL,
  619             flags | SCSI_DATA_OUT);
  620 
  621         SC_DEBUG(sc_link, SDEV_DB2, ("scsi_mode_select: error = %d\n", error));
  622 
  623         return (error);
  624 }
  625 
  626 int
  627 scsi_mode_select_big(struct scsi_link *sc_link, int byte2,
  628     struct scsi_mode_header_big *data, int flags, int timeout)
  629 {
  630         struct scsi_mode_select_big             scsi_cmd;
  631         u_int32_t                               len;
  632         int                                     error;
  633 
  634         len = _2btol(data->data_length) + 2; /* 2 == sizeof data->data_length */
  635 
  636         bzero(&scsi_cmd, sizeof(scsi_cmd));
  637         scsi_cmd.opcode = MODE_SELECT_BIG;
  638         scsi_cmd.byte2 = byte2;
  639         _lto2b(len, scsi_cmd.length);
  640 
  641         /* Length is reserved when doing mode select so zero it. */
  642         _lto2b(0, data->data_length);
  643 
  644         error = scsi_scsi_cmd(sc_link, (struct scsi_generic *)&scsi_cmd,
  645             sizeof(scsi_cmd), (u_char *)data, len, 4, timeout, NULL,
  646             flags | SCSI_DATA_OUT);
  647 
  648         SC_DEBUG(sc_link, SDEV_DB2, ("scsi_mode_select_big: error = %d\n",
  649             error));
  650 
  651         return (error);
  652 }
  653 
  654 int
  655 scsi_report_luns(struct scsi_link *sc_link, int selectreport,
  656     struct scsi_report_luns_data *data, u_int32_t datalen, int flags,
  657     int timeout)
  658 {
  659         struct scsi_report_luns scsi_cmd;
  660         int error;
  661 
  662         bzero(&scsi_cmd, sizeof(scsi_cmd));
  663         bzero(data, datalen);
  664 
  665         scsi_cmd.opcode = REPORT_LUNS;
  666         scsi_cmd.selectreport = selectreport;
  667         _lto4b(datalen, scsi_cmd.length);
  668 
  669         error = scsi_scsi_cmd(sc_link, (struct scsi_generic *)&scsi_cmd,
  670             sizeof(scsi_cmd), (u_char *)data, datalen, 4, timeout, NULL,
  671             flags | SCSI_DATA_IN);
  672 
  673         SC_DEBUG(sc_link, SDEV_DB2, ("scsi_report_luns: error = %d\n", error));
  674 
  675         return (error);
  676 }
  677 
  678 /*
  679  * This routine is called by the scsi interrupt when the transfer is complete.
  680  */
  681 void
  682 scsi_done(struct scsi_xfer *xs)
  683 {
  684         struct scsi_link                        *sc_link = xs->sc_link;
  685         struct buf                              *bp;
  686         int                                     error;
  687 
  688         splassert(IPL_BIO);
  689 
  690         SC_DEBUG(sc_link, SDEV_DB2, ("scsi_done\n"));
  691 #ifdef  SCSIDEBUG
  692         if ((sc_link->flags & SDEV_DB1) != 0)
  693                 show_scsi_cmd(xs);
  694 #endif /* SCSIDEBUG */
  695 
  696         /*
  697          * If it's a user level request, bypass all usual completion processing,
  698          * let the user work it out.. We take reponsibility for freeing the
  699          * xs when the user returns (and restarting the device's queue).
  700          */
  701         if ((xs->flags & SCSI_USER) != 0) {
  702                 SC_DEBUG(sc_link, SDEV_DB3, ("calling user done()\n"));
  703                 scsi_user_done(xs); /* to take a copy of the sense etc. */
  704                 SC_DEBUG(sc_link, SDEV_DB3, ("returned from user done()\n"));
  705 
  706                 scsi_free_xs(xs, 1); /* restarts queue too */
  707                 SC_DEBUG(sc_link, SDEV_DB3, ("returning to adapter\n"));
  708                 return;
  709         }
  710 
  711         if (!((xs->flags & (SCSI_NOSLEEP | SCSI_POLL)) == SCSI_NOSLEEP)) {
  712                 /*
  713                  * if it's a normal upper level request, then ask
  714                  * the upper level code to handle error checking
  715                  * rather than doing it here at interrupt time
  716                  */
  717                 wakeup(xs);
  718                 return;
  719         }
  720 
  721         /*
  722          * Go and handle errors now.
  723          * If it returns ERESTART then we should RETRY
  724          */
  725 retry:
  726         error = sc_err1(xs);
  727         if (error == ERESTART) {
  728                 switch ((*(sc_link->adapter->scsi_cmd)) (xs)) {
  729                 case SUCCESSFULLY_QUEUED:
  730                         return;
  731 
  732                 case TRY_AGAIN_LATER:
  733                         xs->error = XS_BUSY;
  734                         /* FALLTHROUGH */
  735                 case COMPLETE:
  736                         goto retry;
  737                 }
  738         }
  739 
  740         bp = xs->bp;
  741         if (bp != NULL) {
  742                 if (error) {
  743                         bp->b_error = error;
  744                         bp->b_flags |= B_ERROR;
  745                         bp->b_resid = bp->b_bcount;
  746                 } else {
  747                         bp->b_error = 0;
  748                         bp->b_resid = xs->resid;
  749                 }
  750         }
  751 
  752         if (sc_link->device->done) {
  753                 /*
  754                  * Tell the device the operation is actually complete.
  755                  * No more will happen with this xfer.  This for
  756                  * notification of the upper-level driver only; they
  757                  * won't be returning any meaningful information to us.
  758                  */
  759                 (*sc_link->device->done)(xs);
  760         }
  761         scsi_free_xs(xs, 1);
  762         if (bp != NULL)
  763                 biodone(bp);
  764 }
  765 
  766 int
  767 scsi_execute_xs(struct scsi_xfer *xs)
  768 {
  769         int                                     error, flags, rslt, s;
  770 
  771         xs->flags &= ~ITSDONE;
  772         xs->error = XS_NOERROR;
  773         xs->resid = xs->datalen;
  774         xs->status = 0;
  775 
  776         /*
  777          * Do the transfer. If we are polling we will return:
  778          * COMPLETE,  Was poll, and scsi_done has been called
  779          * TRY_AGAIN_LATER, Adapter short resources, try again
  780          *
  781          * if under full steam (interrupts) it will return:
  782          * SUCCESSFULLY_QUEUED, will do a wakeup when complete
  783          * TRY_AGAIN_LATER, (as for polling)
  784          * After the wakeup, we must still check if it succeeded
  785          *
  786          * If we have a SCSI_NOSLEEP (typically because we have a buf)
  787          * we just return.  All the error processing and the buffer
  788          * code both expect us to return straight to them, so as soon
  789          * as the command is queued, return.
  790          */
  791 
  792         /*
  793          * We save the flags here because the xs structure may already
  794          * be freed by scsi_done by the time adapter->scsi_cmd returns.
  795          *
  796          * scsi_done is responsible for freeing the xs if either
  797          * (flags & (SCSI_NOSLEEP | SCSI_POLL)) == SCSI_NOSLEEP
  798          * -or-
  799          * (flags & SCSI_USER) != 0
  800          *
  801          * Note: SCSI_USER must always be called with SCSI_NOSLEEP
  802          * and never with SCSI_POLL, so the second expression should be
  803          * is equivalent to the first.
  804          */
  805 
  806         flags = xs->flags;
  807 #ifdef DIAGNOSTIC
  808         if ((flags & (SCSI_USER | SCSI_NOSLEEP)) == SCSI_USER)
  809                 panic("scsi_execute_xs: USER without NOSLEEP");
  810         if ((flags & (SCSI_USER | SCSI_POLL)) == (SCSI_USER | SCSI_POLL))
  811                 panic("scsi_execute_xs: USER with POLL");
  812 #endif
  813 retry:
  814         rslt = (*(xs->sc_link->adapter->scsi_cmd))(xs);
  815         switch (rslt) {
  816         case SUCCESSFULLY_QUEUED:
  817                 if ((flags & (SCSI_NOSLEEP | SCSI_POLL)) == SCSI_NOSLEEP)
  818                         return (EJUSTRETURN);
  819 #ifdef DIAGNOSTIC
  820                 if (flags & SCSI_NOSLEEP)
  821                         panic("scsi_execute_xs: NOSLEEP and POLL");
  822 #endif
  823                 s = splbio();
  824                 /* Since the xs is active we can't bail out on a signal. */
  825                 while ((xs->flags & ITSDONE) == 0)
  826                         tsleep(xs, PRIBIO + 1, "scsicmd", 0);
  827                 splx(s);
  828                 /* FALLTHROUGH */
  829         case COMPLETE:          /* Polling command completed ok */
  830                 if ((flags & (SCSI_NOSLEEP | SCSI_POLL)) == SCSI_NOSLEEP)
  831                         return (EJUSTRETURN);
  832                 if (xs->bp)
  833                         return (EJUSTRETURN);
  834         doit:
  835                 SC_DEBUG(xs->sc_link, SDEV_DB3, ("back in cmd()\n"));
  836                 if ((error = sc_err1(xs)) != ERESTART)
  837                         return (error);
  838                 goto retry;
  839 
  840         case TRY_AGAIN_LATER:   /* adapter resource shortage */
  841                 xs->error = XS_BUSY;
  842                 goto doit;
  843 
  844         case NO_CCB:
  845                 return (EAGAIN);
  846 
  847         default:
  848                 panic("scsi_execute_xs: invalid return code (%#x)", rslt);
  849         }
  850 
  851 #ifdef DIAGNOSTIC
  852         panic("scsi_execute_xs: impossible");
  853 #endif
  854         return (EINVAL);
  855 }
  856 
  857 /*
  858  * ask the scsi driver to perform a command for us.
  859  * tell it where to read/write the data, and how
  860  * long the data is supposed to be. If we have  a buf
  861  * to associate with the transfer, we need that too.
  862  */
  863 int
  864 scsi_scsi_cmd(struct scsi_link *sc_link, struct scsi_generic *scsi_cmd,
  865     int cmdlen, u_char *data_addr, int datalen, int retries, int timeout,
  866     struct buf *bp, int flags)
  867 {
  868         struct scsi_xfer                        *xs;
  869         int                                     error;
  870         int                                     s;
  871 
  872         SC_DEBUG(sc_link, SDEV_DB2, ("scsi_cmd\n"));
  873 
  874 #ifdef DIAGNOSTIC
  875         if (bp != NULL && (flags & SCSI_NOSLEEP) == 0)
  876                 panic("scsi_scsi_cmd: buffer without nosleep");
  877 #endif
  878 
  879         if ((xs = scsi_make_xs(sc_link, scsi_cmd, cmdlen, data_addr, datalen,
  880             retries, timeout, bp, flags)) == NULL)
  881                 return (ENOMEM);
  882 
  883         if ((error = scsi_execute_xs(xs)) == EJUSTRETURN)
  884                 return (0);
  885 
  886         s = splbio();
  887 
  888         if (error == EAGAIN)
  889                 scsi_free_xs(xs, 0); /* Don't restart queue. */
  890         else
  891                 scsi_free_xs(xs, 1);
  892 
  893         splx(s);
  894 
  895         return (error);
  896 }
  897 
  898 int
  899 sc_err1(struct scsi_xfer *xs)
  900 {
  901         int                                     error;
  902 
  903         SC_DEBUG(xs->sc_link, SDEV_DB3, ("sc_err1,err = 0x%x\n", xs->error));
  904 
  905         /*
  906          * If it has a buf, we might be working with
  907          * a request from the buffer cache or some other
  908          * piece of code that requires us to process
  909          * errors at interrupt time. We have probably
  910          * been called by scsi_done()
  911          */
  912         switch (xs->error) {
  913         case XS_NOERROR:        /* nearly always hit this one */
  914                 error = 0;
  915                 break;
  916 
  917         case XS_SENSE:
  918         case XS_SHORTSENSE:
  919                 if ((error = scsi_interpret_sense(xs)) == ERESTART)
  920                         goto retry;
  921                 SC_DEBUG(xs->sc_link, SDEV_DB3,
  922                     ("scsi_interpret_sense returned %#x\n", error));
  923                 break;
  924 
  925         case XS_BUSY:
  926                 if (xs->retries) {
  927                         if ((error = scsi_delay(xs, 1)) == EIO)
  928                                 goto lose;
  929                 }
  930                 /* FALLTHROUGH */
  931         case XS_TIMEOUT:
  932         retry:
  933                 if (xs->retries--) {
  934                         xs->error = XS_NOERROR;
  935                         xs->flags &= ~ITSDONE;
  936                         return ERESTART;
  937                 }
  938                 /* FALLTHROUGH */
  939         case XS_DRIVER_STUFFUP:
  940         lose:
  941                 error = EIO;
  942                 break;
  943 
  944         case XS_SELTIMEOUT:
  945                 /* XXX Disable device? */
  946                 error = EIO;
  947                 break;
  948 
  949         case XS_RESET:
  950                 if (xs->retries) {
  951                         SC_DEBUG(xs->sc_link, SDEV_DB3,
  952                             ("restarting command destroyed by reset\n"));
  953                         goto retry;
  954                 }
  955                 error = EIO;
  956                 break;
  957 
  958         default:
  959                 sc_print_addr(xs->sc_link);
  960                 printf("unknown error category (0x%x) from scsi driver\n",
  961                     xs->error);
  962                 error = EIO;
  963                 break;
  964         }
  965 
  966         return (error);
  967 }
  968 
  969 int
  970 scsi_delay(struct scsi_xfer *xs, int seconds)
  971 {
  972         switch (xs->flags & (SCSI_POLL | SCSI_NOSLEEP)) {
  973         case SCSI_POLL:
  974                 delay(1000000 * seconds);
  975                 return (ERESTART);
  976         case SCSI_NOSLEEP:
  977                 /* Retry the command immediately since we can't delay. */
  978                 return (ERESTART);
  979         case (SCSI_POLL | SCSI_NOSLEEP):
  980                 /* Invalid combination! */
  981                 return (EIO);
  982         }
  983 
  984         while (seconds-- > 0) {
  985                 if (tsleep(&lbolt, PRIBIO|PCATCH, "scbusy", 0)) {
  986                         /* Signal == abort xs. */
  987                         return (EIO);
  988                 }
  989         }
  990 
  991         return (ERESTART);
  992 }
  993 
  994 /*
  995  * Look at the returned sense and act on the error, determining
  996  * the unix error number to pass back.  (0 = report no error)
  997  *
  998  * THIS IS THE DEFAULT ERROR HANDLER
  999  */
 1000 int
 1001 scsi_interpret_sense(struct scsi_xfer *xs)
 1002 {
 1003         struct scsi_sense_data                  *sense = &xs->sense;
 1004         struct scsi_link                        *sc_link = xs->sc_link;
 1005         u_int8_t                                serr, skey;
 1006         int                                     error;
 1007 
 1008         SC_DEBUG(sc_link, SDEV_DB1,
 1009             ("code:%#x valid:%d key:%#x ili:%d eom:%d fmark:%d extra:%d\n",
 1010             sense->error_code & SSD_ERRCODE,
 1011             sense->error_code & SSD_ERRCODE_VALID ? 1 : 0,
 1012             sense->flags & SSD_KEY,
 1013             sense->flags & SSD_ILI ? 1 : 0,
 1014             sense->flags & SSD_EOM ? 1 : 0,
 1015             sense->flags & SSD_FILEMARK ? 1 : 0,
 1016             sense->extra_len));
 1017 #ifdef  SCSIDEBUG
 1018         if ((sc_link->flags & SDEV_DB1) != 0)
 1019                 show_mem((u_char *)&xs->sense, sizeof xs->sense);
 1020 #endif  /* SCSIDEBUG */
 1021 
 1022         /*
 1023          * If the device has its own error handler, call it first.
 1024          * If it returns a legit error value, return that, otherwise
 1025          * it wants us to continue with normal error processing.
 1026          */
 1027         if (sc_link->device->err_handler) {
 1028                 SC_DEBUG(sc_link, SDEV_DB2,
 1029                     ("calling private err_handler()\n"));
 1030                 error = (*sc_link->device->err_handler) (xs);
 1031                 if (error != EJUSTRETURN)
 1032                         return (error); /* error >= 0  better ? */
 1033         }
 1034 
 1035         /* Default sense interpretation. */
 1036         serr = sense->error_code & SSD_ERRCODE;
 1037         if (serr != SSD_ERRCODE_CURRENT && serr != SSD_ERRCODE_DEFERRED)
 1038                 skey = 0xff;    /* Invalid value, since key is 4 bit value. */
 1039         else
 1040                 skey = sense->flags & SSD_KEY;
 1041 
 1042         /*
 1043          * Interpret the key/asc/ascq information where appropriate.
 1044          */
 1045         error = 0;
 1046         switch (skey) {
 1047         case SKEY_NO_SENSE:
 1048         case SKEY_RECOVERED_ERROR:
 1049                 if (xs->resid == xs->datalen)
 1050                         xs->resid = 0;  /* not short read */
 1051                 break;
 1052         case SKEY_BLANK_CHECK:
 1053         case SKEY_EQUAL:
 1054                 break;
 1055         case SKEY_NOT_READY:
 1056                 if ((xs->flags & SCSI_IGNORE_NOT_READY) != 0)
 1057                         return (0);
 1058                 error = EIO;
 1059                 if (xs->retries) {
 1060                         switch (ASC_ASCQ(sense)) {
 1061                         case SENSE_NOT_READY_BECOMING_READY:
 1062                         case SENSE_NOT_READY_FORMAT:
 1063                         case SENSE_NOT_READY_REBUILD:
 1064                         case SENSE_NOT_READY_RECALC:            
 1065                         case SENSE_NOT_READY_INPROGRESS:
 1066                         case SENSE_NOT_READY_LONGWRITE:
 1067                         case SENSE_NOT_READY_SELFTEST:
 1068                                 SC_DEBUG(sc_link, SDEV_DB1,
 1069                                     ("not ready: busy (%#x)\n",
 1070                                     sense->add_sense_code_qual));
 1071                                 return (scsi_delay(xs, 1));
 1072                         case SENSE_NOMEDIUM:
 1073                         case SENSE_NOMEDIUM_TCLOSED:
 1074                         case SENSE_NOMEDIUM_TOPEN:
 1075                         case SENSE_NOMEDIUM_LOADABLE:
 1076                         case SENSE_NOMEDIUM_AUXMEM:
 1077                                 sc_link->flags &= ~SDEV_MEDIA_LOADED;
 1078                                 error = ENOMEDIUM;
 1079                                 break;
 1080                         default:
 1081                                 break;
 1082                         }
 1083                 }
 1084                 break;
 1085         case SKEY_MEDIUM_ERROR:
 1086                 switch (ASC_ASCQ(sense)) {
 1087                 case SENSE_NOMEDIUM:
 1088                 case SENSE_NOMEDIUM_TCLOSED:
 1089                 case SENSE_NOMEDIUM_TOPEN:
 1090                 case SENSE_NOMEDIUM_LOADABLE:
 1091                 case SENSE_NOMEDIUM_AUXMEM:
 1092                         sc_link->flags &= ~SDEV_MEDIA_LOADED;
 1093                         error = ENOMEDIUM;
 1094                         break;
 1095                 case SENSE_BAD_MEDIUM:
 1096                 case SENSE_NR_MEDIUM_UNKNOWN_FORMAT:
 1097                 case SENSE_NR_MEDIUM_INCOMPATIBLE_FORMAT:
 1098                 case SENSE_NW_MEDIUM_UNKNOWN_FORMAT:
 1099                 case SENSE_NW_MEDIUM_INCOMPATIBLE_FORMAT:
 1100                 case SENSE_NF_MEDIUM_INCOMPATIBLE_FORMAT:
 1101                 case SENSE_NW_MEDIUM_AC_MISMATCH:
 1102                         error = EMEDIUMTYPE;
 1103                         break;
 1104                 default:
 1105                         error = EIO;
 1106                         break;
 1107                 }
 1108                 break;
 1109         case SKEY_ILLEGAL_REQUEST:
 1110                 if ((xs->flags & SCSI_IGNORE_ILLEGAL_REQUEST) != 0)
 1111                         return (0);
 1112                 if (ASC_ASCQ(sense) == SENSE_MEDIUM_REMOVAL_PREVENTED)
 1113                         return(EBUSY);
 1114                 error = EINVAL;
 1115                 break;
 1116         case SKEY_UNIT_ATTENTION:
 1117                 switch (ASC_ASCQ(sense)) {
 1118                 case SENSE_POWER_RESET_OR_BUS:
 1119                 case SENSE_POWER_ON:
 1120                 case SENSE_BUS_RESET:
 1121                 case SENSE_BUS_DEVICE_RESET:
 1122                 case SENSE_DEVICE_INTERNAL_RESET:
 1123                 case SENSE_TSC_CHANGE_SE:
 1124                 case SENSE_TSC_CHANGE_LVD:
 1125                 case SENSE_IT_NEXUS_LOSS:
 1126                         return (scsi_delay(xs, 1));
 1127                 default:
 1128                         break;
 1129                 }
 1130                 if ((sc_link->flags & SDEV_REMOVABLE) != 0)
 1131                         sc_link->flags &= ~SDEV_MEDIA_LOADED;
 1132                 if ((xs->flags & SCSI_IGNORE_MEDIA_CHANGE) != 0 ||
 1133                     /* XXX Should reupload any transient state. */
 1134                     (sc_link->flags & SDEV_REMOVABLE) == 0) {
 1135                         return (scsi_delay(xs, 1));
 1136                 }
 1137                 error = EIO;
 1138                 break;
 1139         case SKEY_WRITE_PROTECT:
 1140                 error = EROFS;
 1141                 break;
 1142         case SKEY_ABORTED_COMMAND:
 1143                 error = ERESTART;
 1144                 break;
 1145         case SKEY_VOLUME_OVERFLOW:
 1146                 error = ENOSPC;
 1147                 break;
 1148         case SKEY_HARDWARE_ERROR:
 1149                 if (ASC_ASCQ(sense) == SENSE_CARTRIDGE_FAULT)
 1150                         return(EMEDIUMTYPE);
 1151                 error = EIO;
 1152                 break;
 1153         default:
 1154                 error = EIO;
 1155                 break;
 1156         }
 1157 
 1158         if (skey && (xs->flags & SCSI_SILENT) == 0)
 1159                 scsi_print_sense(xs);
 1160 
 1161         return (error);
 1162 }
 1163 
 1164 /*
 1165  * Utility routines often used in SCSI stuff
 1166  */
 1167 
 1168 
 1169 /*
 1170  * Print out the scsi_link structure's address info.
 1171  */
 1172 void
 1173 sc_print_addr(struct scsi_link *sc_link)
 1174 {
 1175         printf("%s(%s:%d:%d): ",
 1176             sc_link->device_softc ?
 1177             ((struct device *)sc_link->device_softc)->dv_xname : "probe",
 1178             ((struct device *)sc_link->adapter_softc)->dv_xname,
 1179             sc_link->target, sc_link->lun);
 1180 }
 1181 
 1182 static const char *sense_keys[16] = {
 1183         "No Additional Sense",
 1184         "Soft Error",
 1185         "Not Ready",
 1186         "Media Error",
 1187         "Hardware Error",
 1188         "Illegal Request",
 1189         "Unit Attention",
 1190         "Write Protected",
 1191         "Blank Check",
 1192         "Vendor Unique",
 1193         "Copy Aborted",
 1194         "Aborted Command",
 1195         "Equal Error",
 1196         "Volume Overflow",
 1197         "Miscompare Error",
 1198         "Reserved"
 1199 };
 1200 
 1201 #ifdef SCSITERSE
 1202 static __inline void
 1203 asc2ascii(u_int8_t asc, u_int8_t ascq, char *result, size_t len)
 1204 {
 1205         snprintf(result, len, "ASC 0x%02x ASCQ 0x%02x", asc, ascq);
 1206 }
 1207 #else
 1208 static const struct {
 1209         u_int8_t asc, ascq;
 1210         char *description;
 1211 } adesc[] = {
 1212         { 0x00, 0x00, "No Additional Sense Information" },
 1213         { 0x00, 0x01, "Filemark Detected" },
 1214         { 0x00, 0x02, "End-Of-Partition/Medium Detected" },
 1215         { 0x00, 0x03, "Setmark Detected" },
 1216         { 0x00, 0x04, "Beginning-Of-Partition/Medium Detected" },
 1217         { 0x00, 0x05, "End-Of-Data Detected" },
 1218         { 0x00, 0x06, "I/O Process Terminated" },
 1219         { 0x00, 0x11, "Audio Play Operation In Progress" },
 1220         { 0x00, 0x12, "Audio Play Operation Paused" },
 1221         { 0x00, 0x13, "Audio Play Operation Successfully Completed" },
 1222         { 0x00, 0x14, "Audio Play Operation Stopped Due to Error" },
 1223         { 0x00, 0x15, "No Current Audio Status To Return" },
 1224         { 0x00, 0x16, "Operation In Progress" },
 1225         { 0x00, 0x17, "Cleaning Requested" },
 1226         { 0x00, 0x18, "Erase Operation In Progress" },
 1227         { 0x00, 0x19, "Locate Operation In Progress" },
 1228         { 0x00, 0x1A, "Rewind Operation In Progress" },
 1229         { 0x00, 0x1B, "Set Capacity Operation In Progress" },
 1230         { 0x00, 0x1C, "Verify Operation In Progress" },
 1231         { 0x01, 0x00, "No Index/Sector Signal" },
 1232         { 0x02, 0x00, "No Seek Complete" },
 1233         { 0x03, 0x00, "Peripheral Device Write Fault" },
 1234         { 0x03, 0x01, "No Write Current" },
 1235         { 0x03, 0x02, "Excessive Write Errors" },
 1236         { 0x04, 0x00, "Logical Unit Not Ready, Cause Not Reportable" },
 1237         { 0x04, 0x01, "Logical Unit Is in Process Of Becoming Ready" },
 1238         { 0x04, 0x02, "Logical Unit Not Ready, Initialization Command Required" },
 1239         { 0x04, 0x03, "Logical Unit Not Ready, Manual Intervention Required" },
 1240         { 0x04, 0x04, "Logical Unit Not Ready, Format In Progress" },
 1241         { 0x04, 0x05, "Logical Unit Not Ready, Rebuild In Progress" },
 1242         { 0x04, 0x06, "Logical Unit Not Ready, Recalculation In Progress" },
 1243         { 0x04, 0x07, "Logical Unit Not Ready, Operation In Progress" },
 1244         { 0x04, 0x08, "Logical Unit Not Ready, Long Write In Progress" },
 1245         { 0x04, 0x09, "Logical Unit Not Ready, Self-Test In Progress" },
 1246         { 0x04, 0x0A, "Logical Unit Not Accessible, Asymmetric Access State Transition" },
 1247         { 0x04, 0x0B, "Logical Unit Not Accessible, Target Port In Standby State" },
 1248         { 0x04, 0x0C, "Logical Unit Not Accessible, Target Port In Unavailable State" },
 1249         { 0x04, 0x10, "Logical Unit Not Ready, Auxiliary Memory Not Accessible" },
 1250         { 0x04, 0x11, "Logical Unit Not Ready, Notify (Enable Spinup) Required" },
 1251         { 0x05, 0x00, "Logical Unit Does Not Respond To Selection" },
 1252         { 0x06, 0x00, "No Reference Position Found" },
 1253         { 0x07, 0x00, "Multiple Peripheral Devices Selected" },
 1254         { 0x08, 0x00, "Logical Unit Communication Failure" },
 1255         { 0x08, 0x01, "Logical Unit Communication Timeout" },
 1256         { 0x08, 0x02, "Logical Unit Communication Parity Error" },
 1257         { 0x08, 0x03, "Logical Unit Communication CRC Error (ULTRA-DMA/32)" },
 1258         { 0x08, 0x04, "Unreachable Copy Target" },
 1259         { 0x09, 0x00, "Track Following Error" },
 1260         { 0x09, 0x01, "Tracking Servo Failure" },
 1261         { 0x09, 0x02, "Focus Servo Failure" },
 1262         { 0x09, 0x03, "Spindle Servo Failure" },
 1263         { 0x09, 0x04, "Head Select Fault" },
 1264         { 0x0A, 0x00, "Error Log Overflow" },
 1265         { 0x0B, 0x00, "Warning" },
 1266         { 0x0B, 0x01, "Warning - Specified Temperature Exceeded" },
 1267         { 0x0B, 0x02, "Warning - Enclosure Degraded" },
 1268         { 0x0C, 0x00, "Write Error" },
 1269         { 0x0C, 0x01, "Write Error Recovered with Auto Reallocation" },
 1270         { 0x0C, 0x02, "Write Error - Auto Reallocate Failed" },
 1271         { 0x0C, 0x03, "Write Error - Recommend Reassignment" },
 1272         { 0x0C, 0x04, "Compression Check Miscompare Error" },
 1273         { 0x0C, 0x05, "Data Expansion Occurred During Compression" },
 1274         { 0x0C, 0x06, "Block Not Compressible" },
 1275         { 0x0C, 0x07, "Write Error - Recovery Needed" },
 1276         { 0x0C, 0x08, "Write Error - Recovery Failed" },
 1277         { 0x0C, 0x09, "Write Error - Loss Of Streaming" },
 1278         { 0x0C, 0x0A, "Write Error - Padding Blocks Added" },
 1279         { 0x0C, 0x0B, "Auxiliary Memory Write Error" },
 1280         { 0x0C, 0x0C, "Write Error - Unexpected Unsolicited Data" },
 1281         { 0x0C, 0x0D, "Write Error - Not Enough Unsolicited Data" },
 1282         { 0x0D, 0x00, "Error Detected By Third Party Temporary Initiator" },
 1283         { 0x0D, 0x01, "Third Party Device Failure" },
 1284         { 0x0D, 0x02, "Copy Target Device Not Reachable" },
 1285         { 0x0D, 0x03, "Incorrect Copy Target Device Type" },
 1286         { 0x0D, 0x04, "Copy Target Device Data Underrun" },
 1287         { 0x0D, 0x05, "Copy Target Device Data Overrun" },
 1288         { 0x0E, 0x00, "Invalid Information Unit" },
 1289         { 0x0E, 0x01, "Information Unit Too Short" },
 1290         { 0x0E, 0x02, "Information Unit Too Long" },
 1291         { 0x10, 0x00, "ID CRC Or ECC Error" },
 1292         { 0x11, 0x00, "Unrecovered Read Error" },
 1293         { 0x11, 0x01, "Read Retries Exhausted" },
 1294         { 0x11, 0x02, "Error Too Long To Correct" },
 1295         { 0x11, 0x03, "Multiple Read Errors" },
 1296         { 0x11, 0x04, "Unrecovered Read Error - Auto Reallocate Failed" },
 1297         { 0x11, 0x05, "L-EC Uncorrectable Error" },
 1298         { 0x11, 0x06, "CIRC Unrecovered Error" },
 1299         { 0x11, 0x07, "Data Resynchronization Error" },
 1300         { 0x11, 0x08, "Incomplete Block Read" },
 1301         { 0x11, 0x09, "No Gap Found" },
 1302         { 0x11, 0x0A, "Miscorrected Error" },
 1303         { 0x11, 0x0B, "Uncorrected Read Error - Recommend Reassignment" },
 1304         { 0x11, 0x0C, "Uncorrected Read Error - Recommend Rewrite The Data" },
 1305         { 0x11, 0x0D, "De-Compression CRC Error" },
 1306         { 0x11, 0x0E, "Cannot Decompress Using Declared Algorithm" },
 1307         { 0x11, 0x0F, "Error Reading UPC/EAN Number" },
 1308         { 0x11, 0x10, "Error Reading ISRC Number" },
 1309         { 0x11, 0x11, "Read Error - Loss Of Streaming" },
 1310         { 0x11, 0x12, "Auxiliary Memory Read Error" },
 1311         { 0x11, 0x13, "Read Error - Failed Retransmission Request" },
 1312         { 0x12, 0x00, "Address Mark Not Found for ID Field" },
 1313         { 0x13, 0x00, "Address Mark Not Found for Data Field" },
 1314         { 0x14, 0x00, "Recorded Entity Not Found" },
 1315         { 0x14, 0x01, "Record Not Found" },
 1316         { 0x14, 0x02, "Filemark or Setmark Not Found" },
 1317         { 0x14, 0x03, "End-Of-Data Not Found" },
 1318         { 0x14, 0x04, "Block Sequence Error" },
 1319         { 0x14, 0x05, "Record Not Found - Recommend Reassignment" },
 1320         { 0x14, 0x06, "Record Not Found - Data Auto-Reallocated" },
 1321         { 0x14, 0x07, "Locate Operation Failure" },
 1322         { 0x15, 0x00, "Random Positioning Error" },
 1323         { 0x15, 0x01, "Mechanical Positioning Error" },
 1324         { 0x15, 0x02, "Positioning Error Detected By Read of Medium" },
 1325         { 0x16, 0x00, "Data Synchronization Mark Error" },
 1326         { 0x16, 0x01, "Data Sync Error - Data Rewritten" },
 1327         { 0x16, 0x02, "Data Sync Error - Recommend Rewrite" },
 1328         { 0x16, 0x03, "Data Sync Error - Data Auto-Reallocated" },
 1329         { 0x16, 0x04, "Data Sync Error - Recommend Reassignment" },
 1330         { 0x17, 0x00, "Recovered Data With No Error Correction Applied" },
 1331         { 0x17, 0x01, "Recovered Data With Retries" },
 1332         { 0x17, 0x02, "Recovered Data With Positive Head Offset" },
 1333         { 0x17, 0x03, "Recovered Data With Negative Head Offset" },
 1334         { 0x17, 0x04, "Recovered Data With Retries and/or CIRC Applied" },
 1335         { 0x17, 0x05, "Recovered Data Using Previous Sector ID" },
 1336         { 0x17, 0x06, "Recovered Data Without ECC - Data Auto-Reallocated" },
 1337         { 0x17, 0x07, "Recovered Data Without ECC - Recommend Reassignment" },
 1338         { 0x17, 0x08, "Recovered Data Without ECC - Recommend Rewrite" },
 1339         { 0x17, 0x09, "Recovered Data Without ECC - Data Rewritten" },
 1340         { 0x18, 0x00, "Recovered Data With Error Correction Applied" },
 1341         { 0x18, 0x01, "Recovered Data With Error Correction & Retries Applied" },
 1342         { 0x18, 0x02, "Recovered Data - Data Auto-Reallocated" },
 1343         { 0x18, 0x03, "Recovered Data With CIRC" },
 1344         { 0x18, 0x04, "Recovered Data With L-EC" },
 1345         { 0x18, 0x05, "Recovered Data - Recommend Reassignment" },
 1346         { 0x18, 0x06, "Recovered Data - Recommend Rewrite" },
 1347         { 0x18, 0x07, "Recovered Data With ECC - Data Rewritten" },
 1348         { 0x18, 0x08, "Recovered Data With Linking" },
 1349         { 0x19, 0x00, "Defect List Error" },
 1350         { 0x19, 0x01, "Defect List Not Available" },
 1351         { 0x19, 0x02, "Defect List Error in Primary List" },
 1352         { 0x19, 0x03, "Defect List Error in Grown List" },
 1353         { 0x1A, 0x00, "Parameter List Length Error" },
 1354         { 0x1B, 0x00, "Synchronous Data Transfer Error" },
 1355         { 0x1C, 0x00, "Defect List Not Found" },
 1356         { 0x1C, 0x01, "Primary Defect List Not Found" },
 1357         { 0x1C, 0x02, "Grown Defect List Not Found" },
 1358         { 0x1D, 0x00, "Miscompare During Verify Operation" },
 1359         { 0x1E, 0x00, "Recovered ID with ECC" },
 1360         { 0x1F, 0x00, "Partial Defect List Transfer" },
 1361         { 0x20, 0x00, "Invalid Command Operation Code" },
 1362         { 0x20, 0x01, "Access Denied - Initiator Pending-Enrolled" },
 1363         { 0x20, 0x02, "Access Denied - No Access rights" },
 1364         { 0x20, 0x03, "Access Denied - Invalid Mgmt ID Key" },
 1365         { 0x20, 0x04, "Illegal Command While In Write Capable State" },
 1366         { 0x20, 0x05, "Obsolete" },
 1367         { 0x20, 0x06, "Illegal Command While In Explicit Address Mode" },
 1368         { 0x20, 0x07, "Illegal Command While In Implicit Address Mode" },
 1369         { 0x20, 0x08, "Access Denied - Enrollment Conflict" },
 1370         { 0x20, 0x09, "Access Denied - Invalid LU Identifier" },
 1371         { 0x20, 0x0A, "Access Denied - Invalid Proxy Token" },
 1372         { 0x20, 0x0B, "Access Denied - ACL LUN Conflict" },
 1373         { 0x21, 0x00, "Logical Block Address Out of Range" },
 1374         { 0x21, 0x01, "Invalid Element Address" },
 1375         { 0x21, 0x02, "Invalid Address For Write" },
 1376         { 0x22, 0x00, "Illegal Function (Should 20 00, 24 00, or 26 00)" },
 1377         { 0x24, 0x00, "Illegal Field in CDB" },
 1378         { 0x24, 0x01, "CDB Decryption Error" },
 1379         { 0x24, 0x02, "Obsolete" },
 1380         { 0x24, 0x03, "Obsolete" },
 1381         { 0x24, 0x04, "Security Audit Value Frozen" },
 1382         { 0x24, 0x05, "Security Working Key Frozen" },
 1383         { 0x24, 0x06, "Nonce Not Unique" },
 1384         { 0x24, 0x07, "Nonce Timestamp Out Of Range" },
 1385         { 0x25, 0x00, "Logical Unit Not Supported" },
 1386         { 0x26, 0x00, "Invalid Field In Parameter List" },
 1387         { 0x26, 0x01, "Parameter Not Supported" },
 1388         { 0x26, 0x02, "Parameter Value Invalid" },
 1389         { 0x26, 0x03, "Threshold Parameters Not Supported" },
 1390         { 0x26, 0x04, "Invalid Release Of Persistent Reservation" },
 1391         { 0x26, 0x05, "Data Decryption Error" },
 1392         { 0x26, 0x06, "Too Many Target Descriptors" },
 1393         { 0x26, 0x07, "Unsupported Target Descriptor Type Code" },
 1394         { 0x26, 0x08, "Too Many Segment Descriptors" },
 1395         { 0x26, 0x09, "Unsupported Segment Descriptor Type Code" },
 1396         { 0x26, 0x0A, "Unexpected Inexact Segment" },
 1397         { 0x26, 0x0B, "Inline Data Length Exceeded" },
 1398         { 0x26, 0x0C, "Invalid Operation For Copy Source Or Destination" },
 1399         { 0x26, 0x0D, "Copy Segment Granularity Violation" },
 1400         { 0x26, 0x0E, "Invalid Parameter While Port Is Enabled" },
 1401         { 0x27, 0x00, "Write Protected" },
 1402         { 0x27, 0x01, "Hardware Write Protected" },
 1403         { 0x27, 0x02, "Logical Unit Software Write Protected" },
 1404         { 0x27, 0x03, "Associated Write Protect" },
 1405         { 0x27, 0x04, "Persistent Write Protect" },
 1406         { 0x27, 0x05, "Permanent Write Protect" },
 1407         { 0x27, 0x06, "Conditional Write Protect" },
 1408         { 0x28, 0x00, "Not Ready To Ready Transition (Medium May Have Changed)" },
 1409         { 0x28, 0x01, "Import Or Export Element Accessed" },
 1410         { 0x29, 0x00, "Power On, Reset, or Bus Device Reset Occurred" },
 1411         { 0x29, 0x01, "Power On Occurred" },
 1412         { 0x29, 0x02, "SCSI Bus Reset Occurred" },
 1413         { 0x29, 0x03, "Bus Device Reset Function Occurred" },
 1414         { 0x29, 0x04, "Device Internal Reset" },
 1415         { 0x29, 0x05, "Transceiver Mode Changed to Single Ended" },
 1416         { 0x29, 0x06, "Transceiver Mode Changed to LVD" },
 1417         { 0x29, 0x07, "I_T Nexus Loss Occurred" },
 1418         { 0x2A, 0x00, "Parameters Changed" },
 1419         { 0x2A, 0x01, "Mode Parameters Changed" },
 1420         { 0x2A, 0x02, "Log Parameters Changed" },
 1421         { 0x2A, 0x03, "Reservations Preempted" },
 1422         { 0x2A, 0x04, "Reservations Released" },
 1423         { 0x2A, 0x05, "Registrations Preempted" },
 1424         { 0x2A, 0x06, "Asymmetric Access State Changed" },
 1425         { 0x2A, 0x07, "Implicit Asymmetric Access State Transition Failed" },
 1426         { 0x2B, 0x00, "Copy Cannot Execute Since Host Cannot Disconnect" },
 1427         { 0x2C, 0x00, "Command Sequence Error" },
 1428         { 0x2C, 0x01, "Too Many Windows Specified" },
 1429         { 0x2C, 0x02, "Invalid Combination of Windows Specified" },
 1430         { 0x2C, 0x03, "Current Program Area Is Not Empty" },
 1431         { 0x2C, 0x04, "Current Program Area Is Empty" },
 1432         { 0x2C, 0x05, "Illegal Power Condition Request" },
 1433         { 0x2C, 0x06, "Persistent Prevent Conflict" },
 1434         { 0x2C, 0x07, "Previous Busy Status" },
 1435         { 0x2C, 0x08, "Previous Task Set Full Status" },
 1436         { 0x2C, 0x09, "Previous Reservation Conflict Status" },
 1437         { 0x2C, 0x0A, "Partition Or Collection Contains User Objects" },
 1438         { 0x2D, 0x00, "Overwrite Error On Update In Place" },
 1439         { 0x2E, 0x00, "Insufficient Time For Operation" },
 1440         { 0x2F, 0x00, "Commands Cleared By Another Initiator" },
 1441         { 0x30, 0x00, "Incompatible Medium Installed" },
 1442         { 0x30, 0x01, "Cannot Read Medium - Unknown Format" },
 1443         { 0x30, 0x02, "Cannot Read Medium - Incompatible Format" },
 1444         { 0x30, 0x03, "Cleaning Cartridge Installed" },
 1445         { 0x30, 0x04, "Cannot Write Medium - Unknown Format" },
 1446         { 0x30, 0x05, "Cannot Write Medium - Incompatible Format" },
 1447         { 0x30, 0x06, "Cannot Format Medium - Incompatible Medium" },
 1448         { 0x30, 0x07, "Cleaning Failure" },
 1449         { 0x30, 0x08, "Cannot Write - Application Code Mismatch" },
 1450         { 0x30, 0x09, "Current Session Not Fixated For Append" },
 1451         { 0x30, 0x0A, "Cleaning Request Rejected" },
 1452         { 0x30, 0x10, "Medium Not Formatted" },
 1453         { 0x31, 0x00, "Medium Format Corrupted" },
 1454         { 0x31, 0x01, "Format Command Failed" },
 1455         { 0x32, 0x00, "No Defect Spare Location Available" },
 1456         { 0x32, 0x01, "Defect List Update Failure" },
 1457         { 0x33, 0x00, "Tape Length Error" },
 1458         { 0x34, 0x00, "Enclosure Failure" },
 1459         { 0x35, 0x00, "Enclosure Services Failure" },
 1460         { 0x35, 0x01, "Unsupported Enclosure Function" },
 1461         { 0x35, 0x02, "Enclosure Services Unavailable" },
 1462         { 0x35, 0x03, "Enclosure Services Transfer Failure" },
 1463         { 0x35, 0x04, "Enclosure Services Transfer Refused" },
 1464         { 0x36, 0x00, "Ribbon, Ink, or Toner Failure" },
 1465         { 0x37, 0x00, "Rounded Parameter" },
 1466         { 0x38, 0x00, "Event Status Notification" },
 1467         { 0x38, 0x02, "ESN - Power Management Class Event" },
 1468         { 0x38, 0x04, "ESN - Media Class Event" },
 1469         { 0x38, 0x06, "ESN - Device Busy Class Event" },
 1470         { 0x39, 0x00, "Saving Parameters Not Supported" },
 1471         { 0x3A, 0x00, "Medium Not Present" },
 1472         { 0x3A, 0x01, "Medium Not Present - Tray Closed" },
 1473         { 0x3A, 0x02, "Medium Not Present - Tray Open" },
 1474         { 0x3A, 0x03, "Medium Not Present - Loadable" },
 1475         { 0x3A, 0x04, "Medium Not Present - Medium Auxiliary Memory Accessible" },
 1476         { 0x3B, 0x00, "Sequential Positioning Error" },
 1477         { 0x3B, 0x01, "Tape Position Error At Beginning-of-Medium" },
 1478         { 0x3B, 0x02, "Tape Position Error At End-of-Medium" },
 1479         { 0x3B, 0x03, "Tape or Electronic Vertical Forms Unit Not Ready" },
 1480         { 0x3B, 0x04, "Slew Failure" },
 1481         { 0x3B, 0x05, "Paper Jam" },
 1482         { 0x3B, 0x06, "Failed To Sense Top-Of-Form" },
 1483         { 0x3B, 0x07, "Failed To Sense Bottom-Of-Form" },
 1484         { 0x3B, 0x08, "Reposition Error" },
 1485         { 0x3B, 0x09, "Read Past End Of Medium" },
 1486         { 0x3B, 0x0A, "Read Past Beginning Of Medium" },
 1487         { 0x3B, 0x0B, "Position Past End Of Medium" },
 1488         { 0x3B, 0x0C, "Position Past Beginning Of Medium" },
 1489         { 0x3B, 0x0D, "Medium Destination Element Full" },
 1490         { 0x3B, 0x0E, "Medium Source Element Empty" },
 1491         { 0x3B, 0x0F, "End Of Medium Reached" },
 1492         { 0x3B, 0x11, "Medium Magazine Not Accessible" },
 1493         { 0x3B, 0x12, "Medium Magazine Removed" },
 1494         { 0x3B, 0x13, "Medium Magazine Inserted" },
 1495         { 0x3B, 0x14, "Medium Magazine Locked" },
 1496         { 0x3B, 0x15, "Medium Magazine Unlocked" },
 1497         { 0x3B, 0x16, "Mechanical Positioning Or Changer Error" },
 1498         { 0x3D, 0x00, "Invalid Bits In IDENTIFY Message" },
 1499         { 0x3E, 0x00, "Logical Unit Has Not Self-Configured Yet" },
 1500         { 0x3E, 0x01, "Logical Unit Failure" },
 1501         { 0x3E, 0x02, "Timeout On Logical Unit" },
 1502         { 0x3E, 0x03, "Logical Unit Failed Self-Test" },
 1503         { 0x3E, 0x04, "Logical Unit Unable To Update Self-Test Log" },
 1504         { 0x3F, 0x00, "Target Operating Conditions Have Changed" },
 1505         { 0x3F, 0x01, "Microcode Has Changed" },
 1506         { 0x3F, 0x02, "Changed Operating Definition" },
 1507         { 0x3F, 0x03, "INQUIRY Data Has Changed" },
 1508         { 0x3F, 0x04, "component Device Attached" },
 1509         { 0x3F, 0x05, "Device Identifier Changed" },
 1510         { 0x3F, 0x06, "Redundancy Group Created Or Modified" },
 1511         { 0x3F, 0x07, "Redundancy Group Deleted" },
 1512         { 0x3F, 0x08, "Spare Created Or Modified" },
 1513         { 0x3F, 0x09, "Spare Deleted" },
 1514         { 0x3F, 0x0A, "Volume Set Created Or Modified" },
 1515         { 0x3F, 0x0B, "Volume Set Deleted" },
 1516         { 0x3F, 0x0C, "Volume Set Deassigned" },
 1517         { 0x3F, 0x0D, "Volume Set Reassigned" },
 1518         { 0x3F, 0x0E, "Reported LUNs Data Has Changed" },
 1519         { 0x3F, 0x0F, "Echo Buffer Overwritten" },
 1520         { 0x3F, 0x10, "Medium Loadable" },
 1521         { 0x3F, 0x11, "Medium Auxiliary Memory Accessible" },
 1522         { 0x40, 0x00, "RAM FAILURE (Should Use 40 NN)" },
 1523         /*
 1524          * ASC 0x40 also has an ASCQ range from 0x80 to 0xFF.
 1525          * 0x40 0xNN DIAGNOSTIC FAILURE ON COMPONENT NN
 1526          */
 1527         { 0x41, 0x00, "Data Path FAILURE (Should Use 40 NN)" },
 1528         { 0x42, 0x00, "Power-On or Self-Test FAILURE (Should Use 40 NN)" },
 1529         { 0x43, 0x00, "Message Error" },
 1530         { 0x44, 0x00, "Internal Target Failure" },
 1531         { 0x45, 0x00, "Select Or Reselect Failure" },
 1532         { 0x46, 0x00, "Unsuccessful Soft Reset" },
 1533         { 0x47, 0x00, "SCSI Parity Error" },
 1534         { 0x47, 0x01, "Data Phase CRC Error Detected" },
 1535         { 0x47, 0x02, "SCSI Parity Error Detected During ST Data Phase" },
 1536         { 0x47, 0x03, "Information Unit iuCRC Error Detected" },
 1537         { 0x47, 0x04, "Asynchronous Information Protection Error Detected" },
 1538         { 0x47, 0x05, "Protocol Service CRC Error" },
 1539         { 0x47, 0x7F, "Some Commands Cleared By iSCSI Protocol Event" },
 1540         { 0x48, 0x00, "Initiator Detected Error Message Received" },
 1541         { 0x49, 0x00, "Invalid Message Error" },
 1542         { 0x4A, 0x00, "Command Phase Error" },
 1543         { 0x4B, 0x00, "Data Phase Error" },
 1544         { 0x4B, 0x01, "Invalid Target Port Transfer Tag Received" },
 1545         { 0x4B, 0x02, "Too Much Write Data" },
 1546         { 0x4B, 0x03, "ACK/NAK Timeout" },
 1547         { 0x4B, 0x04, "NAK Received" },
 1548         { 0x4B, 0x05, "Data Offset Error" },
 1549         { 0x4B, 0x06, "Initiator Response Timeout" },
 1550         { 0x4C, 0x00, "Logical Unit Failed Self-Configuration" },
 1551         /*
 1552          * ASC 0x4D has an ASCQ range from 0x00 to 0xFF.
 1553          * 0x4D 0xNN TAGGED OVERLAPPED COMMANDS (NN = TASK TAG)
 1554          */
 1555         { 0x4E, 0x00, "Overlapped Commands Attempted" },
 1556         { 0x50, 0x00, "Write Append Error" },
 1557         { 0x50, 0x01, "Write Append Position Error" },
 1558         { 0x50, 0x02, "Position Error Related To Timing" },
 1559         { 0x51, 0x00, "Erase Failure" },
 1560         { 0x51, 0x01, "Erase Failure - Incomplete Erase Operation Detected" },
 1561         { 0x52, 0x00, "Cartridge Fault" },
 1562         { 0x53, 0x00, "Media Load or Eject Failed" },
 1563         { 0x53, 0x01, "Unload Tape Failure" },
 1564         { 0x53, 0x02, "Medium Removal Prevented" },
 1565         { 0x54, 0x00, "SCSI To Host System Interface Failure" },
 1566         { 0x55, 0x00, "System Resource Failure" },
 1567         { 0x55, 0x01, "System Buffer Full" },
 1568         { 0x55, 0x02, "Insufficient Reservation Resources" },
 1569         { 0x55, 0x03, "Insufficient Resources" },
 1570         { 0x55, 0x04, "Insufficient Registration Resources" },
 1571         { 0x55, 0x05, "Insufficient Access Control Resources" },
 1572         { 0x55, 0x06, "Auxiliary Memory Out Of Space" },
 1573         { 0x57, 0x00, "Unable To Recover Table-Of-Contents" },
 1574         { 0x58, 0x00, "Generation Does Not Exist" },
 1575         { 0x59, 0x00, "Updated Block Read" },
 1576         { 0x5A, 0x00, "Operator Request or State Change Input" },
 1577         { 0x5A, 0x01, "Operator Medium Removal Requested" },
 1578         { 0x5A, 0x02, "Operator Selected Write Protect" },
 1579         { 0x5A, 0x03, "Operator Selected Write Permit" },
 1580         { 0x5B, 0x00, "Log Exception" },
 1581         { 0x5B, 0x01, "Threshold Condition Met" },
 1582         { 0x5B, 0x02, "Log Counter At Maximum" },
 1583         { 0x5B, 0x03, "Log List Codes Exhausted" },
 1584         { 0x5C, 0x00, "RPL Status Change" },
 1585         { 0x5C, 0x01, "Spindles Synchronized" },
 1586         { 0x5C, 0x02, "Spindles Not Synchronized" },
 1587         { 0x5D, 0x00, "Failure Prediction Threshold Exceeded" },
 1588         { 0x5D, 0x01, "Media Failure Prediction Threshold Exceeded" },
 1589         { 0x5D, 0x02, "Logical Unit Failure Prediction Threshold Exceeded" },
 1590         { 0x5D, 0x03, "Spare Area Exhaustion Prediction Threshold Exceeded" },
 1591         { 0x5D, 0x10, "Hardware Impending Failure General Hard Drive Failure" },
 1592         { 0x5D, 0x11, "Hardware Impending Failure Drive Error Rate Too High" },
 1593         { 0x5D, 0x12, "Hardware Impending Failure Data Error Rate Too High" },
 1594         { 0x5D, 0x13, "Hardware Impending Failure Seek Error Rate Too High" },
 1595         { 0x5D, 0x14, "Hardware Impending Failure Too Many Block Reassigns" },
 1596         { 0x5D, 0x15, "Hardware Impending Failure Access Times Too High" },
 1597         { 0x5D, 0x16, "Hardware Impending Failure Start Unit Times Too High" },
 1598         { 0x5D, 0x17, "Hardware Impending Failure Channel Parametrics" },
 1599         { 0x5D, 0x18, "Hardware Impending Failure Controller Detected" },
 1600         { 0x5D, 0x19, "Hardware Impending Failure Throughput Performance" },
 1601         { 0x5D, 0x1A, "Hardware Impending Failure Seek Time Performance" },
 1602         { 0x5D, 0x1B, "Hardware Impending Failure Spin-Up Retry Count" },
 1603         { 0x5D, 0x1C, "Hardware Impending Failure Drive Calibration Retry Count" },
 1604         { 0x5D, 0x20, "Controller Impending Failure General Hard Drive Failure" },
 1605         { 0x5D, 0x21, "Controller Impending Failure Drive Error Rate Too High" },
 1606         { 0x5D, 0x22, "Controller Impending Failure Data Error Rate Too High" },
 1607         { 0x5D, 0x23, "Controller Impending Failure Seek Error Rate Too High" },
 1608         { 0x5D, 0x24, "Controller Impending Failure Too Many Block Reassigns" },
 1609         { 0x5D, 0x25, "Controller Impending Failure Access Times Too High" },
 1610         { 0x5D, 0x26, "Controller Impending Failure Start Unit Times Too High" },
 1611         { 0x5D, 0x27, "Controller Impending Failure Channel Parametrics" },
 1612         { 0x5D, 0x28, "Controller Impending Failure Controller Detected" },
 1613         { 0x5D, 0x29, "Controller Impending Failure Throughput Performance" },
 1614         { 0x5D, 0x2A, "Controller Impending Failure Seek Time Performance" },
 1615         { 0x5D, 0x2B, "Controller Impending Failure Spin-Up Retry Count" },
 1616         { 0x5D, 0x2C, "Controller Impending Failure Drive Calibration Retry Count" },
 1617         { 0x5D, 0x30, "Data Channel Impending Failure General Hard Drive Failure" },
 1618         { 0x5D, 0x31, "Data Channel Impending Failure Drive Error Rate Too High" },
 1619         { 0x5D, 0x32, "Data Channel Impending Failure Data Error Rate Too High" },
 1620         { 0x5D, 0x33, "Data Channel Impending Failure Seek Error Rate Too High" },
 1621         { 0x5D, 0x34, "Data Channel Impending Failure Too Many Block Reassigns" },
 1622         { 0x5D, 0x35, "Data Channel Impending Failure Access Times Too High" },
 1623         { 0x5D, 0x36, "Data Channel Impending Failure Start Unit Times Too High" },
 1624         { 0x5D, 0x37, "Data Channel Impending Failure Channel Parametrics" },
 1625         { 0x5D, 0x38, "Data Channel Impending Failure Controller Detected" },
 1626         { 0x5D, 0x39, "Data Channel Impending Failure Throughput Performance" },
 1627         { 0x5D, 0x3A, "Data Channel Impending Failure Seek Time Performance" },
 1628         { 0x5D, 0x3B, "Data Channel Impending Failure Spin-Up Retry Count" },
 1629         { 0x5D, 0x3C, "Data Channel Impending Failure Drive Calibration Retry Count" },
 1630         { 0x5D, 0x40, "Servo Impending Failure General Hard Drive Failure" },
 1631         { 0x5D, 0x41, "Servo Impending Failure Drive Error Rate Too High" },
 1632         { 0x5D, 0x42, "Servo Impending Failure Data Error Rate Too High" },
 1633         { 0x5D, 0x43, "Servo Impending Failure Seek Error Rate Too High" },
 1634         { 0x5D, 0x44, "Servo Impending Failure Too Many Block Reassigns" },
 1635         { 0x5D, 0x45, "Servo Impending Failure Access Times Too High" },
 1636         { 0x5D, 0x46, "Servo Impending Failure Start Unit Times Too High" },
 1637         { 0x5D, 0x47, "Servo Impending Failure Channel Parametrics" },
 1638         { 0x5D, 0x48, "Servo Impending Failure Controller Detected" },
 1639         { 0x5D, 0x49, "Servo Impending Failure Throughput Performance" },
 1640         { 0x5D, 0x4A, "Servo Impending Failure Seek Time Performance" },
 1641         { 0x5D, 0x4B, "Servo Impending Failure Spin-Up Retry Count" },
 1642         { 0x5D, 0x4C, "Servo Impending Failure Drive Calibration Retry Count" },
 1643         { 0x5D, 0x50, "Spindle Impending Failure General Hard Drive Failure" },
 1644         { 0x5D, 0x51, "Spindle Impending Failure Drive Error Rate Too High" },
 1645         { 0x5D, 0x52, "Spindle Impending Failure Data Error Rate Too High" },
 1646         { 0x5D, 0x53, "Spindle Impending Failure Seek Error Rate Too High" },
 1647         { 0x5D, 0x54, "Spindle Impending Failure Too Many Block Reassigns" },
 1648         { 0x5D, 0x55, "Spindle Impending Failure Access Times Too High" },
 1649         { 0x5D, 0x56, "Spindle Impending Failure Start Unit Times Too High" },
 1650         { 0x5D, 0x57, "Spindle Impending Failure Channel Parametrics" },
 1651         { 0x5D, 0x58, "Spindle Impending Failure Controller Detected" },
 1652         { 0x5D, 0x59, "Spindle Impending Failure Throughput Performance" },
 1653         { 0x5D, 0x5A, "Spindle Impending Failure Seek Time Performance" },
 1654         { 0x5D, 0x5B, "Spindle Impending Failure Spin-Up Retry Count" },
 1655         { 0x5D, 0x5C, "Spindle Impending Failure Drive Calibration Retry Count" },
 1656         { 0x5D, 0x60, "Firmware Impending Failure General Hard Drive Failure" },
 1657         { 0x5D, 0x61, "Firmware Impending Failure Drive Error Rate Too High" },
 1658         { 0x5D, 0x62, "Firmware Impending Failure Data Error Rate Too High" },
 1659         { 0x5D, 0x63, "Firmware Impending Failure Seek Error Rate Too High" },
 1660         { 0x5D, 0x64, "Firmware Impending Failure Too Many Block Reassigns" },
 1661         { 0x5D, 0x65, "Firmware Impending Failure Access Times Too High" },
 1662         { 0x5D, 0x66, "Firmware Impending Failure Start Unit Times Too High" },
 1663         { 0x5D, 0x67, "Firmware Impending Failure Channel Parametrics" },
 1664         { 0x5D, 0x68, "Firmware Impending Failure Controller Detected" },
 1665         { 0x5D, 0x69, "Firmware Impending Failure Throughput Performance" },
 1666         { 0x5D, 0x6A, "Firmware Impending Failure Seek Time Performance" },
 1667         { 0x5D, 0x6B, "Firmware Impending Failure Spin-Up Retry Count" },
 1668         { 0x5D, 0x6C, "Firmware Impending Failure Drive Calibration Retry Count" },
 1669         { 0x5D, 0xFF, "Failure Prediction Threshold Exceeded (false)" },
 1670         { 0x5E, 0x00, "Low Power Condition On" },
 1671         { 0x5E, 0x01, "Idle Condition Activated By Timer" },
 1672         { 0x5E, 0x02, "Standby Condition Activated By Timer" },
 1673         { 0x5E, 0x03, "Idle Condition Activated By Command" },
 1674         { 0x5E, 0x04, "Standby Condition Activated By Command" },
 1675         { 0x5E, 0x41, "Power State Change To Active" },
 1676         { 0x5E, 0x42, "Power State Change To Idle" },
 1677         { 0x5E, 0x43, "Power State Change To Standby" },
 1678         { 0x5E, 0x45, "Power State Change To Sleep" },
 1679         { 0x5E, 0x47, "Power State Change To Device Control" },
 1680         { 0x60, 0x00, "Lamp Failure" },
 1681         { 0x61, 0x00, "Video Acquisition Error" },
 1682         { 0x61, 0x01, "Unable To Acquire Video" },
 1683         { 0x61, 0x02, "Out Of Focus" },
 1684         { 0x62, 0x00, "Scan Head Positioning Error" },
 1685         { 0x63, 0x00, "End Of User Area Encountered On This Track" },
 1686         { 0x63, 0x01, "Packet Does Not Fit In Available Space" },
 1687         { 0x64, 0x00, "Illegal Mode For This Track" },
 1688         { 0x64, 0x01, "Invalid Packet Size" },
 1689         { 0x65, 0x00, "Voltage Fault" },
 1690         { 0x66, 0x00, "Automatic Document Feeder Cover Up" },
 1691         { 0x66, 0x01, "Automatic Document Feeder Lift Up" },
 1692         { 0x66, 0x02, "Document Jam In Automatic Document Feeder" },
 1693         { 0x66, 0x03, "Document Miss Feed Automatic In Document Feeder" },
 1694         { 0x67, 0x00, "Configuration Failure" },
 1695         { 0x67, 0x01, "Configuration Of Incapable Logical Units Failed" },
 1696         { 0x67, 0x02, "Add Logical Unit Failed" },
 1697         { 0x67, 0x03, "Modification Of Logical Unit Failed" },
 1698         { 0x67, 0x04, "Exchange Of Logical Unit Failed" },
 1699         { 0x67, 0x05, "Remove Of Logical Unit Failed" },
 1700         { 0x67, 0x06, "Attachment Of Logical Unit Failed" },
 1701         { 0x67, 0x07, "Creation Of Logical Unit Failed" },
 1702         { 0x67, 0x08, "Assign Failure Occurred" },
 1703         { 0x67, 0x09, "Multiply Assigned Logical Unit" },
 1704         { 0x67, 0x0A, "Set Target Port Groups Command Failed" },
 1705         { 0x68, 0x00, "Logical Unit Not Configured" },
 1706         { 0x69, 0x00, "Data Loss On Logical Unit" },
 1707         { 0x69, 0x01, "Multiple Logical Unit Failures" },
 1708         { 0x69, 0x02, "Parity/Data Mismatch" },
 1709         { 0x6A, 0x00, "Informational, Refer To Log" },
 1710         { 0x6B, 0x00, "State Change Has Occurred" },
 1711         { 0x6B, 0x01, "Redundancy Level Got Better" },
 1712         { 0x6B, 0x02, "Redundancy Level Got Worse" },
 1713         { 0x6C, 0x00, "Rebuild Failure Occurred" },
 1714         { 0x6D, 0x00, "Recalculate Failure Occurred" },
 1715         { 0x6E, 0x00, "Command To Logical Unit Failed" },
 1716         { 0x6F, 0x00, "Copy Protection Key Exchange Failure - Authentication Failure" },
 1717         { 0x6F, 0x01, "Copy Protection Key Exchange Failure - Key Not Present" },
 1718         { 0x6F, 0x02, "Copy Protection Key Exchange Failure - Key Not Established" },
 1719         { 0x6F, 0x03, "Read Of Scrambled Sector Without Authentication" },
 1720         { 0x6F, 0x04, "Media Region Code Is Mismatched To Logical Unit Region" },
 1721         { 0x6F, 0x05, "Drive Region Must Be Permanent/Region Reset Count Error" },
 1722         /*
 1723          * ASC 0x70 has an ASCQ range from 0x00 to 0xFF.
 1724          * 0x70 0xNN DECOMPRESSION EXCEPTION SHORT ALGORITHM ID Of NN
 1725          */
 1726         { 0x71, 0x00, "Decompression Exception Long Algorithm ID" },
 1727         { 0x72, 0x00, "Session Fixation Error" },
 1728         { 0x72, 0x01, "Session Fixation Error Writing Lead-In" },
 1729         { 0x72, 0x02, "Session Fixation Error Writing Lead-Out" },
 1730         { 0x72, 0x03, "Session Fixation Error - Incomplete Track In Session" },
 1731         { 0x72, 0x04, "Empty Or Partially Written Reserved Track" },
 1732         { 0x72, 0x05, "No More Track Reservations Allowed" },
 1733         { 0x73, 0x00, "CD Control Error" },
 1734         { 0x73, 0x01, "Power Calibration Area Almost Full" },
 1735         { 0x73, 0x02, "Power Calibration Area Is Full" },
 1736         { 0x73, 0x03, "Power Calibration Area Error" },
 1737         { 0x73, 0x04, "Program Memory Area Update Failure" },
 1738         { 0x73, 0x05, "Program Memory Area Is Full" },
 1739         { 0x73, 0x06, "RMA/PMA Is Almost Full" },
 1740         { 0x00, 0x00, NULL }
 1741 };
 1742 
 1743 static __inline void
 1744 asc2ascii(u_int8_t asc, u_int8_t ascq, char *result, size_t len)
 1745 {
 1746         int                                     i;
 1747 
 1748         /* Check for a dynamically built description. */
 1749         switch (asc) {
 1750         case 0x40:
 1751                 if (ascq >= 0x80) {
 1752                         snprintf(result, len,
 1753                             "Diagnostic Failure on Component 0x%02x", ascq);
 1754                         return;
 1755                 }
 1756                 break;
 1757         case 0x4d:
 1758                 snprintf(result, len,
 1759                     "Tagged Overlapped Commands (0x%02x = TASK TAG)", ascq);
 1760                 return;
 1761         case 0x70:
 1762                 snprintf(result, len,
 1763                     "Decompression Exception Short Algorithm ID OF 0x%02x",
 1764                     ascq);
 1765                 return;
 1766         default:
 1767                 break;
 1768         }
 1769 
 1770         /* Check for a fixed description. */
 1771         for (i = 0; adesc[i].description != NULL; i++) {
 1772                 if (adesc[i].asc == asc && adesc[i].ascq == ascq) {
 1773                         strlcpy(result, adesc[i].description, len);
 1774                         return;
 1775                 }
 1776         }
 1777 
 1778         /* Just print out the ASC and ASCQ values as a description. */
 1779         snprintf(result, len, "ASC 0x%02x ASCQ 0x%02x", asc, ascq);
 1780 }
 1781 #endif /* SCSITERSE */
 1782 
 1783 void
 1784 scsi_print_sense(struct scsi_xfer *xs)
 1785 {
 1786         struct scsi_sense_data                  *sense = &xs->sense;
 1787         u_int8_t                                serr = sense->error_code &
 1788                                                     SSD_ERRCODE;
 1789         int32_t                                 info;
 1790         char                                    *sbs;
 1791 
 1792         sc_print_addr(xs->sc_link);
 1793 
 1794         /* XXX For error 0x71, current opcode is not the relevant one. */
 1795         printf("%sCheck Condition (error %#x) on opcode 0x%x\n",
 1796             (serr == SSD_ERRCODE_DEFERRED) ? "DEFERRED " : "", serr,
 1797             xs->cmd->opcode);
 1798 
 1799         if (serr != SSD_ERRCODE_CURRENT && serr != SSD_ERRCODE_DEFERRED) {
 1800                 if ((sense->error_code & SSD_ERRCODE_VALID) != 0) {
 1801                         struct scsi_sense_data_unextended *usense =
 1802                             (struct scsi_sense_data_unextended *)sense;
 1803                         printf("   AT BLOCK #: %d (decimal)",
 1804                             _3btol(usense->block));
 1805                 }
 1806                 return;
 1807         }
 1808 
 1809         printf("    SENSE KEY: %s\n", scsi_decode_sense(sense,
 1810             DECODE_SENSE_KEY));
 1811 
 1812         if (sense->flags & (SSD_FILEMARK | SSD_EOM | SSD_ILI)) {
 1813                 char pad = ' ';
 1814 
 1815                 printf("             ");
 1816                 if (sense->flags & SSD_FILEMARK) {
 1817                         printf("%c Filemark Detected", pad);
 1818                         pad = ',';
 1819                 }
 1820                 if (sense->flags & SSD_EOM) {
 1821                         printf("%c EOM Detected", pad);
 1822                         pad = ',';
 1823                 }
 1824                 if (sense->flags & SSD_ILI)
 1825                         printf("%c Incorrect Length Indicator Set", pad);
 1826                 printf("\n");
 1827         }
 1828 
 1829         /*
 1830          * It is inconvenient to use device type to figure out how to
 1831          * format the info fields. So print them as 32 bit integers.
 1832          */
 1833         info = _4btol(&sense->info[0]);
 1834         if (info)
 1835                 printf("         INFO: 0x%x (VALID flag %s)\n", info,
 1836                     sense->error_code & SSD_ERRCODE_VALID ? "on" : "off");
 1837 
 1838         if (sense->extra_len < 4)
 1839                 return;
 1840 
 1841         info = _4btol(&sense->cmd_spec_info[0]);
 1842         if (info)
 1843                 printf(" COMMAND INFO: 0x%x\n", info);
 1844         sbs = scsi_decode_sense(sense, DECODE_ASC_ASCQ);
 1845         if (strlen(sbs) > 0)
 1846                 printf("     ASC/ASCQ: %s\n", sbs);
 1847         if (sense->fru != 0)
 1848                 printf("     FRU CODE: 0x%x\n", sense->fru);
 1849         sbs = scsi_decode_sense(sense, DECODE_SKSV);
 1850         if (strlen(sbs) > 0)
 1851                 printf("         SKSV: %s\n", sbs);
 1852 }
 1853 
 1854 char *
 1855 scsi_decode_sense(struct scsi_sense_data *sense, int flag)
 1856 {
 1857         static char                             rqsbuf[132];
 1858         u_int16_t                               count;
 1859         u_int8_t                                skey, spec_1;
 1860         int                                     len;
 1861 
 1862         bzero(rqsbuf, sizeof(rqsbuf));
 1863 
 1864         skey = sense->flags & SSD_KEY;
 1865         spec_1 = sense->sense_key_spec_1;
 1866         count = _2btol(&sense->sense_key_spec_2);
 1867 
 1868         switch (flag) {
 1869         case DECODE_SENSE_KEY:
 1870                 strlcpy(rqsbuf, sense_keys[skey], sizeof(rqsbuf));
 1871                 break;
 1872         case DECODE_ASC_ASCQ:
 1873                 asc2ascii(sense->add_sense_code, sense->add_sense_code_qual,
 1874                     rqsbuf, sizeof(rqsbuf));
 1875                 break;
 1876         case DECODE_SKSV:
 1877                 if (sense->extra_len < 9 || ((spec_1 & SSD_SCS_VALID) == 0))
 1878                         break;
 1879                 switch (skey) {
 1880                 case SKEY_ILLEGAL_REQUEST:
 1881                         len = snprintf(rqsbuf, sizeof rqsbuf,
 1882                             "Error in %s, Offset %d",
 1883                             (spec_1 & SSD_SCS_CDB_ERROR) ? "CDB" : "Parameters",
 1884                             count);
 1885                         if ((len != -1 && len < sizeof rqsbuf) &&
 1886                             (spec_1 & SSD_SCS_VALID_BIT_INDEX))
 1887                                 snprintf(rqsbuf+len, sizeof rqsbuf - len,
 1888                                     ", bit %d", spec_1 & SSD_SCS_BIT_INDEX);
 1889                         break;
 1890                 case SKEY_RECOVERED_ERROR:
 1891                 case SKEY_MEDIUM_ERROR:
 1892                 case SKEY_HARDWARE_ERROR:
 1893                         snprintf(rqsbuf, sizeof rqsbuf,
 1894                             "Actual Retry Count: %d", count);
 1895                         break;
 1896                 case SKEY_NOT_READY:
 1897                         snprintf(rqsbuf, sizeof rqsbuf,
 1898                             "Progress Indicator: %d", count);
 1899                         break;
 1900                 default:
 1901                         break;
 1902                 }
 1903                 break;
 1904         default:
 1905                 break;
 1906         }
 1907 
 1908         return (rqsbuf);
 1909 }
 1910 
 1911 #ifdef SCSIDEBUG
 1912 /*
 1913  * Given a scsi_xfer, dump the request, in all its glory
 1914  */
 1915 void
 1916 show_scsi_xs(struct scsi_xfer *xs)
 1917 {
 1918         printf("xs(%p): ", xs);
 1919         printf("flg(0x%x)", xs->flags);
 1920         printf("sc_link(%p)", xs->sc_link);
 1921         printf("retr(0x%x)", xs->retries);
 1922         printf("timo(0x%x)", xs->timeout);
 1923         printf("cmd(%p)", xs->cmd);
 1924         printf("len(0x%x)", xs->cmdlen);
 1925         printf("data(%p)", xs->data);
 1926         printf("len(0x%x)", xs->datalen);
 1927         printf("res(0x%x)", xs->resid);
 1928         printf("err(0x%x)", xs->error);
 1929         printf("bp(%p)", xs->bp);
 1930         show_scsi_cmd(xs);
 1931 }
 1932 
 1933 void
 1934 show_scsi_cmd(struct scsi_xfer *xs)
 1935 {
 1936         u_char                                  *b = (u_char *) xs->cmd;
 1937         int                                     i = 0;
 1938 
 1939         sc_print_addr(xs->sc_link);
 1940         printf("command: ");
 1941 
 1942         if ((xs->flags & SCSI_RESET) == 0) {
 1943                 while (i < xs->cmdlen) {
 1944                         if (i)
 1945                                 printf(",");
 1946                         printf("%x", b[i++]);
 1947                 }
 1948                 printf("-[%d bytes]\n", xs->datalen);
 1949                 if (xs->datalen)
 1950                         show_mem(xs->data, min(64, xs->datalen));
 1951         } else
 1952                 printf("-RESET-\n");
 1953 }
 1954 
 1955 void
 1956 show_mem(u_char *address, int num)
 1957 {
 1958         int                                     x;
 1959 
 1960         printf("------------------------------");
 1961         for (x = 0; x < num; x++) {
 1962                 if ((x % 16) == 0)
 1963                         printf("\n%03d: ", x);
 1964                 printf("%02x ", *address++);
 1965         }
 1966         printf("\n------------------------------\n");
 1967 }
 1968 #endif /* SCSIDEBUG */

/* [<][>][^][v][top][bottom][index][help] */