LCOV - code coverage report
Current view: top level - scsi - scsi_base.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 811 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 62 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: scsi_base.c,v 1.227 2017/09/08 05:36:53 deraadt 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/param.h>
      39             : #include <sys/systm.h>
      40             : #include <sys/kernel.h>
      41             : #include <sys/uio.h>
      42             : #include <sys/errno.h>
      43             : #include <sys/device.h>
      44             : #include <sys/pool.h>
      45             : #include <sys/task.h>
      46             : 
      47             : #include <scsi/scsi_all.h>
      48             : #include <scsi/scsi_disk.h>
      49             : #include <scsi/scsiconf.h>
      50             : 
      51             : static __inline void asc2ascii(u_int8_t, u_int8_t ascq, char *result,
      52             :     size_t len);
      53             : int     scsi_xs_error(struct scsi_xfer *);
      54             : char   *scsi_decode_sense(struct scsi_sense_data *, int);
      55             : 
      56             : void    scsi_xs_sync_done(struct scsi_xfer *);
      57             : 
      58             : /* Values for flag parameter to scsi_decode_sense. */
      59             : #define DECODE_SENSE_KEY        1
      60             : #define DECODE_ASC_ASCQ         2
      61             : #define DECODE_SKSV             3
      62             : 
      63             : struct pool             scsi_xfer_pool;
      64             : struct pool             scsi_plug_pool;
      65             : 
      66             : struct scsi_plug {
      67             :         struct task             task;
      68             :         struct scsibus_softc    *sb;
      69             :         int                     target;
      70             :         int                     lun;
      71             :         int                     how;
      72             : };
      73             : 
      74             : void    scsi_plug_probe(void *);
      75             : void    scsi_plug_detach(void *);
      76             : 
      77             : struct scsi_xfer *      scsi_xs_io(struct scsi_link *, void *, int);
      78             : 
      79             : int                     scsi_ioh_pending(struct scsi_iopool *);
      80             : struct scsi_iohandler * scsi_ioh_deq(struct scsi_iopool *);
      81             : 
      82             : void                    scsi_xsh_runqueue(struct scsi_link *);
      83             : void                    scsi_xsh_ioh(void *, void *);
      84             : 
      85             : int                     scsi_link_open(struct scsi_link *);
      86             : void                    scsi_link_close(struct scsi_link *);
      87             : 
      88             : void *                  scsi_iopool_get(struct scsi_iopool *);
      89             : void                    scsi_iopool_put(struct scsi_iopool *, void *);
      90             : 
      91             : /* ioh/xsh queue state */
      92             : #define RUNQ_IDLE       0
      93             : #define RUNQ_LINKQ      1
      94             : #define RUNQ_POOLQ      2
      95             : 
      96             : /* synchronous api for allocating an io. */
      97             : struct scsi_io_mover {
      98             :         struct mutex mtx;
      99             :         void *io;
     100             :         u_int done;
     101             : };
     102             : #define SCSI_IO_MOVER_INITIALIZER { MUTEX_INITIALIZER(IPL_BIO), NULL, 0 }
     103             : 
     104             : void scsi_move(struct scsi_io_mover *);
     105             : void scsi_move_done(void *, void *);
     106             : 
     107             : void scsi_io_get_done(void *, void *);
     108             : void scsi_xs_get_done(void *, void *);
     109             : 
     110             : /*
     111             :  * Called when a scsibus is attached to initialize global data.
     112             :  */
     113             : void
     114           0 : scsi_init(void)
     115             : {
     116             :         static int scsi_init_done;
     117             : 
     118           0 :         if (scsi_init_done)
     119             :                 return;
     120           0 :         scsi_init_done = 1;
     121             : 
     122             : #if defined(SCSI_DELAY) && SCSI_DELAY > 0
     123             :         /* Historical. Older buses may need a moment to stabilize. */
     124             :         delay(1000000 * SCSI_DELAY);
     125             : #endif
     126             : 
     127             :         /* Initialize the scsi_xfer pool. */
     128           0 :         pool_init(&scsi_xfer_pool, sizeof(struct scsi_xfer), 0, IPL_BIO, 0,
     129             :             "scxspl", NULL);
     130           0 :         pool_init(&scsi_plug_pool, sizeof(struct scsi_plug), 0, IPL_BIO, 0,
     131             :             "scsiplug", NULL);
     132           0 : }
     133             : 
     134             : int
     135           0 : scsi_req_probe(struct scsibus_softc *sb, int target, int lun)
     136             : {
     137             :         struct scsi_plug *p;
     138             : 
     139           0 :         p = pool_get(&scsi_plug_pool, PR_NOWAIT);
     140           0 :         if (p == NULL)
     141           0 :                 return (ENOMEM);
     142             : 
     143           0 :         task_set(&p->task, scsi_plug_probe, p);
     144           0 :         p->sb = sb;
     145           0 :         p->target = target;
     146           0 :         p->lun = lun;
     147             : 
     148           0 :         task_add(systq, &p->task);
     149             : 
     150           0 :         return (0);
     151           0 : }
     152             : 
     153             : int
     154           0 : scsi_req_detach(struct scsibus_softc *sb, int target, int lun, int how)
     155             : {
     156             :         struct scsi_plug *p;
     157             : 
     158           0 :         p = pool_get(&scsi_plug_pool, PR_NOWAIT);
     159           0 :         if (p == NULL)
     160           0 :                 return (ENOMEM);
     161             : 
     162           0 :         task_set(&p->task, scsi_plug_detach, p);
     163           0 :         p->sb = sb;
     164           0 :         p->target = target;
     165           0 :         p->lun = lun;
     166           0 :         p->how = how;
     167             : 
     168           0 :         task_add(systq, &p->task);
     169             : 
     170           0 :         return (0);
     171           0 : }
     172             : 
     173             : void
     174           0 : scsi_plug_probe(void *xp)
     175             : {
     176           0 :         struct scsi_plug *p = xp;
     177           0 :         struct scsibus_softc *sb = p->sb;
     178           0 :         int target = p->target, lun = p->lun;
     179             : 
     180           0 :         pool_put(&scsi_plug_pool, p);
     181             : 
     182           0 :         scsi_probe(sb, target, lun);
     183           0 : }
     184             : 
     185             : void
     186           0 : scsi_plug_detach(void *xp)
     187             : {
     188           0 :         struct scsi_plug *p = xp;
     189           0 :         struct scsibus_softc *sb = p->sb;
     190           0 :         int target = p->target, lun = p->lun;
     191           0 :         int how = p->how;
     192             : 
     193           0 :         pool_put(&scsi_plug_pool, p);
     194             : 
     195           0 :         scsi_detach(sb, target, lun, how);
     196           0 : }
     197             : 
     198             : int
     199           0 : scsi_pending_start(struct mutex *mtx, u_int *running)
     200             : {
     201             :         int rv = 1;
     202             : 
     203           0 :         mtx_enter(mtx);
     204           0 :         (*running)++;
     205           0 :         if ((*running) > 1)
     206           0 :                 rv = 0;
     207           0 :         mtx_leave(mtx);
     208             : 
     209           0 :         return (rv);
     210             : }
     211             : 
     212             : int
     213           0 : scsi_pending_finish(struct mutex *mtx, u_int *running)
     214             : {
     215             :         int rv = 1;
     216             : 
     217           0 :         mtx_enter(mtx);
     218           0 :         (*running)--;
     219           0 :         if ((*running) > 0) {
     220           0 :                 (*running) = 1;
     221             :                 rv = 0;
     222           0 :         }
     223           0 :         mtx_leave(mtx);
     224             : 
     225           0 :         return (rv);
     226             : }
     227             : 
     228             : void
     229           0 : scsi_iopool_init(struct scsi_iopool *iopl, void *iocookie,
     230             :     void *(*io_get)(void *), void (*io_put)(void *, void *))
     231             : {
     232           0 :         iopl->iocookie = iocookie;
     233           0 :         iopl->io_get = io_get;
     234           0 :         iopl->io_put = io_put;
     235             : 
     236           0 :         TAILQ_INIT(&iopl->queue);
     237           0 :         iopl->running = 0;
     238           0 :         mtx_init(&iopl->mtx, IPL_BIO);
     239           0 : }
     240             : 
     241             : void *
     242           0 : scsi_iopool_get(struct scsi_iopool *iopl)
     243             : {
     244             :         void *io;
     245             : 
     246           0 :         KERNEL_LOCK();
     247           0 :         io = iopl->io_get(iopl->iocookie);
     248           0 :         KERNEL_UNLOCK();
     249             : 
     250           0 :         return (io);
     251             : }
     252             : 
     253             : void
     254           0 : scsi_iopool_put(struct scsi_iopool *iopl, void *io)
     255             : {
     256           0 :         KERNEL_LOCK();
     257           0 :         iopl->io_put(iopl->iocookie, io);
     258           0 :         KERNEL_UNLOCK();
     259           0 : }
     260             : 
     261             : void
     262           0 : scsi_iopool_destroy(struct scsi_iopool *iopl)
     263             : {
     264           0 :         struct scsi_runq sleepers = TAILQ_HEAD_INITIALIZER(sleepers);
     265             :         struct scsi_iohandler *ioh = NULL;
     266             : 
     267           0 :         mtx_enter(&iopl->mtx);
     268           0 :         while ((ioh = TAILQ_FIRST(&iopl->queue)) != NULL) {
     269           0 :                 TAILQ_REMOVE(&iopl->queue, ioh, q_entry);
     270           0 :                 ioh->q_state = RUNQ_IDLE;
     271             : 
     272           0 :                 if (ioh->handler == scsi_io_get_done)
     273           0 :                         TAILQ_INSERT_TAIL(&sleepers, ioh, q_entry);
     274             : #ifdef DIAGNOSTIC
     275             :                 else
     276           0 :                         panic("scsi_iopool_destroy: scsi_iohandler on pool");
     277             : #endif
     278             :         }
     279           0 :         mtx_leave(&iopl->mtx);
     280             : 
     281           0 :         while ((ioh = TAILQ_FIRST(&sleepers)) != NULL) {
     282           0 :                 TAILQ_REMOVE(&sleepers, ioh, q_entry);
     283           0 :                 ioh->handler(ioh->cookie, NULL);
     284             :         }
     285           0 : }
     286             : 
     287             : void *
     288           0 : scsi_default_get(void *iocookie)
     289             : {
     290           0 :         return (SCSI_IOPOOL_POISON);
     291             : }
     292             : 
     293             : void
     294           0 : scsi_default_put(void *iocookie, void *io)
     295             : {
     296             : #ifdef DIAGNOSTIC
     297           0 :         if (io != SCSI_IOPOOL_POISON)
     298           0 :                 panic("unexpected opening returned");
     299             : #endif
     300           0 : }
     301             : 
     302             : /*
     303             :  * public interface to the ioh api.
     304             :  */
     305             : 
     306             : void
     307           0 : scsi_ioh_set(struct scsi_iohandler *ioh, struct scsi_iopool *iopl,
     308             :     void (*handler)(void *, void *), void *cookie)
     309             : {
     310           0 :         ioh->q_state = RUNQ_IDLE;
     311           0 :         ioh->pool = iopl;
     312           0 :         ioh->handler = handler;
     313           0 :         ioh->cookie = cookie;
     314           0 : }
     315             : 
     316             : int
     317           0 : scsi_ioh_add(struct scsi_iohandler *ioh)
     318             : {
     319           0 :         struct scsi_iopool *iopl = ioh->pool;
     320             :         int rv = 0;
     321             : 
     322           0 :         mtx_enter(&iopl->mtx);
     323           0 :         switch (ioh->q_state) {
     324             :         case RUNQ_IDLE:
     325           0 :                 TAILQ_INSERT_TAIL(&iopl->queue, ioh, q_entry);
     326           0 :                 ioh->q_state = RUNQ_POOLQ;
     327             :                 rv = 1;
     328           0 :                 break;
     329             : #ifdef DIAGNOSTIC
     330             :         case RUNQ_POOLQ:
     331             :                 break;
     332             :         default:
     333           0 :                 panic("scsi_ioh_add: unexpected state %u", ioh->q_state);
     334             : #endif
     335             :         }
     336           0 :         mtx_leave(&iopl->mtx);
     337             : 
     338             :         /* lets get some io up in the air */
     339           0 :         scsi_iopool_run(iopl);
     340             : 
     341           0 :         return (rv);
     342             : }
     343             : 
     344             : int
     345           0 : scsi_ioh_del(struct scsi_iohandler *ioh)
     346             : {
     347           0 :         struct scsi_iopool *iopl = ioh->pool;
     348             :         int rv = 0;
     349             : 
     350           0 :         mtx_enter(&iopl->mtx);
     351           0 :         switch (ioh->q_state) {
     352             :         case RUNQ_POOLQ:
     353           0 :                 TAILQ_REMOVE(&iopl->queue, ioh, q_entry);
     354           0 :                 ioh->q_state = RUNQ_IDLE;
     355             :                 rv = 1;
     356           0 :                 break;
     357             : #ifdef DIAGNOSTIC
     358             :         case RUNQ_IDLE:
     359             :                 break;
     360             :         default:
     361           0 :                 panic("scsi_ioh_del: unexpected state %u", ioh->q_state);
     362             : #endif
     363             :         }
     364           0 :         mtx_leave(&iopl->mtx);
     365             : 
     366           0 :         return (rv);
     367             : }
     368             : 
     369             : /*
     370             :  * internal iopool runqueue handling.
     371             :  */
     372             : 
     373             : struct scsi_iohandler *
     374           0 : scsi_ioh_deq(struct scsi_iopool *iopl)
     375             : {
     376             :         struct scsi_iohandler *ioh = NULL;
     377             : 
     378           0 :         mtx_enter(&iopl->mtx);
     379           0 :         ioh = TAILQ_FIRST(&iopl->queue);
     380           0 :         if (ioh != NULL) {
     381           0 :                 TAILQ_REMOVE(&iopl->queue, ioh, q_entry);
     382           0 :                 ioh->q_state = RUNQ_IDLE;
     383           0 :         }
     384           0 :         mtx_leave(&iopl->mtx);
     385             : 
     386           0 :         return (ioh);
     387             : }
     388             : 
     389             : int
     390           0 : scsi_ioh_pending(struct scsi_iopool *iopl)
     391             : {
     392             :         int rv;
     393             : 
     394           0 :         mtx_enter(&iopl->mtx);
     395           0 :         rv = !TAILQ_EMPTY(&iopl->queue);
     396           0 :         mtx_leave(&iopl->mtx);
     397             : 
     398           0 :         return (rv);
     399             : }
     400             : 
     401             : void
     402           0 : scsi_iopool_run(struct scsi_iopool *iopl)
     403             : {
     404             :         struct scsi_iohandler *ioh;
     405             :         void *io;
     406             : 
     407           0 :         if (!scsi_pending_start(&iopl->mtx, &iopl->running))
     408           0 :                 return;
     409           0 :         do {
     410           0 :                 while (scsi_ioh_pending(iopl)) {
     411           0 :                         io = scsi_iopool_get(iopl);
     412           0 :                         if (io == NULL)
     413             :                                 break;
     414             : 
     415           0 :                         ioh = scsi_ioh_deq(iopl);
     416           0 :                         if (ioh == NULL) {
     417           0 :                                 scsi_iopool_put(iopl, io);
     418           0 :                                 break;
     419             :                         }
     420             : 
     421           0 :                         ioh->handler(ioh->cookie, io);
     422             :                 }
     423           0 :         } while (!scsi_pending_finish(&iopl->mtx, &iopl->running));
     424           0 : }
     425             : 
     426             : /*
     427             :  * move an io from a runq to a proc thats waiting for an io.
     428             :  */
     429             : 
     430             : void
     431           0 : scsi_move(struct scsi_io_mover *m)
     432             : {
     433           0 :         mtx_enter(&m->mtx);
     434           0 :         while (!m->done)
     435           0 :                 msleep(m, &m->mtx, PRIBIO, "scsiiomv", 0);
     436           0 :         mtx_leave(&m->mtx);
     437           0 : }
     438             : 
     439             : void
     440           0 : scsi_move_done(void *cookie, void *io)
     441             : {
     442           0 :         struct scsi_io_mover *m = cookie;
     443             : 
     444           0 :         mtx_enter(&m->mtx);
     445           0 :         m->io = io;
     446           0 :         m->done = 1;
     447           0 :         wakeup_one(m);
     448           0 :         mtx_leave(&m->mtx);
     449           0 : }
     450             : 
     451             : /*
     452             :  * synchronous api for allocating an io.
     453             :  */
     454             : 
     455             : void *
     456           0 : scsi_io_get(struct scsi_iopool *iopl, int flags)
     457             : {
     458           0 :         struct scsi_io_mover m = SCSI_IO_MOVER_INITIALIZER;
     459           0 :         struct scsi_iohandler ioh;
     460             :         void *io;
     461             : 
     462             :         /* try and sneak an io off the backend immediately */
     463           0 :         io = scsi_iopool_get(iopl);
     464           0 :         if (io != NULL)
     465           0 :                 return (io);
     466           0 :         else if (ISSET(flags, SCSI_NOSLEEP))
     467           0 :                 return (NULL);
     468             : 
     469             :         /* otherwise sleep until we get one */
     470           0 :         scsi_ioh_set(&ioh, iopl, scsi_io_get_done, &m);
     471           0 :         scsi_ioh_add(&ioh);
     472           0 :         scsi_move(&m);
     473             : 
     474           0 :         return (m.io);
     475           0 : }
     476             : 
     477             : void
     478           0 : scsi_io_get_done(void *cookie, void *io)
     479             : {
     480           0 :         scsi_move_done(cookie, io);
     481           0 : }
     482             : 
     483             : void
     484           0 : scsi_io_put(struct scsi_iopool *iopl, void *io)
     485             : {
     486           0 :         scsi_iopool_put(iopl, io);
     487           0 :         scsi_iopool_run(iopl);
     488           0 : }
     489             : 
     490             : /*
     491             :  * public interface to the xsh api.
     492             :  */
     493             : 
     494             : void
     495           0 : scsi_xsh_set(struct scsi_xshandler *xsh, struct scsi_link *link,
     496             :     void (*handler)(struct scsi_xfer *))
     497             : {
     498           0 :         scsi_ioh_set(&xsh->ioh, link->pool, scsi_xsh_ioh, xsh);
     499             : 
     500           0 :         xsh->link = link;
     501           0 :         xsh->handler = handler;
     502           0 : }
     503             : 
     504             : int
     505           0 : scsi_xsh_add(struct scsi_xshandler *xsh)
     506             : {
     507           0 :         struct scsi_link *link = xsh->link;
     508             :         int rv = 0;
     509             : 
     510           0 :         if (ISSET(link->state, SDEV_S_DYING))
     511           0 :                 return (0);
     512             : 
     513           0 :         mtx_enter(&link->pool->mtx);
     514           0 :         if (xsh->ioh.q_state == RUNQ_IDLE) {
     515           0 :                 TAILQ_INSERT_TAIL(&link->queue, &xsh->ioh, q_entry);
     516           0 :                 xsh->ioh.q_state = RUNQ_LINKQ;
     517             :                 rv = 1;
     518           0 :         }
     519           0 :         mtx_leave(&link->pool->mtx);
     520             : 
     521             :         /* lets get some io up in the air */
     522           0 :         scsi_xsh_runqueue(link);
     523             : 
     524           0 :         return (rv);
     525           0 : }
     526             : 
     527             : int
     528           0 : scsi_xsh_del(struct scsi_xshandler *xsh)
     529             : {
     530           0 :         struct scsi_link *link = xsh->link;
     531             :         int rv = 1;
     532             : 
     533           0 :         mtx_enter(&link->pool->mtx);
     534           0 :         switch (xsh->ioh.q_state) {
     535             :         case RUNQ_IDLE:
     536             :                 rv = 0;
     537           0 :                 break;
     538             :         case RUNQ_LINKQ:
     539           0 :                 TAILQ_REMOVE(&link->queue, &xsh->ioh, q_entry);
     540           0 :                 break;
     541             :         case RUNQ_POOLQ:
     542           0 :                 TAILQ_REMOVE(&link->pool->queue, &xsh->ioh, q_entry);
     543           0 :                 link->pending--;
     544           0 :                 if (ISSET(link->state, SDEV_S_DYING) && link->pending == 0)
     545           0 :                         wakeup_one(&link->pending);
     546             :                 break;
     547             :         default:
     548           0 :                 panic("unexpected xsh state %u", xsh->ioh.q_state);
     549             :         }
     550           0 :         xsh->ioh.q_state = RUNQ_IDLE;
     551           0 :         mtx_leave(&link->pool->mtx);
     552             : 
     553           0 :         return (rv);
     554             : }
     555             : 
     556             : /*
     557             :  * internal xs runqueue handling.
     558             :  */
     559             : 
     560             : void
     561           0 : scsi_xsh_runqueue(struct scsi_link *link)
     562             : {
     563             :         struct scsi_iohandler *ioh;
     564             :         int runq;
     565             : 
     566           0 :         if (!scsi_pending_start(&link->pool->mtx, &link->running))
     567           0 :                 return;
     568           0 :         do {
     569             :                 runq = 0;
     570             : 
     571           0 :                 mtx_enter(&link->pool->mtx);
     572           0 :                 while (!ISSET(link->state, SDEV_S_DYING) &&
     573           0 :                     link->pending < link->openings &&
     574           0 :                     ((ioh = TAILQ_FIRST(&link->queue)) != NULL)) {
     575           0 :                         link->pending++;
     576             : 
     577           0 :                         TAILQ_REMOVE(&link->queue, ioh, q_entry);
     578           0 :                         TAILQ_INSERT_TAIL(&link->pool->queue, ioh, q_entry);
     579           0 :                         ioh->q_state = RUNQ_POOLQ;
     580             : 
     581             :                         runq = 1;
     582             :                 }
     583           0 :                 mtx_leave(&link->pool->mtx);
     584             : 
     585           0 :                 if (runq)
     586           0 :                         scsi_iopool_run(link->pool);
     587           0 :         } while (!scsi_pending_finish(&link->pool->mtx, &link->running));
     588           0 : }
     589             : 
     590             : void
     591           0 : scsi_xsh_ioh(void *cookie, void *io)
     592             : {
     593           0 :         struct scsi_xshandler *xsh = cookie;
     594             :         struct scsi_xfer *xs;
     595             : 
     596           0 :         xs = scsi_xs_io(xsh->link, io, SCSI_NOSLEEP);
     597           0 :         if (xs == NULL) {
     598             :                 /*
     599             :                  * in this situation we should queue things waiting for an
     600             :                  * xs and then give them xses when they were supposed be to
     601             :                  * returned to the pool.
     602             :                  */
     603             : 
     604           0 :                 printf("scsi_xfer pool exhausted!\n");
     605           0 :                 scsi_xsh_add(xsh);
     606           0 :                 return;
     607             :         }
     608             : 
     609           0 :         xsh->handler(xs);
     610           0 : }
     611             : 
     612             : /*
     613             :  * Get a scsi transfer structure for the caller.
     614             :  * Go to the iopool backend for an "opening" and then attach an xs to it.
     615             :  */
     616             : 
     617             : struct scsi_xfer *
     618           0 : scsi_xs_get(struct scsi_link *link, int flags)
     619             : {
     620           0 :         struct scsi_xshandler xsh;
     621           0 :         struct scsi_io_mover m = SCSI_IO_MOVER_INITIALIZER;
     622             : 
     623           0 :         struct scsi_iopool *iopl = link->pool;
     624             :         void *io;
     625             : 
     626           0 :         if (ISSET(link->state, SDEV_S_DYING))
     627           0 :                 return (NULL);
     628             : 
     629             :         /* really custom xs handler to avoid scsi_xsh_ioh */
     630           0 :         scsi_ioh_set(&xsh.ioh, iopl, scsi_xs_get_done, &m);
     631           0 :         xsh.link = link;
     632             : 
     633           0 :         if (!scsi_link_open(link)) {
     634           0 :                 if (ISSET(flags, SCSI_NOSLEEP))
     635           0 :                         return (NULL);
     636             : 
     637           0 :                 scsi_xsh_add(&xsh);
     638           0 :                 scsi_move(&m);
     639           0 :                 if (m.io == NULL)
     640           0 :                         return (NULL);
     641             : 
     642             :                 io = m.io;
     643           0 :         } else if ((io = scsi_iopool_get(iopl)) == NULL) {
     644           0 :                 if (ISSET(flags, SCSI_NOSLEEP)) {
     645           0 :                         scsi_link_close(link);
     646           0 :                         return (NULL);
     647             :                 }
     648             : 
     649           0 :                 scsi_ioh_add(&xsh.ioh);
     650           0 :                 scsi_move(&m);
     651           0 :                 if (m.io == NULL)
     652           0 :                         return (NULL);
     653             : 
     654             :                 io = m.io;
     655           0 :         }
     656             : 
     657           0 :         return (scsi_xs_io(link, io, flags));
     658           0 : }
     659             : 
     660             : void
     661           0 : scsi_xs_get_done(void *cookie, void *io)
     662             : {
     663           0 :         scsi_move_done(cookie, io);
     664           0 : }
     665             : 
     666             : void
     667           0 : scsi_link_shutdown(struct scsi_link *link)
     668             : {
     669           0 :         struct scsi_runq sleepers = TAILQ_HEAD_INITIALIZER(sleepers);
     670           0 :         struct scsi_iopool *iopl = link->pool;
     671             :         struct scsi_iohandler *ioh;
     672             :         struct scsi_xshandler *xsh;
     673             : 
     674           0 :         mtx_enter(&iopl->mtx);
     675           0 :         while ((ioh = TAILQ_FIRST(&link->queue)) != NULL) {
     676           0 :                 TAILQ_REMOVE(&link->queue, ioh, q_entry);
     677           0 :                 ioh->q_state = RUNQ_IDLE;
     678             : 
     679           0 :                 if (ioh->handler == scsi_xs_get_done)
     680           0 :                         TAILQ_INSERT_TAIL(&sleepers, ioh, q_entry);
     681             : #ifdef DIAGNOSTIC
     682             :                 else
     683           0 :                         panic("scsi_link_shutdown: scsi_xshandler on link");
     684             : #endif
     685             :         }
     686             : 
     687           0 :         ioh = TAILQ_FIRST(&iopl->queue);
     688           0 :         while (ioh != NULL) {
     689           0 :                 xsh = (struct scsi_xshandler *)ioh;
     690           0 :                 ioh = TAILQ_NEXT(ioh, q_entry);
     691             : 
     692             : #ifdef DIAGNOSTIC
     693           0 :                 if (xsh->ioh.handler == scsi_xsh_ioh &&
     694           0 :                     xsh->link == link)
     695           0 :                         panic("scsi_link_shutdown: scsi_xshandler on pool");
     696             : #endif
     697             : 
     698           0 :                 if (xsh->ioh.handler == scsi_xs_get_done &&
     699           0 :                     xsh->link == link) {
     700           0 :                         TAILQ_REMOVE(&iopl->queue, &xsh->ioh, q_entry);
     701           0 :                         xsh->ioh.q_state = RUNQ_IDLE;
     702           0 :                         link->pending--;
     703             : 
     704           0 :                         TAILQ_INSERT_TAIL(&sleepers, &xsh->ioh, q_entry);
     705           0 :                 }
     706             :         }
     707             : 
     708           0 :         while (link->pending > 0)
     709           0 :                 msleep(&link->pending, &iopl->mtx, PRIBIO, "pendxs", 0);
     710           0 :         mtx_leave(&iopl->mtx);
     711             : 
     712           0 :         while ((ioh = TAILQ_FIRST(&sleepers)) != NULL) {
     713           0 :                 TAILQ_REMOVE(&sleepers, ioh, q_entry);
     714           0 :                 ioh->handler(ioh->cookie, NULL);
     715             :         }
     716           0 : }
     717             : 
     718             : int
     719           0 : scsi_link_open(struct scsi_link *link)
     720             : {
     721             :         int open = 0;
     722             : 
     723           0 :         mtx_enter(&link->pool->mtx);
     724           0 :         if (link->pending < link->openings) {
     725           0 :                 link->pending++;
     726             :                 open = 1;
     727           0 :         }
     728           0 :         mtx_leave(&link->pool->mtx);
     729             : 
     730           0 :         return (open);
     731             : }
     732             : 
     733             : void
     734           0 : scsi_link_close(struct scsi_link *link)
     735             : {
     736           0 :         mtx_enter(&link->pool->mtx);
     737           0 :         link->pending--;
     738           0 :         if (ISSET(link->state, SDEV_S_DYING) && link->pending == 0)
     739           0 :                 wakeup_one(&link->pending);
     740           0 :         mtx_leave(&link->pool->mtx);
     741             : 
     742           0 :         scsi_xsh_runqueue(link);
     743           0 : }
     744             : 
     745             : struct scsi_xfer *
     746           0 : scsi_xs_io(struct scsi_link *link, void *io, int flags)
     747             : {
     748             :         struct scsi_xfer *xs;
     749             : 
     750           0 :         xs = pool_get(&scsi_xfer_pool, PR_ZERO |
     751           0 :             (ISSET(flags, SCSI_NOSLEEP) ? PR_NOWAIT : PR_WAITOK));
     752           0 :         if (xs == NULL) {
     753           0 :                 scsi_io_put(link->pool, io);
     754           0 :                 scsi_link_close(link);
     755           0 :         } else {
     756           0 :                 xs->flags = flags;
     757           0 :                 xs->sc_link = link;
     758           0 :                 xs->retries = SCSI_RETRIES;
     759           0 :                 xs->timeout = 10000;
     760           0 :                 xs->cmd = &xs->cmdstore;
     761           0 :                 xs->io = io;
     762             :         }
     763             : 
     764           0 :         return (xs);
     765             : }
     766             : 
     767             : void
     768           0 : scsi_xs_put(struct scsi_xfer *xs)
     769             : {
     770           0 :         struct scsi_link *link = xs->sc_link;
     771           0 :         void *io = xs->io;
     772             : 
     773           0 :         pool_put(&scsi_xfer_pool, xs);
     774             : 
     775           0 :         scsi_io_put(link->pool, io);
     776           0 :         scsi_link_close(link);
     777           0 : }
     778             : 
     779             : /*
     780             :  * Get scsi driver to send a "are you ready?" command
     781             :  */
     782             : int
     783           0 : scsi_test_unit_ready(struct scsi_link *link, int retries, int flags)
     784             : {
     785             :         struct scsi_test_unit_ready *cmd;
     786             :         struct scsi_xfer *xs;
     787             :         int error;
     788             : 
     789           0 :         xs = scsi_xs_get(link, flags);
     790           0 :         if (xs == NULL)
     791           0 :                 return (ENOMEM);
     792           0 :         xs->cmdlen = sizeof(*cmd);
     793           0 :         xs->retries = retries;
     794           0 :         xs->timeout = 10000;
     795             : 
     796           0 :         cmd = (struct scsi_test_unit_ready *)xs->cmd;
     797           0 :         cmd->opcode = TEST_UNIT_READY;
     798             : 
     799           0 :         error = scsi_xs_sync(xs);
     800           0 :         scsi_xs_put(xs);
     801             : 
     802           0 :         return (error);
     803           0 : }
     804             : 
     805             : void
     806           0 : scsi_init_inquiry(struct scsi_xfer *xs, u_int8_t flags, u_int8_t pagecode,
     807             :     void *data, size_t len)
     808             : {
     809             :         struct scsi_inquiry *cmd;
     810             : 
     811           0 :         cmd = (struct scsi_inquiry *)xs->cmd;
     812           0 :         cmd->opcode = INQUIRY;
     813           0 :         cmd->flags = flags;
     814           0 :         cmd->pagecode = pagecode;
     815           0 :         _lto2b(len, cmd->length);
     816             : 
     817           0 :         xs->cmdlen = sizeof(*cmd);
     818             : 
     819           0 :         xs->flags |= SCSI_DATA_IN;
     820           0 :         xs->data = data;
     821           0 :         xs->datalen = len;
     822           0 : }
     823             : 
     824             : /*
     825             :  * Do a scsi operation asking a device what it is.
     826             :  * Use the scsi_cmd routine in the switch table.
     827             :  */
     828             : int
     829           0 : scsi_inquire(struct scsi_link *link, struct scsi_inquiry_data *inqbuf,
     830             :     int flags)
     831             : {
     832             :         struct scsi_xfer *xs;
     833             :         int error;
     834             : 
     835           0 :         xs = scsi_xs_get(link, flags);
     836           0 :         if (xs == NULL)
     837           0 :                 return (EBUSY);
     838             : 
     839             :         /*
     840             :          * Ask for only the basic 36 bytes of SCSI2 inquiry information. This
     841             :          * avoids problems with devices that choke trying to supply more.
     842             :          */
     843           0 :         scsi_init_inquiry(xs, 0, 0, inqbuf, SID_INQUIRY_HDR + SID_SCSI2_ALEN);
     844             : 
     845           0 :         bzero(inqbuf, sizeof(*inqbuf));
     846           0 :         memset(&inqbuf->vendor, ' ', sizeof inqbuf->vendor);
     847           0 :         memset(&inqbuf->product, ' ', sizeof inqbuf->product);
     848           0 :         memset(&inqbuf->revision, ' ', sizeof inqbuf->revision);
     849           0 :         memset(&inqbuf->extra, ' ', sizeof inqbuf->extra);
     850             : 
     851           0 :         error = scsi_xs_sync(xs);
     852             : 
     853           0 :         scsi_xs_put(xs);
     854             : 
     855           0 :         return (error);
     856           0 : }
     857             : 
     858             : /*
     859             :  * Query a VPD inquiry page
     860             :  */
     861             : int
     862           0 : scsi_inquire_vpd(struct scsi_link *link, void *buf, u_int buflen,
     863             :     u_int8_t page, int flags)
     864             : {
     865             :         struct scsi_xfer *xs;
     866             :         int error;
     867             : 
     868           0 :         if (link->flags & SDEV_UMASS)
     869           0 :                 return (EJUSTRETURN);
     870             : 
     871           0 :         xs = scsi_xs_get(link, flags | SCSI_DATA_IN | SCSI_SILENT);
     872           0 :         if (xs == NULL)
     873           0 :                 return (ENOMEM);
     874             : 
     875           0 :         xs->retries = 2;
     876           0 :         xs->timeout = 10000;
     877             : 
     878           0 :         scsi_init_inquiry(xs, SI_EVPD, page, buf, buflen);
     879             : 
     880           0 :         error = scsi_xs_sync(xs);
     881             : 
     882           0 :         scsi_xs_put(xs);
     883             : 
     884           0 :         return (error);
     885           0 : }
     886             : 
     887             : /*
     888             :  * Prevent or allow the user to remove the media
     889             :  */
     890             : int
     891           0 : scsi_prevent(struct scsi_link *link, int type, int flags)
     892             : {
     893             :         struct scsi_prevent *cmd;
     894             :         struct scsi_xfer *xs;
     895             :         int error;
     896             : 
     897           0 :         if (link->quirks & ADEV_NODOORLOCK)
     898           0 :                 return (0);
     899             : 
     900           0 :         xs = scsi_xs_get(link, flags);
     901           0 :         if (xs == NULL)
     902           0 :                 return (ENOMEM);
     903           0 :         xs->cmdlen = sizeof(*cmd);
     904           0 :         xs->retries = 2;
     905           0 :         xs->timeout = 5000;
     906             : 
     907           0 :         cmd = (struct scsi_prevent *)xs->cmd;
     908           0 :         cmd->opcode = PREVENT_ALLOW;
     909           0 :         cmd->how = type;
     910             : 
     911           0 :         error = scsi_xs_sync(xs);
     912           0 :         scsi_xs_put(xs);
     913             : 
     914           0 :         return (error);
     915           0 : }
     916             : 
     917             : /*
     918             :  * Get scsi driver to send a "start up" command
     919             :  */
     920             : int
     921           0 : scsi_start(struct scsi_link *link, int type, int flags)
     922             : {
     923             :         struct scsi_start_stop *cmd;
     924             :         struct scsi_xfer *xs;
     925             :         int error;
     926             : 
     927           0 :         xs = scsi_xs_get(link, flags);
     928           0 :         if (xs == NULL)
     929           0 :                 return (ENOMEM);
     930           0 :         xs->cmdlen = sizeof(*cmd);
     931           0 :         xs->retries = 2;
     932           0 :         xs->timeout = (type == SSS_START) ? 30000 : 10000;
     933             : 
     934           0 :         cmd = (struct scsi_start_stop *)xs->cmd;
     935           0 :         cmd->opcode = START_STOP;
     936           0 :         cmd->how = type;
     937             : 
     938           0 :         error = scsi_xs_sync(xs);
     939           0 :         scsi_xs_put(xs);
     940             : 
     941           0 :         return (error);
     942           0 : }
     943             : 
     944             : int
     945           0 : scsi_mode_sense(struct scsi_link *link, int byte2, int page,
     946             :     struct scsi_mode_header *data, size_t len, int flags, int timeout)
     947             : {
     948             :         struct scsi_mode_sense *cmd;
     949             :         struct scsi_xfer *xs;
     950             :         int error;
     951             : 
     952           0 :         xs = scsi_xs_get(link, flags | SCSI_DATA_IN);
     953           0 :         if (xs == NULL)
     954           0 :                 return (ENOMEM);
     955           0 :         xs->cmdlen = sizeof(*cmd);
     956           0 :         xs->data = (void *)data;
     957           0 :         xs->datalen = len;
     958           0 :         xs->timeout = timeout;
     959             : 
     960             :         /*
     961             :          * Make sure the sense buffer is clean before we do the mode sense, so
     962             :          * that checks for bogus values of 0 will work in case the mode sense
     963             :          * fails.
     964             :          */
     965           0 :         bzero(data, len);
     966             : 
     967           0 :         cmd = (struct scsi_mode_sense *)xs->cmd;
     968           0 :         cmd->opcode = MODE_SENSE;
     969           0 :         cmd->byte2 = byte2;
     970           0 :         cmd->page = page;
     971             : 
     972           0 :         if (len > 0xff)
     973           0 :                 len = 0xff;
     974           0 :         cmd->length = len;
     975             : 
     976           0 :         error = scsi_xs_sync(xs);
     977           0 :         scsi_xs_put(xs);
     978             : 
     979             :         SC_DEBUG(link, SDEV_DB2, ("scsi_mode_sense: page %#x, error = %d\n",
     980             :             page, error));
     981             : 
     982           0 :         return (error);
     983           0 : }
     984             : 
     985             : int
     986           0 : scsi_mode_sense_big(struct scsi_link *link, int byte2, int page,
     987             :     struct scsi_mode_header_big *data, size_t len, int flags, int timeout)
     988             : {
     989             :         struct scsi_mode_sense_big *cmd;
     990             :         struct scsi_xfer *xs;
     991             :         int error;
     992             : 
     993           0 :         xs = scsi_xs_get(link, flags | SCSI_DATA_IN);
     994           0 :         if (xs == NULL)
     995           0 :                 return (ENOMEM);
     996           0 :         xs->cmdlen = sizeof(*cmd);
     997           0 :         xs->data = (void *)data;
     998           0 :         xs->datalen = len;
     999           0 :         xs->timeout = timeout;
    1000             : 
    1001             :         /*
    1002             :          * Make sure the sense buffer is clean before we do the mode sense, so
    1003             :          * that checks for bogus values of 0 will work in case the mode sense
    1004             :          * fails.
    1005             :          */
    1006           0 :         bzero(data, len);
    1007             : 
    1008           0 :         cmd = (struct scsi_mode_sense_big *)xs->cmd;
    1009           0 :         cmd->opcode = MODE_SENSE_BIG;
    1010           0 :         cmd->byte2 = byte2;
    1011           0 :         cmd->page = page;
    1012             : 
    1013           0 :         if (len > 0xffff)
    1014           0 :                 len = 0xffff;
    1015           0 :         _lto2b(len, cmd->length);
    1016             : 
    1017           0 :         error = scsi_xs_sync(xs);
    1018           0 :         scsi_xs_put(xs);
    1019             : 
    1020             :         SC_DEBUG(link, SDEV_DB2,
    1021             :             ("scsi_mode_sense_big: page %#x, error = %d\n", page, error));
    1022             : 
    1023           0 :         return (error);
    1024           0 : }
    1025             : 
    1026             : void *
    1027           0 : scsi_mode_sense_page(struct scsi_mode_header *hdr, const int page_len)
    1028             : {
    1029             :         int                                     total_length, header_length;
    1030             : 
    1031           0 :         total_length = hdr->data_length + sizeof(hdr->data_length);
    1032           0 :         header_length = sizeof(*hdr) + hdr->blk_desc_len;
    1033             : 
    1034           0 :         if ((total_length - header_length) < page_len)
    1035           0 :                 return (NULL);
    1036             : 
    1037           0 :         return ((u_char *)hdr + header_length);
    1038           0 : }
    1039             : 
    1040             : void *
    1041           0 : scsi_mode_sense_big_page(struct scsi_mode_header_big *hdr, const int page_len)
    1042             : {
    1043             :         int                                     total_length, header_length;
    1044             : 
    1045           0 :         total_length = _2btol(hdr->data_length) + sizeof(hdr->data_length);
    1046           0 :         header_length = sizeof(*hdr) + _2btol(hdr->blk_desc_len);
    1047             : 
    1048           0 :         if ((total_length - header_length) < page_len)
    1049           0 :                 return (NULL);
    1050             : 
    1051           0 :         return ((u_char *)hdr + header_length);
    1052           0 : }
    1053             : 
    1054             : int
    1055           0 : scsi_do_mode_sense(struct scsi_link *link, int page,
    1056             :     union scsi_mode_sense_buf *buf, void **page_data, u_int32_t *density,
    1057             :     u_int64_t *block_count, u_int32_t *block_size, int page_len, int flags,
    1058             :     int *big)
    1059             : {
    1060             :         struct scsi_direct_blk_desc             *direct;
    1061             :         struct scsi_blk_desc                    *general;
    1062             :         int                                     error, blk_desc_len, offset;
    1063             : 
    1064           0 :         *page_data = NULL;
    1065             : 
    1066           0 :         if (density != NULL)
    1067           0 :                 *density = 0;
    1068           0 :         if (block_count != NULL)
    1069           0 :                 *block_count = 0;
    1070           0 :         if (block_size != NULL)
    1071           0 :                 *block_size = 0;
    1072           0 :         if (big != NULL)
    1073           0 :                 *big = 0;
    1074             : 
    1075           0 :         if ((link->flags & SDEV_ATAPI) == 0 ||
    1076           0 :             (link->inqdata.device & SID_TYPE) == T_SEQUENTIAL) {
    1077             :                 /*
    1078             :                  * Try 6 byte mode sense request first. Some devices don't
    1079             :                  * distinguish between 6 and 10 byte MODE SENSE commands,
    1080             :                  * returning 6 byte data for 10 byte requests. ATAPI tape
    1081             :                  * drives use MODE SENSE (6) even though ATAPI uses 10 byte
    1082             :                  * everything else. Don't bother with SMS_DBD. Check returned
    1083             :                  * data length to ensure that at least a header (3 additional
    1084             :                  * bytes) is returned.
    1085             :                  */
    1086           0 :                 error = scsi_mode_sense(link, 0, page, &buf->hdr,
    1087             :                     sizeof(*buf), flags, 20000);
    1088           0 :                 if (error == 0) {
    1089           0 :                         *page_data = scsi_mode_sense_page(&buf->hdr, page_len);
    1090           0 :                         if (*page_data == NULL) {
    1091             :                                 /*
    1092             :                                  * XXX
    1093             :                                  * Page data may be invalid (e.g. all zeros)
    1094             :                                  * but we accept the device's word that this is
    1095             :                                  * the best it can do. Some devices will freak
    1096             :                                  * out if their word is not accepted and
    1097             :                                  * MODE_SENSE_BIG is attempted.
    1098             :                                  */
    1099           0 :                                 return (0);
    1100             :                         }
    1101             :                         offset = sizeof(struct scsi_mode_header);
    1102           0 :                         blk_desc_len = buf->hdr.blk_desc_len;
    1103           0 :                         goto blk_desc;
    1104             :                 }
    1105             :         }
    1106             : 
    1107             :         /*
    1108             :          * Try 10 byte mode sense request. Don't bother with SMS_DBD or
    1109             :          * SMS_LLBAA. Bail out if the returned information is less than
    1110             :          * a big header in size (6 additional bytes).
    1111             :          */
    1112           0 :         if ((link->flags & (SDEV_ATAPI | SDEV_UMASS)) == 0 &&
    1113           0 :             SCSISPC(link->inqdata.version) < 2) {
    1114             :                 /*
    1115             :                  * The 10 byte MODE_SENSE request appeared with SCSI-2,
    1116             :                  * so don't bother trying it on SCSI-1 devices, they are
    1117             :                  * not supposed to understand it.
    1118             :                  */
    1119           0 :                 return (0);
    1120             :         }
    1121           0 :         error = scsi_mode_sense_big(link, 0, page, &buf->hdr_big,
    1122             :             sizeof(*buf), flags, 20000);
    1123           0 :         if (error != 0)
    1124           0 :                 return (error);
    1125           0 :         if (_2btol(buf->hdr_big.data_length) < 6)
    1126           0 :                 return (EIO);
    1127             : 
    1128           0 :         if (big != NULL)
    1129           0 :                 *big = 1;
    1130             :         offset = sizeof(struct scsi_mode_header_big);
    1131           0 :         *page_data = scsi_mode_sense_big_page(&buf->hdr_big, page_len);
    1132           0 :         blk_desc_len = _2btol(buf->hdr_big.blk_desc_len);
    1133             : 
    1134             : blk_desc:
    1135             :         /* Both scsi_blk_desc and scsi_direct_blk_desc are 8 bytes. */
    1136           0 :         if (blk_desc_len == 0 || (blk_desc_len % 8 != 0))
    1137           0 :                 return (0);
    1138             : 
    1139           0 :         switch (link->inqdata.device & SID_TYPE) {
    1140             :         case T_SEQUENTIAL:
    1141             :                 /*
    1142             :                  * XXX What other device types return general block descriptors?
    1143             :                  */
    1144           0 :                 general = (struct scsi_blk_desc *)&buf->buf[offset];
    1145           0 :                 if (density != NULL)
    1146           0 :                         *density = general->density;
    1147           0 :                 if (block_size != NULL)
    1148           0 :                         *block_size = _3btol(general->blklen);
    1149           0 :                 if (block_count != NULL)
    1150           0 :                         *block_count = (u_int64_t)_3btol(general->nblocks);
    1151             :                 break;
    1152             : 
    1153             :         default:
    1154           0 :                 direct = (struct scsi_direct_blk_desc *)&buf->buf[offset];
    1155           0 :                 if (density != NULL)
    1156           0 :                         *density = direct->density;
    1157           0 :                 if (block_size != NULL)
    1158           0 :                         *block_size = _3btol(direct->blklen);
    1159           0 :                 if (block_count != NULL)
    1160           0 :                         *block_count = (u_int64_t)_4btol(direct->nblocks);
    1161             :                 break;
    1162             :         }
    1163             : 
    1164           0 :         return (0);
    1165           0 : }
    1166             : 
    1167             : int
    1168           0 : scsi_mode_select(struct scsi_link *link, int byte2,
    1169             :     struct scsi_mode_header *data, int flags, int timeout)
    1170             : {
    1171             :         struct scsi_mode_select *cmd;
    1172             :         struct scsi_xfer *xs;
    1173             :         u_int32_t len;
    1174             :         int error;
    1175             : 
    1176           0 :         len = data->data_length + 1; /* 1 == sizeof(data_length) */
    1177             : 
    1178           0 :         xs = scsi_xs_get(link, flags | SCSI_DATA_OUT);
    1179           0 :         if (xs == NULL)
    1180           0 :                 return (ENOMEM);
    1181           0 :         xs->cmdlen = sizeof(*cmd);
    1182           0 :         xs->data = (void *)data;
    1183           0 :         xs->datalen = len;
    1184           0 :         xs->timeout = timeout;
    1185             : 
    1186           0 :         cmd = (struct scsi_mode_select *)xs->cmd;
    1187           0 :         cmd->opcode = MODE_SELECT;
    1188           0 :         cmd->byte2 = byte2;
    1189           0 :         cmd->length = len;
    1190             : 
    1191             :         /* Length is reserved when doing mode select so zero it. */
    1192           0 :         data->data_length = 0;
    1193             : 
    1194           0 :         error = scsi_xs_sync(xs);
    1195           0 :         scsi_xs_put(xs);
    1196             : 
    1197             :         SC_DEBUG(link, SDEV_DB2, ("scsi_mode_select: error = %d\n", error));
    1198             : 
    1199           0 :         return (error);
    1200           0 : }
    1201             : 
    1202             : int
    1203           0 : scsi_mode_select_big(struct scsi_link *link, int byte2,
    1204             :     struct scsi_mode_header_big *data, int flags, int timeout)
    1205             : {
    1206             :         struct scsi_mode_select_big *cmd;
    1207             :         struct scsi_xfer *xs;
    1208             :         u_int32_t len;
    1209             :         int error;
    1210             : 
    1211           0 :         len = _2btol(data->data_length) + 2; /* 2 == sizeof data_length */
    1212             : 
    1213           0 :         xs = scsi_xs_get(link, flags | SCSI_DATA_OUT);
    1214           0 :         if (xs == NULL)
    1215           0 :                 return (ENOMEM);
    1216           0 :         xs->cmdlen = sizeof(*cmd);
    1217           0 :         xs->data = (void *)data;
    1218           0 :         xs->datalen = len;
    1219           0 :         xs->timeout = timeout;
    1220             : 
    1221           0 :         cmd = (struct scsi_mode_select_big *)xs->cmd;
    1222           0 :         cmd->opcode = MODE_SELECT_BIG;
    1223           0 :         cmd->byte2 = byte2;
    1224           0 :         _lto2b(len, cmd->length);
    1225             : 
    1226             :         /* Length is reserved when doing mode select so zero it. */
    1227           0 :         _lto2b(0, data->data_length);
    1228             : 
    1229           0 :         error = scsi_xs_sync(xs);
    1230           0 :         scsi_xs_put(xs);
    1231             : 
    1232             :         SC_DEBUG(link, SDEV_DB2, ("scsi_mode_select_big: error = %d\n",
    1233             :             error));
    1234             : 
    1235           0 :         return (error);
    1236           0 : }
    1237             : 
    1238             : int
    1239           0 : scsi_report_luns(struct scsi_link *link, int selectreport,
    1240             :     struct scsi_report_luns_data *data, u_int32_t datalen, int flags,
    1241             :     int timeout)
    1242             : {
    1243             :         struct scsi_report_luns *cmd;
    1244             :         struct scsi_xfer *xs;
    1245             :         int error;
    1246             : 
    1247           0 :         xs = scsi_xs_get(link, flags | SCSI_DATA_IN);
    1248           0 :         if (xs == NULL)
    1249           0 :                 return (ENOMEM);
    1250           0 :         xs->cmdlen = sizeof(*cmd);
    1251           0 :         xs->data = (void *)data;
    1252           0 :         xs->datalen = datalen;
    1253           0 :         xs->timeout = timeout;
    1254             : 
    1255           0 :         bzero(data, datalen);
    1256             : 
    1257           0 :         cmd = (struct scsi_report_luns *)xs->cmd;
    1258           0 :         cmd->opcode = REPORT_LUNS;
    1259           0 :         cmd->selectreport = selectreport;
    1260           0 :         _lto4b(datalen, cmd->length);
    1261             : 
    1262           0 :         error = scsi_xs_sync(xs);
    1263           0 :         scsi_xs_put(xs);
    1264             : 
    1265             :         SC_DEBUG(link, SDEV_DB2, ("scsi_report_luns: error = %d\n", error));
    1266             : 
    1267           0 :         return (error);
    1268           0 : }
    1269             : 
    1270             : void
    1271           0 : scsi_xs_exec(struct scsi_xfer *xs)
    1272             : {
    1273           0 :         xs->error = XS_NOERROR;
    1274           0 :         xs->resid = xs->datalen;
    1275           0 :         xs->status = 0;
    1276           0 :         CLR(xs->flags, ITSDONE);
    1277             : 
    1278             : #ifdef SCSIDEBUG
    1279             :         if (xs->sc_link->flags & SDEV_DB1) {
    1280             :                 scsi_xs_show(xs);
    1281             :                 if (xs->datalen && (xs->flags & SCSI_DATA_OUT))
    1282             :                         scsi_show_mem(xs->data, min(64, xs->datalen));
    1283             :         }
    1284             : #endif
    1285             : 
    1286             :         /* The adapter's scsi_cmd() is responsible for calling scsi_done(). */
    1287           0 :         KERNEL_LOCK();
    1288           0 :         xs->sc_link->adapter->scsi_cmd(xs);
    1289           0 :         KERNEL_UNLOCK();
    1290           0 : }
    1291             : 
    1292             : /*
    1293             :  * This routine is called by the adapter when its xs handling is done.
    1294             :  */
    1295             : void
    1296           0 : scsi_done(struct scsi_xfer *xs)
    1297             : {
    1298             : #ifdef SCSIDEBUG
    1299             :         if (xs->sc_link->flags & SDEV_DB1) {
    1300             :                 if (xs->datalen && (xs->flags & SCSI_DATA_IN))
    1301             :                         scsi_show_mem(xs->data, min(64, xs->datalen));
    1302             :         }
    1303             : #endif /* SCSIDEBUG */
    1304             : 
    1305           0 :         SET(xs->flags, ITSDONE);
    1306           0 :         KERNEL_LOCK();
    1307           0 :         xs->done(xs);
    1308           0 :         KERNEL_UNLOCK();
    1309           0 : }
    1310             : 
    1311             : int
    1312           0 : scsi_xs_sync(struct scsi_xfer *xs)
    1313             : {
    1314           0 :         struct mutex cookie = MUTEX_INITIALIZER(IPL_BIO);
    1315             :         int error;
    1316             : 
    1317             : #ifdef DIAGNOSTIC
    1318           0 :         if (xs->cookie != NULL)
    1319           0 :                 panic("xs->cookie != NULL in scsi_xs_sync");
    1320           0 :         if (xs->done != NULL)
    1321           0 :                 panic("xs->done != NULL in scsi_xs_sync");
    1322             : #endif
    1323             : 
    1324             :         /*
    1325             :          * If we cant sleep while waiting for completion, get the adapter to
    1326             :          * complete it for us.
    1327             :          */
    1328           0 :         if (ISSET(xs->flags, SCSI_NOSLEEP))
    1329           0 :                 SET(xs->flags, SCSI_POLL);
    1330             : 
    1331           0 :         xs->done = scsi_xs_sync_done;
    1332             : 
    1333           0 :         do {
    1334           0 :                 xs->cookie = &cookie;
    1335             : 
    1336           0 :                 scsi_xs_exec(xs);
    1337             : 
    1338           0 :                 mtx_enter(&cookie);
    1339           0 :                 while (xs->cookie != NULL)
    1340           0 :                         msleep(xs, &cookie, PRIBIO, "syncxs", 0);
    1341           0 :                 mtx_leave(&cookie);
    1342             : 
    1343           0 :                 error = scsi_xs_error(xs);
    1344           0 :         } while (error == ERESTART);
    1345             : 
    1346           0 :         return (error);
    1347           0 : }
    1348             : 
    1349             : void
    1350           0 : scsi_xs_sync_done(struct scsi_xfer *xs)
    1351             : {
    1352           0 :         struct mutex *cookie = xs->cookie;
    1353             : 
    1354           0 :         if (cookie == NULL)
    1355           0 :                 panic("scsi_done called twice on xs(%p)", xs);
    1356             : 
    1357           0 :         mtx_enter(cookie);
    1358           0 :         xs->cookie = NULL;
    1359           0 :         if (!ISSET(xs->flags, SCSI_NOSLEEP))
    1360           0 :                 wakeup_one(xs);
    1361           0 :         mtx_leave(cookie);
    1362           0 : }
    1363             : 
    1364             : int
    1365           0 : scsi_xs_error(struct scsi_xfer *xs)
    1366             : {
    1367             :         int error = EIO;
    1368             : 
    1369             :         SC_DEBUG(xs->sc_link, SDEV_DB3, ("scsi_xs_error,err = 0x%x\n",
    1370             :             xs->error));
    1371             : 
    1372           0 :         if (ISSET(xs->sc_link->state, SDEV_S_DYING))
    1373           0 :                 return (ENXIO);
    1374             : 
    1375           0 :         switch (xs->error) {
    1376             :         case XS_NOERROR:        /* nearly always hit this one */
    1377             :                 error = 0;
    1378           0 :                 break;
    1379             : 
    1380             :         case XS_SENSE:
    1381             :         case XS_SHORTSENSE:
    1382             : #ifdef SCSIDEBUG
    1383             :                 scsi_sense_print_debug(xs);
    1384             : #endif
    1385           0 :                 error = xs->sc_link->interpret_sense(xs);
    1386             :                 SC_DEBUG(xs->sc_link, SDEV_DB3,
    1387             :                     ("scsi_interpret_sense returned %#x\n", error));
    1388           0 :                 break;
    1389             : 
    1390             :         case XS_BUSY:
    1391           0 :                 error = scsi_delay(xs, 1);
    1392           0 :                 break;
    1393             : 
    1394             :         case XS_TIMEOUT:
    1395             :         case XS_RESET:
    1396             :                 error = ERESTART;
    1397           0 :                 break;
    1398             : 
    1399             :         case XS_DRIVER_STUFFUP:
    1400             :         case XS_SELTIMEOUT:
    1401             :                 break;
    1402             : 
    1403             :         default:
    1404           0 :                 sc_print_addr(xs->sc_link);
    1405           0 :                 printf("unknown error category (0x%x) from scsi driver\n",
    1406           0 :                     xs->error);
    1407           0 :                 break;
    1408             :         }
    1409             : 
    1410           0 :         if (error == ERESTART && xs->retries-- < 1)
    1411           0 :                 return (EIO);
    1412             :         else
    1413           0 :                 return (error);
    1414           0 : }
    1415             : 
    1416             : int
    1417           0 : scsi_delay(struct scsi_xfer *xs, int seconds)
    1418             : {
    1419           0 :         switch (xs->flags & (SCSI_POLL | SCSI_NOSLEEP)) {
    1420             :         case SCSI_POLL:
    1421           0 :                 delay(1000000 * seconds);
    1422           0 :                 return (ERESTART);
    1423             :         case SCSI_NOSLEEP:
    1424             :                 /* Retry the command immediately since we can't delay. */
    1425           0 :                 return (ERESTART);
    1426             :         case (SCSI_POLL | SCSI_NOSLEEP):
    1427             :                 /* Invalid combination! */
    1428           0 :                 return (EIO);
    1429             :         }
    1430             : 
    1431           0 :         while (seconds-- > 0) {
    1432           0 :                 if (tsleep(&lbolt, PRIBIO|PCATCH, "scbusy", 0)) {
    1433             :                         /* Signal == abort xs. */
    1434           0 :                         return (EIO);
    1435             :                 }
    1436             :         }
    1437             : 
    1438           0 :         return (ERESTART);
    1439           0 : }
    1440             : 
    1441             : #ifdef SCSIDEBUG
    1442             : /*
    1443             :  * Print out sense data details.
    1444             :  */
    1445             : void
    1446             : scsi_sense_print_debug(struct scsi_xfer *xs)
    1447             : {
    1448             :         struct scsi_sense_data *sense = &xs->sense;
    1449             :         struct scsi_link *link = xs->sc_link;
    1450             : 
    1451             :         SC_DEBUG(link, SDEV_DB1,
    1452             :             ("code:%#x valid:%d key:%#x ili:%d eom:%d fmark:%d extra:%d\n",
    1453             :             sense->error_code & SSD_ERRCODE,
    1454             :             sense->error_code & SSD_ERRCODE_VALID ? 1 : 0,
    1455             :             sense->flags & SSD_KEY,
    1456             :             sense->flags & SSD_ILI ? 1 : 0,
    1457             :             sense->flags & SSD_EOM ? 1 : 0,
    1458             :             sense->flags & SSD_FILEMARK ? 1 : 0,
    1459             :             sense->extra_len));
    1460             : 
    1461             :         if (xs->sc_link->flags & SDEV_DB1)
    1462             :                 scsi_show_mem((u_char *)&xs->sense, sizeof(xs->sense));
    1463             : 
    1464             :         scsi_print_sense(xs);
    1465             : }
    1466             : #endif
    1467             : 
    1468             : /*
    1469             :  * Look at the returned sense and act on the error, determining
    1470             :  * the unix error number to pass back.  (0 = report no error)
    1471             :  *
    1472             :  * THIS IS THE DEFAULT ERROR HANDLER
    1473             :  */
    1474             : int
    1475           0 : scsi_interpret_sense(struct scsi_xfer *xs)
    1476             : {
    1477           0 :         struct scsi_sense_data                  *sense = &xs->sense;
    1478           0 :         struct scsi_link                        *link = xs->sc_link;
    1479             :         u_int8_t                                serr, skey;
    1480             :         int                                     error;
    1481             : 
    1482             :         /* Default sense interpretation. */
    1483           0 :         serr = sense->error_code & SSD_ERRCODE;
    1484           0 :         if (serr != SSD_ERRCODE_CURRENT && serr != SSD_ERRCODE_DEFERRED)
    1485           0 :                 skey = 0xff;    /* Invalid value, since key is 4 bit value. */
    1486             :         else
    1487           0 :                 skey = sense->flags & SSD_KEY;
    1488             : 
    1489             :         /*
    1490             :          * Interpret the key/asc/ascq information where appropriate.
    1491             :          */
    1492             :         error = 0;
    1493           0 :         switch (skey) {
    1494             :         case SKEY_NO_SENSE:
    1495             :         case SKEY_RECOVERED_ERROR:
    1496           0 :                 if (xs->resid == xs->datalen)
    1497           0 :                         xs->resid = 0;       /* not short read */
    1498             :                 break;
    1499             :         case SKEY_BLANK_CHECK:
    1500             :         case SKEY_EQUAL:
    1501             :                 break;
    1502             :         case SKEY_NOT_READY:
    1503           0 :                 if ((xs->flags & SCSI_IGNORE_NOT_READY) != 0)
    1504           0 :                         return (0);
    1505             :                 error = EIO;
    1506           0 :                 if (xs->retries) {
    1507           0 :                         switch (ASC_ASCQ(sense)) {
    1508             :                         case SENSE_NOT_READY_BECOMING_READY:
    1509             :                         case SENSE_NOT_READY_FORMAT:
    1510             :                         case SENSE_NOT_READY_REBUILD:
    1511             :                         case SENSE_NOT_READY_RECALC:
    1512             :                         case SENSE_NOT_READY_INPROGRESS:
    1513             :                         case SENSE_NOT_READY_LONGWRITE:
    1514             :                         case SENSE_NOT_READY_SELFTEST:
    1515             :                         case SENSE_NOT_READY_INIT_REQUIRED:
    1516             :                                 SC_DEBUG(link, SDEV_DB1,
    1517             :                                     ("not ready (ASC_ASCQ == %#x)\n",
    1518             :                                     ASC_ASCQ(sense)));
    1519           0 :                                 return (scsi_delay(xs, 1));
    1520             :                         case SENSE_NOMEDIUM:
    1521             :                         case SENSE_NOMEDIUM_TCLOSED:
    1522             :                         case SENSE_NOMEDIUM_TOPEN:
    1523             :                         case SENSE_NOMEDIUM_LOADABLE:
    1524             :                         case SENSE_NOMEDIUM_AUXMEM:
    1525           0 :                                 link->flags &= ~SDEV_MEDIA_LOADED;
    1526             :                                 error = ENOMEDIUM;
    1527           0 :                                 break;
    1528             :                         default:
    1529             :                                 break;
    1530             :                         }
    1531             :                 }
    1532             :                 break;
    1533             :         case SKEY_MEDIUM_ERROR:
    1534           0 :                 switch (ASC_ASCQ(sense)) {
    1535             :                 case SENSE_NOMEDIUM:
    1536             :                 case SENSE_NOMEDIUM_TCLOSED:
    1537             :                 case SENSE_NOMEDIUM_TOPEN:
    1538             :                 case SENSE_NOMEDIUM_LOADABLE:
    1539             :                 case SENSE_NOMEDIUM_AUXMEM:
    1540           0 :                         link->flags &= ~SDEV_MEDIA_LOADED;
    1541             :                         error = ENOMEDIUM;
    1542           0 :                         break;
    1543             :                 case SENSE_BAD_MEDIUM:
    1544             :                 case SENSE_NR_MEDIUM_UNKNOWN_FORMAT:
    1545             :                 case SENSE_NR_MEDIUM_INCOMPATIBLE_FORMAT:
    1546             :                 case SENSE_NW_MEDIUM_UNKNOWN_FORMAT:
    1547             :                 case SENSE_NW_MEDIUM_INCOMPATIBLE_FORMAT:
    1548             :                 case SENSE_NF_MEDIUM_INCOMPATIBLE_FORMAT:
    1549             :                 case SENSE_NW_MEDIUM_AC_MISMATCH:
    1550             :                         error = EMEDIUMTYPE;
    1551           0 :                         break;
    1552             :                 default:
    1553             :                         error = EIO;
    1554           0 :                         break;
    1555             :                 }
    1556             :                 break;
    1557             :         case SKEY_ILLEGAL_REQUEST:
    1558           0 :                 if ((xs->flags & SCSI_IGNORE_ILLEGAL_REQUEST) != 0)
    1559           0 :                         return (0);
    1560           0 :                 if (ASC_ASCQ(sense) == SENSE_MEDIUM_REMOVAL_PREVENTED)
    1561           0 :                         return(EBUSY);
    1562             :                 error = EINVAL;
    1563           0 :                 break;
    1564             :         case SKEY_UNIT_ATTENTION:
    1565           0 :                 switch (ASC_ASCQ(sense)) {
    1566             :                 case SENSE_POWER_RESET_OR_BUS:
    1567             :                 case SENSE_POWER_ON:
    1568             :                 case SENSE_BUS_RESET:
    1569             :                 case SENSE_BUS_DEVICE_RESET:
    1570             :                 case SENSE_DEVICE_INTERNAL_RESET:
    1571             :                 case SENSE_TSC_CHANGE_SE:
    1572             :                 case SENSE_TSC_CHANGE_LVD:
    1573             :                 case SENSE_IT_NEXUS_LOSS:
    1574           0 :                         return (scsi_delay(xs, 1));
    1575             :                 default:
    1576             :                         break;
    1577             :                 }
    1578           0 :                 if ((link->flags & SDEV_REMOVABLE) != 0)
    1579           0 :                         link->flags &= ~SDEV_MEDIA_LOADED;
    1580           0 :                 if ((xs->flags & SCSI_IGNORE_MEDIA_CHANGE) != 0 ||
    1581             :                     /* XXX Should reupload any transient state. */
    1582           0 :                     (link->flags & SDEV_REMOVABLE) == 0) {
    1583           0 :                         return (scsi_delay(xs, 1));
    1584             :                 }
    1585             :                 error = EIO;
    1586           0 :                 break;
    1587             :         case SKEY_WRITE_PROTECT:
    1588             :                 error = EROFS;
    1589           0 :                 break;
    1590             :         case SKEY_ABORTED_COMMAND:
    1591             :                 error = ERESTART;
    1592           0 :                 break;
    1593             :         case SKEY_VOLUME_OVERFLOW:
    1594             :                 error = ENOSPC;
    1595           0 :                 break;
    1596             :         case SKEY_HARDWARE_ERROR:
    1597           0 :                 if (ASC_ASCQ(sense) == SENSE_CARTRIDGE_FAULT)
    1598           0 :                         return(EMEDIUMTYPE);
    1599             :                 error = EIO;
    1600           0 :                 break;
    1601             :         default:
    1602             :                 error = EIO;
    1603           0 :                 break;
    1604             :         }
    1605             : 
    1606             : #ifndef SCSIDEBUG
    1607             :         /* SCSIDEBUG would mean it has already been printed. */
    1608           0 :         if (skey && (xs->flags & SCSI_SILENT) == 0)
    1609           0 :                 scsi_print_sense(xs);
    1610             : #endif /* SCSIDEBUG */
    1611             : 
    1612           0 :         return (error);
    1613           0 : }
    1614             : 
    1615             : /*
    1616             :  * Utility routines often used in SCSI stuff
    1617             :  */
    1618             : 
    1619             : 
    1620             : /*
    1621             :  * Print out the scsi_link structure's address info.
    1622             :  */
    1623             : void
    1624           0 : sc_print_addr(struct scsi_link *link)
    1625             : {
    1626           0 :         struct device *adapter_device = link->bus->sc_dev.dv_parent;
    1627             : 
    1628           0 :         printf("%s(%s:%d:%d): ",
    1629           0 :             link->device_softc ?
    1630           0 :             ((struct device *)link->device_softc)->dv_xname : "probe",
    1631           0 :             adapter_device->dv_xname,
    1632           0 :             link->target, link->lun);
    1633           0 : }
    1634             : 
    1635             : static const char *sense_keys[16] = {
    1636             :         "No Additional Sense",
    1637             :         "Soft Error",
    1638             :         "Not Ready",
    1639             :         "Media Error",
    1640             :         "Hardware Error",
    1641             :         "Illegal Request",
    1642             :         "Unit Attention",
    1643             :         "Write Protected",
    1644             :         "Blank Check",
    1645             :         "Vendor Unique",
    1646             :         "Copy Aborted",
    1647             :         "Aborted Command",
    1648             :         "Equal Error",
    1649             :         "Volume Overflow",
    1650             :         "Miscompare Error",
    1651             :         "Reserved"
    1652             : };
    1653             : 
    1654             : #ifdef SCSITERSE
    1655             : static __inline void
    1656             : asc2ascii(u_int8_t asc, u_int8_t ascq, char *result, size_t len)
    1657             : {
    1658             :         snprintf(result, len, "ASC 0x%02x ASCQ 0x%02x", asc, ascq);
    1659             : }
    1660             : #else
    1661             : static const struct {
    1662             :         u_int8_t asc, ascq;
    1663             :         char *description;
    1664             : } adesc[] = {
    1665             :         /* www.t10.org/lists/asc-num.txt as of 11/15/10. */
    1666             :         { 0x00, 0x00, "No Additional Sense Information" },
    1667             :         { 0x00, 0x01, "Filemark Detected" },
    1668             :         { 0x00, 0x02, "End-Of-Partition/Medium Detected" },
    1669             :         { 0x00, 0x03, "Setmark Detected" },
    1670             :         { 0x00, 0x04, "Beginning-Of-Partition/Medium Detected" },
    1671             :         { 0x00, 0x05, "End-Of-Data Detected" },
    1672             :         { 0x00, 0x06, "I/O Process Terminated" },
    1673             :         { 0x00, 0x11, "Audio Play Operation In Progress" },
    1674             :         { 0x00, 0x12, "Audio Play Operation Paused" },
    1675             :         { 0x00, 0x13, "Audio Play Operation Successfully Completed" },
    1676             :         { 0x00, 0x14, "Audio Play Operation Stopped Due to Error" },
    1677             :         { 0x00, 0x15, "No Current Audio Status To Return" },
    1678             :         { 0x00, 0x16, "Operation In Progress" },
    1679             :         { 0x00, 0x17, "Cleaning Requested" },
    1680             :         { 0x00, 0x18, "Erase Operation In Progress" },
    1681             :         { 0x00, 0x19, "Locate Operation In Progress" },
    1682             :         { 0x00, 0x1A, "Rewind Operation In Progress" },
    1683             :         { 0x00, 0x1B, "Set Capacity Operation In Progress" },
    1684             :         { 0x00, 0x1C, "Verify Operation In Progress" },
    1685             :         { 0x01, 0x00, "No Index/Sector Signal" },
    1686             :         { 0x02, 0x00, "No Seek Complete" },
    1687             :         { 0x03, 0x00, "Peripheral Device Write Fault" },
    1688             :         { 0x03, 0x01, "No Write Current" },
    1689             :         { 0x03, 0x02, "Excessive Write Errors" },
    1690             :         { 0x04, 0x00, "Logical Unit Not Ready, Cause Not Reportable" },
    1691             :         { 0x04, 0x01, "Logical Unit Is in Process Of Becoming Ready" },
    1692             :         { 0x04, 0x02, "Logical Unit Not Ready, Initialization Command Required" },
    1693             :         { 0x04, 0x03, "Logical Unit Not Ready, Manual Intervention Required" },
    1694             :         { 0x04, 0x04, "Logical Unit Not Ready, Format In Progress" },
    1695             :         { 0x04, 0x05, "Logical Unit Not Ready, Rebuild In Progress" },
    1696             :         { 0x04, 0x06, "Logical Unit Not Ready, Recalculation In Progress" },
    1697             :         { 0x04, 0x07, "Logical Unit Not Ready, Operation In Progress" },
    1698             :         { 0x04, 0x08, "Logical Unit Not Ready, Long Write In Progress" },
    1699             :         { 0x04, 0x09, "Logical Unit Not Ready, Self-Test In Progress" },
    1700             :         { 0x04, 0x0A, "Logical Unit Not Accessible, Asymmetric Access State Transition" },
    1701             :         { 0x04, 0x0B, "Logical Unit Not Accessible, Target Port In Standby State" },
    1702             :         { 0x04, 0x0C, "Logical Unit Not Accessible, Target Port In Unavailable State" },
    1703             :         { 0x04, 0x0D, "Logical Unit Not Ready, Structure Check Required" },
    1704             :         { 0x04, 0x10, "Logical Unit Not Ready, Auxiliary Memory Not Accessible" },
    1705             :         { 0x04, 0x11, "Logical Unit Not Ready, Notify (Enable Spinup) Required" },
    1706             :         { 0x04, 0x12, "Logical Unit Not Ready, Offline" },
    1707             :         { 0x04, 0x13, "Logical Unit Not Ready, SA Creation In Progress" },
    1708             :         { 0x04, 0x14, "Logical Unit Not Ready, Space Allocation In Progress" },
    1709             :         { 0x04, 0x15, "Logical Unit Not Ready, Robotics Disabled" },
    1710             :         { 0x04, 0x16, "Logical Unit Not Ready, Configuration Required" },
    1711             :         { 0x04, 0x17, "Logical Unit Not Ready, Calibration Required" },
    1712             :         { 0x04, 0x18, "Logical Unit Not Ready, A Door Is Open" },
    1713             :         { 0x04, 0x19, "Logical Unit Not Ready, Operating In Sequential Mode" },
    1714             :         { 0x04, 0x1A, "Logical Unit Not Ready, Start Stop Unit Command In Progress" },
    1715             :         { 0x05, 0x00, "Logical Unit Does Not Respond To Selection" },
    1716             :         { 0x06, 0x00, "No Reference Position Found" },
    1717             :         { 0x07, 0x00, "Multiple Peripheral Devices Selected" },
    1718             :         { 0x08, 0x00, "Logical Unit Communication Failure" },
    1719             :         { 0x08, 0x01, "Logical Unit Communication Timeout" },
    1720             :         { 0x08, 0x02, "Logical Unit Communication Parity Error" },
    1721             :         { 0x08, 0x03, "Logical Unit Communication CRC Error (ULTRA-DMA/32)" },
    1722             :         { 0x08, 0x04, "Unreachable Copy Target" },
    1723             :         { 0x09, 0x00, "Track Following Error" },
    1724             :         { 0x09, 0x01, "Tracking Servo Failure" },
    1725             :         { 0x09, 0x02, "Focus Servo Failure" },
    1726             :         { 0x09, 0x03, "Spindle Servo Failure" },
    1727             :         { 0x09, 0x04, "Head Select Fault" },
    1728             :         { 0x0A, 0x00, "Error Log Overflow" },
    1729             :         { 0x0B, 0x00, "Warning" },
    1730             :         { 0x0B, 0x01, "Warning - Specified Temperature Exceeded" },
    1731             :         { 0x0B, 0x02, "Warning - Enclosure Degraded" },
    1732             :         { 0x0B, 0x03, "Warning - Background Self-Test Failed" },
    1733             :         { 0x0B, 0x04, "Warning - Background Pre-Scan Detected Medium Error" },
    1734             :         { 0x0B, 0x05, "Warning - Background Medium Scan Detected Medium Error" },
    1735             :         { 0x0B, 0x06, "Warning - Non-Volatile Cache Now Volatile" },
    1736             :         { 0x0B, 0x07, "Warning - Degraded Power To Non-Volatile Cache" },
    1737             :         { 0x0B, 0x08, "Warning - Power Loss Expected" },
    1738             :         { 0x0C, 0x00, "Write Error" },
    1739             :         { 0x0C, 0x01, "Write Error Recovered with Auto Reallocation" },
    1740             :         { 0x0C, 0x02, "Write Error - Auto Reallocate Failed" },
    1741             :         { 0x0C, 0x03, "Write Error - Recommend Reassignment" },
    1742             :         { 0x0C, 0x04, "Compression Check Miscompare Error" },
    1743             :         { 0x0C, 0x05, "Data Expansion Occurred During Compression" },
    1744             :         { 0x0C, 0x06, "Block Not Compressible" },
    1745             :         { 0x0C, 0x07, "Write Error - Recovery Needed" },
    1746             :         { 0x0C, 0x08, "Write Error - Recovery Failed" },
    1747             :         { 0x0C, 0x09, "Write Error - Loss Of Streaming" },
    1748             :         { 0x0C, 0x0A, "Write Error - Padding Blocks Added" },
    1749             :         { 0x0C, 0x0B, "Auxiliary Memory Write Error" },
    1750             :         { 0x0C, 0x0C, "Write Error - Unexpected Unsolicited Data" },
    1751             :         { 0x0C, 0x0D, "Write Error - Not Enough Unsolicited Data" },
    1752             :         { 0x0C, 0x0F, "Defects In Error Window" },
    1753             :         { 0x0D, 0x00, "Error Detected By Third Party Temporary Initiator" },
    1754             :         { 0x0D, 0x01, "Third Party Device Failure" },
    1755             :         { 0x0D, 0x02, "Copy Target Device Not Reachable" },
    1756             :         { 0x0D, 0x03, "Incorrect Copy Target Device Type" },
    1757             :         { 0x0D, 0x04, "Copy Target Device Data Underrun" },
    1758             :         { 0x0D, 0x05, "Copy Target Device Data Overrun" },
    1759             :         { 0x0E, 0x00, "Invalid Information Unit" },
    1760             :         { 0x0E, 0x01, "Information Unit Too Short" },
    1761             :         { 0x0E, 0x02, "Information Unit Too Long" },
    1762             :         { 0x10, 0x00, "ID CRC Or ECC Error" },
    1763             :         { 0x10, 0x01, "Logical Block Guard Check Failed" },
    1764             :         { 0x10, 0x02, "Logical Block Application Tag Check Failed" },
    1765             :         { 0x10, 0x03, "Logical Block Reference Tag Check Failed" },
    1766             :         { 0x10, 0x04, "Logical Block Protection Error On Recover Buffered Data" },
    1767             :         { 0x10, 0x05, "Logical Block Protection Method Error" },
    1768             :         { 0x11, 0x00, "Unrecovered Read Error" },
    1769             :         { 0x11, 0x01, "Read Retries Exhausted" },
    1770             :         { 0x11, 0x02, "Error Too Long To Correct" },
    1771             :         { 0x11, 0x03, "Multiple Read Errors" },
    1772             :         { 0x11, 0x04, "Unrecovered Read Error - Auto Reallocate Failed" },
    1773             :         { 0x11, 0x05, "L-EC Uncorrectable Error" },
    1774             :         { 0x11, 0x06, "CIRC Unrecovered Error" },
    1775             :         { 0x11, 0x07, "Data Resynchronization Error" },
    1776             :         { 0x11, 0x08, "Incomplete Block Read" },
    1777             :         { 0x11, 0x09, "No Gap Found" },
    1778             :         { 0x11, 0x0A, "Miscorrected Error" },
    1779             :         { 0x11, 0x0B, "Uncorrected Read Error - Recommend Reassignment" },
    1780             :         { 0x11, 0x0C, "Uncorrected Read Error - Recommend Rewrite The Data" },
    1781             :         { 0x11, 0x0D, "De-Compression CRC Error" },
    1782             :         { 0x11, 0x0E, "Cannot Decompress Using Declared Algorithm" },
    1783             :         { 0x11, 0x0F, "Error Reading UPC/EAN Number" },
    1784             :         { 0x11, 0x10, "Error Reading ISRC Number" },
    1785             :         { 0x11, 0x11, "Read Error - Loss Of Streaming" },
    1786             :         { 0x11, 0x12, "Auxiliary Memory Read Error" },
    1787             :         { 0x11, 0x13, "Read Error - Failed Retransmission Request" },
    1788             :         { 0x11, 0x14, "Read Error - LBA Marked Bad By Application Client" },
    1789             :         { 0x12, 0x00, "Address Mark Not Found for ID Field" },
    1790             :         { 0x13, 0x00, "Address Mark Not Found for Data Field" },
    1791             :         { 0x14, 0x00, "Recorded Entity Not Found" },
    1792             :         { 0x14, 0x01, "Record Not Found" },
    1793             :         { 0x14, 0x02, "Filemark or Setmark Not Found" },
    1794             :         { 0x14, 0x03, "End-Of-Data Not Found" },
    1795             :         { 0x14, 0x04, "Block Sequence Error" },
    1796             :         { 0x14, 0x05, "Record Not Found - Recommend Reassignment" },
    1797             :         { 0x14, 0x06, "Record Not Found - Data Auto-Reallocated" },
    1798             :         { 0x14, 0x07, "Locate Operation Failure" },
    1799             :         { 0x15, 0x00, "Random Positioning Error" },
    1800             :         { 0x15, 0x01, "Mechanical Positioning Error" },
    1801             :         { 0x15, 0x02, "Positioning Error Detected By Read of Medium" },
    1802             :         { 0x16, 0x00, "Data Synchronization Mark Error" },
    1803             :         { 0x16, 0x01, "Data Sync Error - Data Rewritten" },
    1804             :         { 0x16, 0x02, "Data Sync Error - Recommend Rewrite" },
    1805             :         { 0x16, 0x03, "Data Sync Error - Data Auto-Reallocated" },
    1806             :         { 0x16, 0x04, "Data Sync Error - Recommend Reassignment" },
    1807             :         { 0x17, 0x00, "Recovered Data With No Error Correction Applied" },
    1808             :         { 0x17, 0x01, "Recovered Data With Retries" },
    1809             :         { 0x17, 0x02, "Recovered Data With Positive Head Offset" },
    1810             :         { 0x17, 0x03, "Recovered Data With Negative Head Offset" },
    1811             :         { 0x17, 0x04, "Recovered Data With Retries and/or CIRC Applied" },
    1812             :         { 0x17, 0x05, "Recovered Data Using Previous Sector ID" },
    1813             :         { 0x17, 0x06, "Recovered Data Without ECC - Data Auto-Reallocated" },
    1814             :         { 0x17, 0x07, "Recovered Data Without ECC - Recommend Reassignment" },
    1815             :         { 0x17, 0x08, "Recovered Data Without ECC - Recommend Rewrite" },
    1816             :         { 0x17, 0x09, "Recovered Data Without ECC - Data Rewritten" },
    1817             :         { 0x18, 0x00, "Recovered Data With Error Correction Applied" },
    1818             :         { 0x18, 0x01, "Recovered Data With Error Correction & Retries Applied" },
    1819             :         { 0x18, 0x02, "Recovered Data - Data Auto-Reallocated" },
    1820             :         { 0x18, 0x03, "Recovered Data With CIRC" },
    1821             :         { 0x18, 0x04, "Recovered Data With L-EC" },
    1822             :         { 0x18, 0x05, "Recovered Data - Recommend Reassignment" },
    1823             :         { 0x18, 0x06, "Recovered Data - Recommend Rewrite" },
    1824             :         { 0x18, 0x07, "Recovered Data With ECC - Data Rewritten" },
    1825             :         { 0x18, 0x08, "Recovered Data With Linking" },
    1826             :         { 0x19, 0x00, "Defect List Error" },
    1827             :         { 0x19, 0x01, "Defect List Not Available" },
    1828             :         { 0x19, 0x02, "Defect List Error in Primary List" },
    1829             :         { 0x19, 0x03, "Defect List Error in Grown List" },
    1830             :         { 0x1A, 0x00, "Parameter List Length Error" },
    1831             :         { 0x1B, 0x00, "Synchronous Data Transfer Error" },
    1832             :         { 0x1C, 0x00, "Defect List Not Found" },
    1833             :         { 0x1C, 0x01, "Primary Defect List Not Found" },
    1834             :         { 0x1C, 0x02, "Grown Defect List Not Found" },
    1835             :         { 0x1D, 0x00, "Miscompare During Verify Operation" },
    1836             :         { 0x1D, 0x01, "Miscompare Verify Of Unmapped Lba" },
    1837             :         { 0x1E, 0x00, "Recovered ID with ECC" },
    1838             :         { 0x1F, 0x00, "Partial Defect List Transfer" },
    1839             :         { 0x20, 0x00, "Invalid Command Operation Code" },
    1840             :         { 0x20, 0x01, "Access Denied - Initiator Pending-Enrolled" },
    1841             :         { 0x20, 0x02, "Access Denied - No Access rights" },
    1842             :         { 0x20, 0x03, "Access Denied - Invalid Mgmt ID Key" },
    1843             :         { 0x20, 0x04, "Illegal Command While In Write Capable State" },
    1844             :         { 0x20, 0x05, "Obsolete" },
    1845             :         { 0x20, 0x06, "Illegal Command While In Explicit Address Mode" },
    1846             :         { 0x20, 0x07, "Illegal Command While In Implicit Address Mode" },
    1847             :         { 0x20, 0x08, "Access Denied - Enrollment Conflict" },
    1848             :         { 0x20, 0x09, "Access Denied - Invalid LU Identifier" },
    1849             :         { 0x20, 0x0A, "Access Denied - Invalid Proxy Token" },
    1850             :         { 0x20, 0x0B, "Access Denied - ACL LUN Conflict" },
    1851             :         { 0x20, 0x0C, "Illegal Command When Not In Append-Only Mode" },
    1852             :         { 0x21, 0x00, "Logical Block Address Out of Range" },
    1853             :         { 0x21, 0x01, "Invalid Element Address" },
    1854             :         { 0x21, 0x02, "Invalid Address For Write" },
    1855             :         { 0x21, 0x03, "Invalid Write Crossing Layer Jump" },
    1856             :         { 0x22, 0x00, "Illegal Function (Should 20 00, 24 00, or 26 00)" },
    1857             :         { 0x24, 0x00, "Illegal Field in CDB" },
    1858             :         { 0x24, 0x01, "CDB Decryption Error" },
    1859             :         { 0x24, 0x02, "Obsolete" },
    1860             :         { 0x24, 0x03, "Obsolete" },
    1861             :         { 0x24, 0x04, "Security Audit Value Frozen" },
    1862             :         { 0x24, 0x05, "Security Working Key Frozen" },
    1863             :         { 0x24, 0x06, "Nonce Not Unique" },
    1864             :         { 0x24, 0x07, "Nonce Timestamp Out Of Range" },
    1865             :         { 0x24, 0x08, "Invalid XCDB" },
    1866             :         { 0x25, 0x00, "Logical Unit Not Supported" },
    1867             :         { 0x26, 0x00, "Invalid Field In Parameter List" },
    1868             :         { 0x26, 0x01, "Parameter Not Supported" },
    1869             :         { 0x26, 0x02, "Parameter Value Invalid" },
    1870             :         { 0x26, 0x03, "Threshold Parameters Not Supported" },
    1871             :         { 0x26, 0x04, "Invalid Release Of Persistent Reservation" },
    1872             :         { 0x26, 0x05, "Data Decryption Error" },
    1873             :         { 0x26, 0x06, "Too Many Target Descriptors" },
    1874             :         { 0x26, 0x07, "Unsupported Target Descriptor Type Code" },
    1875             :         { 0x26, 0x08, "Too Many Segment Descriptors" },
    1876             :         { 0x26, 0x09, "Unsupported Segment Descriptor Type Code" },
    1877             :         { 0x26, 0x0A, "Unexpected Inexact Segment" },
    1878             :         { 0x26, 0x0B, "Inline Data Length Exceeded" },
    1879             :         { 0x26, 0x0C, "Invalid Operation For Copy Source Or Destination" },
    1880             :         { 0x26, 0x0D, "Copy Segment Granularity Violation" },
    1881             :         { 0x26, 0x0E, "Invalid Parameter While Port Is Enabled" },
    1882             :         { 0x26, 0x0F, "Invalid Data-Out Buffer Integrity Check Value" },
    1883             :         { 0x26, 0x10, "Data Decryption Key Fail Limit Reached" },
    1884             :         { 0x26, 0x11, "Incomplete Key-Associated Data Set" },
    1885             :         { 0x26, 0x12, "Vendor Specific Key Reference Not Found" },
    1886             :         { 0x27, 0x00, "Write Protected" },
    1887             :         { 0x27, 0x01, "Hardware Write Protected" },
    1888             :         { 0x27, 0x02, "Logical Unit Software Write Protected" },
    1889             :         { 0x27, 0x03, "Associated Write Protect" },
    1890             :         { 0x27, 0x04, "Persistent Write Protect" },
    1891             :         { 0x27, 0x05, "Permanent Write Protect" },
    1892             :         { 0x27, 0x06, "Conditional Write Protect" },
    1893             :         { 0x27, 0x07, "Space Allocation Failed Write Protect" },
    1894             :         { 0x28, 0x00, "Not Ready To Ready Transition (Medium May Have Changed)" },
    1895             :         { 0x28, 0x01, "Import Or Export Element Accessed" },
    1896             :         { 0x28, 0x02, "Format-Layer May Have Changed" },
    1897             :         { 0x28, 0x03, "Import/Export Element Accessed, Medium Changed" },
    1898             :         { 0x29, 0x00, "Power On, Reset, or Bus Device Reset Occurred" },
    1899             :         { 0x29, 0x01, "Power On Occurred" },
    1900             :         { 0x29, 0x02, "SCSI Bus Reset Occurred" },
    1901             :         { 0x29, 0x03, "Bus Device Reset Function Occurred" },
    1902             :         { 0x29, 0x04, "Device Internal Reset" },
    1903             :         { 0x29, 0x05, "Transceiver Mode Changed to Single Ended" },
    1904             :         { 0x29, 0x06, "Transceiver Mode Changed to LVD" },
    1905             :         { 0x29, 0x07, "I_T Nexus Loss Occurred" },
    1906             :         { 0x2A, 0x00, "Parameters Changed" },
    1907             :         { 0x2A, 0x01, "Mode Parameters Changed" },
    1908             :         { 0x2A, 0x02, "Log Parameters Changed" },
    1909             :         { 0x2A, 0x03, "Reservations Preempted" },
    1910             :         { 0x2A, 0x04, "Reservations Released" },
    1911             :         { 0x2A, 0x05, "Registrations Preempted" },
    1912             :         { 0x2A, 0x06, "Asymmetric Access State Changed" },
    1913             :         { 0x2A, 0x07, "Implicit Asymmetric Access State Transition Failed" },
    1914             :         { 0x2A, 0x08, "Priority Changed" },
    1915             :         { 0x2A, 0x09, "Capacity Data Has Changed" },
    1916             :         { 0x2A, 0x0A, "Error History I_T Nexus Cleared" },
    1917             :         { 0x2A, 0x0B, "Error History Snapshot Released" },
    1918             :         { 0x2A, 0x0C, "Error Recovery Attributes Have Changed" },
    1919             :         { 0x2A, 0x0D, "Data Encryption Capabilities Changed" },
    1920             :         { 0x2A, 0x10, "Timestamp Changed" },
    1921             :         { 0x2A, 0x11, "Data Encryption Parameters Changed By Another I_T Nexus" },
    1922             :         { 0x2A, 0x12, "Data Encryption Parameters Changed By Vendor Specific Event" },
    1923             :         { 0x2A, 0x13, "Data Encryption Key Instance Counter Has Changed" },
    1924             :         { 0x2A, 0x14, "SA Creation Capabilities Data Has Changed" },
    1925             :         { 0x2B, 0x00, "Copy Cannot Execute Since Host Cannot Disconnect" },
    1926             :         { 0x2C, 0x00, "Command Sequence Error" },
    1927             :         { 0x2C, 0x01, "Too Many Windows Specified" },
    1928             :         { 0x2C, 0x02, "Invalid Combination of Windows Specified" },
    1929             :         { 0x2C, 0x03, "Current Program Area Is Not Empty" },
    1930             :         { 0x2C, 0x04, "Current Program Area Is Empty" },
    1931             :         { 0x2C, 0x05, "Illegal Power Condition Request" },
    1932             :         { 0x2C, 0x06, "Persistent Prevent Conflict" },
    1933             :         { 0x2C, 0x07, "Previous Busy Status" },
    1934             :         { 0x2C, 0x08, "Previous Task Set Full Status" },
    1935             :         { 0x2C, 0x09, "Previous Reservation Conflict Status" },
    1936             :         { 0x2C, 0x0A, "Partition Or Collection Contains User Objects" },
    1937             :         { 0x2C, 0x0B, "Not Reserved" },
    1938             :         { 0x2C, 0x0C, "ORWrite Generation Does Not Match" },
    1939             :         { 0x2D, 0x00, "Overwrite Error On Update In Place" },
    1940             :         { 0x2E, 0x00, "Insufficient Time For Operation" },
    1941             :         { 0x2F, 0x00, "Commands Cleared By Another Initiator" },
    1942             :         { 0x2F, 0x01, "Commands Cleared By Power Loss Notification" },
    1943             :         { 0x2F, 0x02, "Commands Cleared By Device Server" },
    1944             :         { 0x30, 0x00, "Incompatible Medium Installed" },
    1945             :         { 0x30, 0x01, "Cannot Read Medium - Unknown Format" },
    1946             :         { 0x30, 0x02, "Cannot Read Medium - Incompatible Format" },
    1947             :         { 0x30, 0x03, "Cleaning Cartridge Installed" },
    1948             :         { 0x30, 0x04, "Cannot Write Medium - Unknown Format" },
    1949             :         { 0x30, 0x05, "Cannot Write Medium - Incompatible Format" },
    1950             :         { 0x30, 0x06, "Cannot Format Medium - Incompatible Medium" },
    1951             :         { 0x30, 0x07, "Cleaning Failure" },
    1952             :         { 0x30, 0x08, "Cannot Write - Application Code Mismatch" },
    1953             :         { 0x30, 0x09, "Current Session Not Fixated For Append" },
    1954             :         { 0x30, 0x0A, "Cleaning Request Rejected" },
    1955             :         { 0x30, 0x10, "Medium Not Formatted" },
    1956             :         { 0x30, 0x11, "Incompatible Volume Type" },
    1957             :         { 0x30, 0x12, "Incompatible Volume Qualifier" },
    1958             :         { 0x30, 0x13, "Cleaning Volume Expired" },
    1959             :         { 0x31, 0x00, "Medium Format Corrupted" },
    1960             :         { 0x31, 0x01, "Format Command Failed" },
    1961             :         { 0x31, 0x02, "Zoned Formatting Failed Due To Spare Linking" },
    1962             :         { 0x32, 0x00, "No Defect Spare Location Available" },
    1963             :         { 0x32, 0x01, "Defect List Update Failure" },
    1964             :         { 0x33, 0x00, "Tape Length Error" },
    1965             :         { 0x34, 0x00, "Enclosure Failure" },
    1966             :         { 0x35, 0x00, "Enclosure Services Failure" },
    1967             :         { 0x35, 0x01, "Unsupported Enclosure Function" },
    1968             :         { 0x35, 0x02, "Enclosure Services Unavailable" },
    1969             :         { 0x35, 0x03, "Enclosure Services Transfer Failure" },
    1970             :         { 0x35, 0x04, "Enclosure Services Transfer Refused" },
    1971             :         { 0x36, 0x00, "Ribbon, Ink, or Toner Failure" },
    1972             :         { 0x37, 0x00, "Rounded Parameter" },
    1973             :         { 0x38, 0x00, "Event Status Notification" },
    1974             :         { 0x38, 0x02, "ESN - Power Management Class Event" },
    1975             :         { 0x38, 0x04, "ESN - Media Class Event" },
    1976             :         { 0x38, 0x06, "ESN - Device Busy Class Event" },
    1977             :         { 0x39, 0x00, "Saving Parameters Not Supported" },
    1978             :         { 0x3A, 0x00, "Medium Not Present" },
    1979             :         { 0x3A, 0x01, "Medium Not Present - Tray Closed" },
    1980             :         { 0x3A, 0x02, "Medium Not Present - Tray Open" },
    1981             :         { 0x3A, 0x03, "Medium Not Present - Loadable" },
    1982             :         { 0x3A, 0x04, "Medium Not Present - Medium Auxiliary Memory Accessible" },
    1983             :         { 0x3B, 0x00, "Sequential Positioning Error" },
    1984             :         { 0x3B, 0x01, "Tape Position Error At Beginning-of-Medium" },
    1985             :         { 0x3B, 0x02, "Tape Position Error At End-of-Medium" },
    1986             :         { 0x3B, 0x03, "Tape or Electronic Vertical Forms Unit Not Ready" },
    1987             :         { 0x3B, 0x04, "Slew Failure" },
    1988             :         { 0x3B, 0x05, "Paper Jam" },
    1989             :         { 0x3B, 0x06, "Failed To Sense Top-Of-Form" },
    1990             :         { 0x3B, 0x07, "Failed To Sense Bottom-Of-Form" },
    1991             :         { 0x3B, 0x08, "Reposition Error" },
    1992             :         { 0x3B, 0x09, "Read Past End Of Medium" },
    1993             :         { 0x3B, 0x0A, "Read Past Beginning Of Medium" },
    1994             :         { 0x3B, 0x0B, "Position Past End Of Medium" },
    1995             :         { 0x3B, 0x0C, "Position Past Beginning Of Medium" },
    1996             :         { 0x3B, 0x0D, "Medium Destination Element Full" },
    1997             :         { 0x3B, 0x0E, "Medium Source Element Empty" },
    1998             :         { 0x3B, 0x0F, "End Of Medium Reached" },
    1999             :         { 0x3B, 0x11, "Medium Magazine Not Accessible" },
    2000             :         { 0x3B, 0x12, "Medium Magazine Removed" },
    2001             :         { 0x3B, 0x13, "Medium Magazine Inserted" },
    2002             :         { 0x3B, 0x14, "Medium Magazine Locked" },
    2003             :         { 0x3B, 0x15, "Medium Magazine Unlocked" },
    2004             :         { 0x3B, 0x16, "Mechanical Positioning Or Changer Error" },
    2005             :         { 0x3B, 0x17, "Read Past End Of User Object" },
    2006             :         { 0x3B, 0x18, "Element Disabled" },
    2007             :         { 0x3B, 0x19, "Element Enabled" },
    2008             :         { 0x3B, 0x1A, "Data Transfer Device Removed" },
    2009             :         { 0x3B, 0x1B, "Data Transfer Device Inserted" },
    2010             :         { 0x3D, 0x00, "Invalid Bits In IDENTIFY Message" },
    2011             :         { 0x3E, 0x00, "Logical Unit Has Not Self-Configured Yet" },
    2012             :         { 0x3E, 0x01, "Logical Unit Failure" },
    2013             :         { 0x3E, 0x02, "Timeout On Logical Unit" },
    2014             :         { 0x3E, 0x03, "Logical Unit Failed Self-Test" },
    2015             :         { 0x3E, 0x04, "Logical Unit Unable To Update Self-Test Log" },
    2016             :         { 0x3F, 0x00, "Target Operating Conditions Have Changed" },
    2017             :         { 0x3F, 0x01, "Microcode Has Changed" },
    2018             :         { 0x3F, 0x02, "Changed Operating Definition" },
    2019             :         { 0x3F, 0x03, "INQUIRY Data Has Changed" },
    2020             :         { 0x3F, 0x04, "component Device Attached" },
    2021             :         { 0x3F, 0x05, "Device Identifier Changed" },
    2022             :         { 0x3F, 0x06, "Redundancy Group Created Or Modified" },
    2023             :         { 0x3F, 0x07, "Redundancy Group Deleted" },
    2024             :         { 0x3F, 0x08, "Spare Created Or Modified" },
    2025             :         { 0x3F, 0x09, "Spare Deleted" },
    2026             :         { 0x3F, 0x0A, "Volume Set Created Or Modified" },
    2027             :         { 0x3F, 0x0B, "Volume Set Deleted" },
    2028             :         { 0x3F, 0x0C, "Volume Set Deassigned" },
    2029             :         { 0x3F, 0x0D, "Volume Set Reassigned" },
    2030             :         { 0x3F, 0x0E, "Reported LUNs Data Has Changed" },
    2031             :         { 0x3F, 0x0F, "Echo Buffer Overwritten" },
    2032             :         { 0x3F, 0x10, "Medium Loadable" },
    2033             :         { 0x3F, 0x11, "Medium Auxiliary Memory Accessible" },
    2034             :         { 0x3F, 0x12, "iSCSI IP Address Added" },
    2035             :         { 0x3F, 0x13, "iSCSI IP Address Removed" },
    2036             :         { 0x3F, 0x14, "iSCSI IP Address Changed" },
    2037             :         { 0x40, 0x00, "RAM FAILURE (Should Use 40 NN)" },
    2038             :         /*
    2039             :          * ASC 0x40 also has an ASCQ range from 0x80 to 0xFF.
    2040             :          * 0x40 0xNN DIAGNOSTIC FAILURE ON COMPONENT NN
    2041             :          */
    2042             :         { 0x41, 0x00, "Data Path FAILURE (Should Use 40 NN)" },
    2043             :         { 0x42, 0x00, "Power-On or Self-Test FAILURE (Should Use 40 NN)" },
    2044             :         { 0x43, 0x00, "Message Error" },
    2045             :         { 0x44, 0x00, "Internal Target Failure" },
    2046             :         { 0x44, 0x71, "ATA Device Failed Set Features" },
    2047             :         { 0x45, 0x00, "Select Or Reselect Failure" },
    2048             :         { 0x46, 0x00, "Unsuccessful Soft Reset" },
    2049             :         { 0x47, 0x00, "SCSI Parity Error" },
    2050             :         { 0x47, 0x01, "Data Phase CRC Error Detected" },
    2051             :         { 0x47, 0x02, "SCSI Parity Error Detected During ST Data Phase" },
    2052             :         { 0x47, 0x03, "Information Unit iuCRC Error Detected" },
    2053             :         { 0x47, 0x04, "Asynchronous Information Protection Error Detected" },
    2054             :         { 0x47, 0x05, "Protocol Service CRC Error" },
    2055             :         { 0x47, 0x06, "PHY Test Function In Progress" },
    2056             :         { 0x47, 0x7F, "Some Commands Cleared By iSCSI Protocol Event" },
    2057             :         { 0x48, 0x00, "Initiator Detected Error Message Received" },
    2058             :         { 0x49, 0x00, "Invalid Message Error" },
    2059             :         { 0x4A, 0x00, "Command Phase Error" },
    2060             :         { 0x4B, 0x00, "Data Phase Error" },
    2061             :         { 0x4B, 0x01, "Invalid Target Port Transfer Tag Received" },
    2062             :         { 0x4B, 0x02, "Too Much Write Data" },
    2063             :         { 0x4B, 0x03, "ACK/NAK Timeout" },
    2064             :         { 0x4B, 0x04, "NAK Received" },
    2065             :         { 0x4B, 0x05, "Data Offset Error" },
    2066             :         { 0x4B, 0x06, "Initiator Response Timeout" },
    2067             :         { 0x4B, 0x07, "Connection Lost" },
    2068             :         { 0x4C, 0x00, "Logical Unit Failed Self-Configuration" },
    2069             :         /*
    2070             :          * ASC 0x4D has an ASCQ range from 0x00 to 0xFF.
    2071             :          * 0x4D 0xNN TAGGED OVERLAPPED COMMANDS (NN = TASK TAG)
    2072             :          */
    2073             :         { 0x4E, 0x00, "Overlapped Commands Attempted" },
    2074             :         { 0x50, 0x00, "Write Append Error" },
    2075             :         { 0x50, 0x01, "Write Append Position Error" },
    2076             :         { 0x50, 0x02, "Position Error Related To Timing" },
    2077             :         { 0x51, 0x00, "Erase Failure" },
    2078             :         { 0x51, 0x01, "Erase Failure - Incomplete Erase Operation Detected" },
    2079             :         { 0x52, 0x00, "Cartridge Fault" },
    2080             :         { 0x53, 0x00, "Media Load or Eject Failed" },
    2081             :         { 0x53, 0x01, "Unload Tape Failure" },
    2082             :         { 0x53, 0x02, "Medium Removal Prevented" },
    2083             :         { 0x53, 0x03, "Medium Removal Prevented By Data Transfer Element" },
    2084             :         { 0x53, 0x04, "Medium Thread Or Unthread Failure" },
    2085             :         { 0x53, 0x05, "Volume Identifier Invalid" },
    2086             :         { 0x53, 0x06, "Volume Identifier Missing" },
    2087             :         { 0x53, 0x07, "Duplicate Volume Identifier" },
    2088             :         { 0x53, 0x08, "Element Status Unknown" },
    2089             :         { 0x54, 0x00, "SCSI To Host System Interface Failure" },
    2090             :         { 0x55, 0x00, "System Resource Failure" },
    2091             :         { 0x55, 0x01, "System Buffer Full" },
    2092             :         { 0x55, 0x02, "Insufficient Reservation Resources" },
    2093             :         { 0x55, 0x03, "Insufficient Resources" },
    2094             :         { 0x55, 0x04, "Insufficient Registration Resources" },
    2095             :         { 0x55, 0x05, "Insufficient Access Control Resources" },
    2096             :         { 0x55, 0x06, "Auxiliary Memory Out Of Space" },
    2097             :         { 0x55, 0x07, "Quota Error" },
    2098             :         { 0x55, 0x08, "Maximum Number Of Supplemental Decryption Keys Exceeded" },
    2099             :         { 0x55, 0x09, "Medium Auxiliary Memory Not Accessible" },
    2100             :         { 0x55, 0x0A, "Data Currently Unavailable" },
    2101             :         { 0x55, 0x0B, "Insufficient Power For Operation" },
    2102             :         { 0x57, 0x00, "Unable To Recover Table-Of-Contents" },
    2103             :         { 0x58, 0x00, "Generation Does Not Exist" },
    2104             :         { 0x59, 0x00, "Updated Block Read" },
    2105             :         { 0x5A, 0x00, "Operator Request or State Change Input" },
    2106             :         { 0x5A, 0x01, "Operator Medium Removal Requested" },
    2107             :         { 0x5A, 0x02, "Operator Selected Write Protect" },
    2108             :         { 0x5A, 0x03, "Operator Selected Write Permit" },
    2109             :         { 0x5B, 0x00, "Log Exception" },
    2110             :         { 0x5B, 0x01, "Threshold Condition Met" },
    2111             :         { 0x5B, 0x02, "Log Counter At Maximum" },
    2112             :         { 0x5B, 0x03, "Log List Codes Exhausted" },
    2113             :         { 0x5C, 0x00, "RPL Status Change" },
    2114             :         { 0x5C, 0x01, "Spindles Synchronized" },
    2115             :         { 0x5C, 0x02, "Spindles Not Synchronized" },
    2116             :         { 0x5D, 0x00, "Failure Prediction Threshold Exceeded" },
    2117             :         { 0x5D, 0x01, "Media Failure Prediction Threshold Exceeded" },
    2118             :         { 0x5D, 0x02, "Logical Unit Failure Prediction Threshold Exceeded" },
    2119             :         { 0x5D, 0x03, "Spare Area Exhaustion Prediction Threshold Exceeded" },
    2120             :         { 0x5D, 0x10, "Hardware Impending Failure General Hard Drive Failure" },
    2121             :         { 0x5D, 0x11, "Hardware Impending Failure Drive Error Rate Too High" },
    2122             :         { 0x5D, 0x12, "Hardware Impending Failure Data Error Rate Too High" },
    2123             :         { 0x5D, 0x13, "Hardware Impending Failure Seek Error Rate Too High" },
    2124             :         { 0x5D, 0x14, "Hardware Impending Failure Too Many Block Reassigns" },
    2125             :         { 0x5D, 0x15, "Hardware Impending Failure Access Times Too High" },
    2126             :         { 0x5D, 0x16, "Hardware Impending Failure Start Unit Times Too High" },
    2127             :         { 0x5D, 0x17, "Hardware Impending Failure Channel Parametrics" },
    2128             :         { 0x5D, 0x18, "Hardware Impending Failure Controller Detected" },
    2129             :         { 0x5D, 0x19, "Hardware Impending Failure Throughput Performance" },
    2130             :         { 0x5D, 0x1A, "Hardware Impending Failure Seek Time Performance" },
    2131             :         { 0x5D, 0x1B, "Hardware Impending Failure Spin-Up Retry Count" },
    2132             :         { 0x5D, 0x1C, "Hardware Impending Failure Drive Calibration Retry Count" },
    2133             :         { 0x5D, 0x20, "Controller Impending Failure General Hard Drive Failure" },
    2134             :         { 0x5D, 0x21, "Controller Impending Failure Drive Error Rate Too High" },
    2135             :         { 0x5D, 0x22, "Controller Impending Failure Data Error Rate Too High" },
    2136             :         { 0x5D, 0x23, "Controller Impending Failure Seek Error Rate Too High" },
    2137             :         { 0x5D, 0x24, "Controller Impending Failure Too Many Block Reassigns" },
    2138             :         { 0x5D, 0x25, "Controller Impending Failure Access Times Too High" },
    2139             :         { 0x5D, 0x26, "Controller Impending Failure Start Unit Times Too High" },
    2140             :         { 0x5D, 0x27, "Controller Impending Failure Channel Parametrics" },
    2141             :         { 0x5D, 0x28, "Controller Impending Failure Controller Detected" },
    2142             :         { 0x5D, 0x29, "Controller Impending Failure Throughput Performance" },
    2143             :         { 0x5D, 0x2A, "Controller Impending Failure Seek Time Performance" },
    2144             :         { 0x5D, 0x2B, "Controller Impending Failure Spin-Up Retry Count" },
    2145             :         { 0x5D, 0x2C, "Controller Impending Failure Drive Calibration Retry Count" },
    2146             :         { 0x5D, 0x30, "Data Channel Impending Failure General Hard Drive Failure" },
    2147             :         { 0x5D, 0x31, "Data Channel Impending Failure Drive Error Rate Too High" },
    2148             :         { 0x5D, 0x32, "Data Channel Impending Failure Data Error Rate Too High" },
    2149             :         { 0x5D, 0x33, "Data Channel Impending Failure Seek Error Rate Too High" },
    2150             :         { 0x5D, 0x34, "Data Channel Impending Failure Too Many Block Reassigns" },
    2151             :         { 0x5D, 0x35, "Data Channel Impending Failure Access Times Too High" },
    2152             :         { 0x5D, 0x36, "Data Channel Impending Failure Start Unit Times Too High" },
    2153             :         { 0x5D, 0x37, "Data Channel Impending Failure Channel Parametrics" },
    2154             :         { 0x5D, 0x38, "Data Channel Impending Failure Controller Detected" },
    2155             :         { 0x5D, 0x39, "Data Channel Impending Failure Throughput Performance" },
    2156             :         { 0x5D, 0x3A, "Data Channel Impending Failure Seek Time Performance" },
    2157             :         { 0x5D, 0x3B, "Data Channel Impending Failure Spin-Up Retry Count" },
    2158             :         { 0x5D, 0x3C, "Data Channel Impending Failure Drive Calibration Retry Count" },
    2159             :         { 0x5D, 0x40, "Servo Impending Failure General Hard Drive Failure" },
    2160             :         { 0x5D, 0x41, "Servo Impending Failure Drive Error Rate Too High" },
    2161             :         { 0x5D, 0x42, "Servo Impending Failure Data Error Rate Too High" },
    2162             :         { 0x5D, 0x43, "Servo Impending Failure Seek Error Rate Too High" },
    2163             :         { 0x5D, 0x44, "Servo Impending Failure Too Many Block Reassigns" },
    2164             :         { 0x5D, 0x45, "Servo Impending Failure Access Times Too High" },
    2165             :         { 0x5D, 0x46, "Servo Impending Failure Start Unit Times Too High" },
    2166             :         { 0x5D, 0x47, "Servo Impending Failure Channel Parametrics" },
    2167             :         { 0x5D, 0x48, "Servo Impending Failure Controller Detected" },
    2168             :         { 0x5D, 0x49, "Servo Impending Failure Throughput Performance" },
    2169             :         { 0x5D, 0x4A, "Servo Impending Failure Seek Time Performance" },
    2170             :         { 0x5D, 0x4B, "Servo Impending Failure Spin-Up Retry Count" },
    2171             :         { 0x5D, 0x4C, "Servo Impending Failure Drive Calibration Retry Count" },
    2172             :         { 0x5D, 0x50, "Spindle Impending Failure General Hard Drive Failure" },
    2173             :         { 0x5D, 0x51, "Spindle Impending Failure Drive Error Rate Too High" },
    2174             :         { 0x5D, 0x52, "Spindle Impending Failure Data Error Rate Too High" },
    2175             :         { 0x5D, 0x53, "Spindle Impending Failure Seek Error Rate Too High" },
    2176             :         { 0x5D, 0x54, "Spindle Impending Failure Too Many Block Reassigns" },
    2177             :         { 0x5D, 0x55, "Spindle Impending Failure Access Times Too High" },
    2178             :         { 0x5D, 0x56, "Spindle Impending Failure Start Unit Times Too High" },
    2179             :         { 0x5D, 0x57, "Spindle Impending Failure Channel Parametrics" },
    2180             :         { 0x5D, 0x58, "Spindle Impending Failure Controller Detected" },
    2181             :         { 0x5D, 0x59, "Spindle Impending Failure Throughput Performance" },
    2182             :         { 0x5D, 0x5A, "Spindle Impending Failure Seek Time Performance" },
    2183             :         { 0x5D, 0x5B, "Spindle Impending Failure Spin-Up Retry Count" },
    2184             :         { 0x5D, 0x5C, "Spindle Impending Failure Drive Calibration Retry Count" },
    2185             :         { 0x5D, 0x60, "Firmware Impending Failure General Hard Drive Failure" },
    2186             :         { 0x5D, 0x61, "Firmware Impending Failure Drive Error Rate Too High" },
    2187             :         { 0x5D, 0x62, "Firmware Impending Failure Data Error Rate Too High" },
    2188             :         { 0x5D, 0x63, "Firmware Impending Failure Seek Error Rate Too High" },
    2189             :         { 0x5D, 0x64, "Firmware Impending Failure Too Many Block Reassigns" },
    2190             :         { 0x5D, 0x65, "Firmware Impending Failure Access Times Too High" },
    2191             :         { 0x5D, 0x66, "Firmware Impending Failure Start Unit Times Too High" },
    2192             :         { 0x5D, 0x67, "Firmware Impending Failure Channel Parametrics" },
    2193             :         { 0x5D, 0x68, "Firmware Impending Failure Controller Detected" },
    2194             :         { 0x5D, 0x69, "Firmware Impending Failure Throughput Performance" },
    2195             :         { 0x5D, 0x6A, "Firmware Impending Failure Seek Time Performance" },
    2196             :         { 0x5D, 0x6B, "Firmware Impending Failure Spin-Up Retry Count" },
    2197             :         { 0x5D, 0x6C, "Firmware Impending Failure Drive Calibration Retry Count" },
    2198             :         { 0x5D, 0xFF, "Failure Prediction Threshold Exceeded (false)" },
    2199             :         { 0x5E, 0x00, "Low Power Condition On" },
    2200             :         { 0x5E, 0x01, "Idle Condition Activated By Timer" },
    2201             :         { 0x5E, 0x02, "Standby Condition Activated By Timer" },
    2202             :         { 0x5E, 0x03, "Idle Condition Activated By Command" },
    2203             :         { 0x5E, 0x04, "Standby Condition Activated By Command" },
    2204             :         { 0x5E, 0x05, "IDLE_B Condition Activated By Timer" },
    2205             :         { 0x5E, 0x06, "IDLE_B Condition Activated By Command" },
    2206             :         { 0x5E, 0x07, "IDLE_C Condition Activated By Timer" },
    2207             :         { 0x5E, 0x08, "IDLE_C Condition Activated By Command" },
    2208             :         { 0x5E, 0x09, "STANDBY_Y Condition Activated By Timer" },
    2209             :         { 0x5E, 0x0A, "STANDBY_Y Condition Activated By Command" },
    2210             :         { 0x5E, 0x41, "Power State Change To Active" },
    2211             :         { 0x5E, 0x42, "Power State Change To Idle" },
    2212             :         { 0x5E, 0x43, "Power State Change To Standby" },
    2213             :         { 0x5E, 0x45, "Power State Change To Sleep" },
    2214             :         { 0x5E, 0x47, "Power State Change To Device Control" },
    2215             :         { 0x60, 0x00, "Lamp Failure" },
    2216             :         { 0x61, 0x00, "Video Acquisition Error" },
    2217             :         { 0x61, 0x01, "Unable To Acquire Video" },
    2218             :         { 0x61, 0x02, "Out Of Focus" },
    2219             :         { 0x62, 0x00, "Scan Head Positioning Error" },
    2220             :         { 0x63, 0x00, "End Of User Area Encountered On This Track" },
    2221             :         { 0x63, 0x01, "Packet Does Not Fit In Available Space" },
    2222             :         { 0x64, 0x00, "Illegal Mode For This Track" },
    2223             :         { 0x64, 0x01, "Invalid Packet Size" },
    2224             :         { 0x65, 0x00, "Voltage Fault" },
    2225             :         { 0x66, 0x00, "Automatic Document Feeder Cover Up" },
    2226             :         { 0x66, 0x01, "Automatic Document Feeder Lift Up" },
    2227             :         { 0x66, 0x02, "Document Jam In Automatic Document Feeder" },
    2228             :         { 0x66, 0x03, "Document Miss Feed Automatic In Document Feeder" },
    2229             :         { 0x67, 0x00, "Configuration Failure" },
    2230             :         { 0x67, 0x01, "Configuration Of Incapable Logical Units Failed" },
    2231             :         { 0x67, 0x02, "Add Logical Unit Failed" },
    2232             :         { 0x67, 0x03, "Modification Of Logical Unit Failed" },
    2233             :         { 0x67, 0x04, "Exchange Of Logical Unit Failed" },
    2234             :         { 0x67, 0x05, "Remove Of Logical Unit Failed" },
    2235             :         { 0x67, 0x06, "Attachment Of Logical Unit Failed" },
    2236             :         { 0x67, 0x07, "Creation Of Logical Unit Failed" },
    2237             :         { 0x67, 0x08, "Assign Failure Occurred" },
    2238             :         { 0x67, 0x09, "Multiply Assigned Logical Unit" },
    2239             :         { 0x67, 0x0A, "Set Target Port Groups Command Failed" },
    2240             :         { 0x67, 0x0B, "ATA Device Feature Not Enabled" },
    2241             :         { 0x68, 0x00, "Logical Unit Not Configured" },
    2242             :         { 0x69, 0x00, "Data Loss On Logical Unit" },
    2243             :         { 0x69, 0x01, "Multiple Logical Unit Failures" },
    2244             :         { 0x69, 0x02, "Parity/Data Mismatch" },
    2245             :         { 0x6A, 0x00, "Informational, Refer To Log" },
    2246             :         { 0x6B, 0x00, "State Change Has Occurred" },
    2247             :         { 0x6B, 0x01, "Redundancy Level Got Better" },
    2248             :         { 0x6B, 0x02, "Redundancy Level Got Worse" },
    2249             :         { 0x6C, 0x00, "Rebuild Failure Occurred" },
    2250             :         { 0x6D, 0x00, "Recalculate Failure Occurred" },
    2251             :         { 0x6E, 0x00, "Command To Logical Unit Failed" },
    2252             :         { 0x6F, 0x00, "Copy Protection Key Exchange Failure - Authentication Failure" },
    2253             :         { 0x6F, 0x01, "Copy Protection Key Exchange Failure - Key Not Present" },
    2254             :         { 0x6F, 0x02, "Copy Protection Key Exchange Failure - Key Not Established" },
    2255             :         { 0x6F, 0x03, "Read Of Scrambled Sector Without Authentication" },
    2256             :         { 0x6F, 0x04, "Media Region Code Is Mismatched To Logical Unit Region" },
    2257             :         { 0x6F, 0x05, "Drive Region Must Be Permanent/Region Reset Count Error" },
    2258             :         /*
    2259             :          * ASC 0x70 has an ASCQ range from 0x00 to 0xFF.
    2260             :          * 0x70 0xNN DECOMPRESSION EXCEPTION SHORT ALGORITHM ID Of NN
    2261             :          */
    2262             :         { 0x71, 0x00, "Decompression Exception Long Algorithm ID" },
    2263             :         { 0x72, 0x00, "Session Fixation Error" },
    2264             :         { 0x72, 0x01, "Session Fixation Error Writing Lead-In" },
    2265             :         { 0x72, 0x02, "Session Fixation Error Writing Lead-Out" },
    2266             :         { 0x72, 0x03, "Session Fixation Error - Incomplete Track In Session" },
    2267             :         { 0x72, 0x04, "Empty Or Partially Written Reserved Track" },
    2268             :         { 0x72, 0x05, "No More Track Reservations Allowed" },
    2269             :         { 0x72, 0x06, "RMZ Extension Is Not Allowed" },
    2270             :         { 0x72, 0x07, "No More Test Zone Extensions Are Allowed" },
    2271             :         { 0x73, 0x00, "CD Control Error" },
    2272             :         { 0x73, 0x01, "Power Calibration Area Almost Full" },
    2273             :         { 0x73, 0x02, "Power Calibration Area Is Full" },
    2274             :         { 0x73, 0x03, "Power Calibration Area Error" },
    2275             :         { 0x73, 0x04, "Program Memory Area Update Failure" },
    2276             :         { 0x73, 0x05, "Program Memory Area Is Full" },
    2277             :         { 0x73, 0x06, "RMA/PMA Is Almost Full" },
    2278             :         { 0x73, 0x10, "Current Power Calibration Area Almost Full" },
    2279             :         { 0x73, 0x11, "Current Power Calibration Area Is Full" },
    2280             :         { 0x73, 0x17, "RDZ Is Full" },
    2281             :         { 0x74, 0x00, "Security Error" },
    2282             :         { 0x74, 0x01, "Unable To Decrypt Data" },
    2283             :         { 0x74, 0x02, "Unencrypted Data Encountered While Decrypting" },
    2284             :         { 0x74, 0x03, "Incorrect Data Encryption Key" },
    2285             :         { 0x74, 0x04, "Cryptographic Integrity Validation Failed" },
    2286             :         { 0x74, 0x05, "Error Decrypting Data" },
    2287             :         { 0x74, 0x06, "Unknown Signature Verification Key" },
    2288             :         { 0x74, 0x07, "Encryption Parameters Not Useable" },
    2289             :         { 0x74, 0x08, "Digital Signature Validation Failure" },
    2290             :         { 0x74, 0x09, "Encryption Mode Mismatch On Read" },
    2291             :         { 0x74, 0x0A, "Encrypted Block Not Raw Read Enabled" },
    2292             :         { 0x74, 0x0B, "Incorrect Encryption Parameters" },
    2293             :         { 0x74, 0x0C, "Unable To Decrypt Parameter List" },
    2294             :         { 0x74, 0x0D, "Encryption Algorithm Disabled" },
    2295             :         { 0x74, 0x10, "SA Creation Parameter Value Invalid" },
    2296             :         { 0x74, 0x11, "SA Creation Parameter Value Rejected" },
    2297             :         { 0x74, 0x12, "Invalid SA Usage" },
    2298             :         { 0x74, 0x21, "Data Encryption Configuration Prevented" },
    2299             :         { 0x74, 0x30, "SA Creation Parameter Not Supported" },
    2300             :         { 0x74, 0x40, "Authentication Failed" },
    2301             :         { 0x74, 0x61, "External Data Encryption Key Manager Access Error" },
    2302             :         { 0x74, 0x62, "External Data Encryption Key Manager Error" },
    2303             :         { 0x74, 0x63, "External Data Encryption Key Not Found" },
    2304             :         { 0x74, 0x64, "External Data Encryption Request Not Authorized" },
    2305             :         { 0x74, 0x6E, "External Data Encryption Control Timeout" },
    2306             :         { 0x74, 0x6F, "External Data Encryption Control Error" },
    2307             :         { 0x74, 0x71, "Logical Unit Access Not Authorized" },
    2308             :         { 0x74, 0x79, "Security Conflict In Translated Device" },
    2309             :         { 0x00, 0x00, NULL }
    2310             : };
    2311             : 
    2312             : static __inline void
    2313           0 : asc2ascii(u_int8_t asc, u_int8_t ascq, char *result, size_t len)
    2314             : {
    2315             :         int                                     i;
    2316             : 
    2317             :         /* Check for a dynamically built description. */
    2318           0 :         switch (asc) {
    2319             :         case 0x40:
    2320           0 :                 if (ascq >= 0x80) {
    2321           0 :                         snprintf(result, len,
    2322             :                             "Diagnostic Failure on Component 0x%02x", ascq);
    2323           0 :                         return;
    2324             :                 }
    2325             :                 break;
    2326             :         case 0x4d:
    2327           0 :                 snprintf(result, len,
    2328           0 :                     "Tagged Overlapped Commands (0x%02x = TASK TAG)", ascq);
    2329           0 :                 return;
    2330             :         case 0x70:
    2331           0 :                 snprintf(result, len,
    2332             :                     "Decompression Exception Short Algorithm ID OF 0x%02x",
    2333           0 :                     ascq);
    2334           0 :                 return;
    2335             :         default:
    2336             :                 break;
    2337             :         }
    2338             : 
    2339             :         /* Check for a fixed description. */
    2340           0 :         for (i = 0; adesc[i].description != NULL; i++) {
    2341           0 :                 if (adesc[i].asc == asc && adesc[i].ascq == ascq) {
    2342           0 :                         strlcpy(result, adesc[i].description, len);
    2343           0 :                         return;
    2344             :                 }
    2345             :         }
    2346             : 
    2347             :         /* Just print out the ASC and ASCQ values as a description. */
    2348           0 :         snprintf(result, len, "ASC 0x%02x ASCQ 0x%02x", asc, ascq);
    2349           0 : }
    2350             : #endif /* SCSITERSE */
    2351             : 
    2352             : void
    2353           0 : scsi_print_sense(struct scsi_xfer *xs)
    2354             : {
    2355           0 :         struct scsi_sense_data                  *sense = &xs->sense;
    2356           0 :         u_int8_t                                serr = sense->error_code &
    2357             :                                                     SSD_ERRCODE;
    2358             :         int32_t                                 info;
    2359             :         char                                    *sbs;
    2360             : 
    2361           0 :         sc_print_addr(xs->sc_link);
    2362             : 
    2363             :         /* XXX For error 0x71, current opcode is not the relevant one. */
    2364           0 :         printf("%sCheck Condition (error %#x) on opcode 0x%x\n",
    2365           0 :             (serr == SSD_ERRCODE_DEFERRED) ? "DEFERRED " : "", serr,
    2366           0 :             xs->cmd->opcode);
    2367             : 
    2368           0 :         if (serr != SSD_ERRCODE_CURRENT && serr != SSD_ERRCODE_DEFERRED) {
    2369           0 :                 if ((sense->error_code & SSD_ERRCODE_VALID) != 0) {
    2370             :                         struct scsi_sense_data_unextended *usense =
    2371           0 :                             (struct scsi_sense_data_unextended *)sense;
    2372           0 :                         printf("   AT BLOCK #: %d (decimal)",
    2373           0 :                             _3btol(usense->block));
    2374           0 :                 }
    2375           0 :                 return;
    2376             :         }
    2377             : 
    2378           0 :         printf("    SENSE KEY: %s\n", scsi_decode_sense(sense,
    2379             :             DECODE_SENSE_KEY));
    2380             : 
    2381           0 :         if (sense->flags & (SSD_FILEMARK | SSD_EOM | SSD_ILI)) {
    2382             :                 char pad = ' ';
    2383             : 
    2384           0 :                 printf("             ");
    2385           0 :                 if (sense->flags & SSD_FILEMARK) {
    2386           0 :                         printf("%c Filemark Detected", pad);
    2387             :                         pad = ',';
    2388           0 :                 }
    2389           0 :                 if (sense->flags & SSD_EOM) {
    2390           0 :                         printf("%c EOM Detected", pad);
    2391             :                         pad = ',';
    2392           0 :                 }
    2393           0 :                 if (sense->flags & SSD_ILI)
    2394           0 :                         printf("%c Incorrect Length Indicator Set", pad);
    2395           0 :                 printf("\n");
    2396           0 :         }
    2397             : 
    2398             :         /*
    2399             :          * It is inconvenient to use device type to figure out how to
    2400             :          * format the info fields. So print them as 32 bit integers.
    2401             :          */
    2402           0 :         info = _4btol(&sense->info[0]);
    2403           0 :         if (info)
    2404           0 :                 printf("         INFO: 0x%x (VALID flag %s)\n", info,
    2405           0 :                     sense->error_code & SSD_ERRCODE_VALID ? "on" : "off");
    2406             : 
    2407           0 :         if (sense->extra_len < 4)
    2408           0 :                 return;
    2409             : 
    2410           0 :         info = _4btol(&sense->cmd_spec_info[0]);
    2411           0 :         if (info)
    2412           0 :                 printf(" COMMAND INFO: 0x%x\n", info);
    2413           0 :         sbs = scsi_decode_sense(sense, DECODE_ASC_ASCQ);
    2414           0 :         if (strlen(sbs) > 0)
    2415           0 :                 printf("     ASC/ASCQ: %s\n", sbs);
    2416           0 :         if (sense->fru != 0)
    2417           0 :                 printf("     FRU CODE: 0x%x\n", sense->fru);
    2418           0 :         sbs = scsi_decode_sense(sense, DECODE_SKSV);
    2419           0 :         if (strlen(sbs) > 0)
    2420           0 :                 printf("         SKSV: %s\n", sbs);
    2421           0 : }
    2422             : 
    2423             : char *
    2424           0 : scsi_decode_sense(struct scsi_sense_data *sense, int flag)
    2425             : {
    2426             :         static char                             rqsbuf[132];
    2427             :         u_int16_t                               count;
    2428             :         u_int8_t                                skey, spec_1;
    2429             :         int                                     len;
    2430             : 
    2431           0 :         bzero(rqsbuf, sizeof(rqsbuf));
    2432             : 
    2433           0 :         skey = sense->flags & SSD_KEY;
    2434           0 :         spec_1 = sense->sense_key_spec_1;
    2435           0 :         count = _2btol(&sense->sense_key_spec_2);
    2436             : 
    2437           0 :         switch (flag) {
    2438             :         case DECODE_SENSE_KEY:
    2439           0 :                 strlcpy(rqsbuf, sense_keys[skey], sizeof(rqsbuf));
    2440           0 :                 break;
    2441             :         case DECODE_ASC_ASCQ:
    2442           0 :                 asc2ascii(sense->add_sense_code, sense->add_sense_code_qual,
    2443             :                     rqsbuf, sizeof(rqsbuf));
    2444           0 :                 break;
    2445             :         case DECODE_SKSV:
    2446           0 :                 if (sense->extra_len < 9 || ((spec_1 & SSD_SCS_VALID) == 0))
    2447             :                         break;
    2448           0 :                 switch (skey) {
    2449             :                 case SKEY_ILLEGAL_REQUEST:
    2450           0 :                         len = snprintf(rqsbuf, sizeof rqsbuf,
    2451             :                             "Error in %s, Offset %d",
    2452           0 :                             (spec_1 & SSD_SCS_CDB_ERROR) ? "CDB" : "Parameters",
    2453           0 :                             count);
    2454           0 :                         if ((len != -1 && len < sizeof rqsbuf) &&
    2455           0 :                             (spec_1 & SSD_SCS_VALID_BIT_INDEX))
    2456           0 :                                 snprintf(rqsbuf+len, sizeof rqsbuf - len,
    2457           0 :                                     ", bit %d", spec_1 & SSD_SCS_BIT_INDEX);
    2458             :                         break;
    2459             :                 case SKEY_RECOVERED_ERROR:
    2460             :                 case SKEY_MEDIUM_ERROR:
    2461             :                 case SKEY_HARDWARE_ERROR:
    2462           0 :                         snprintf(rqsbuf, sizeof rqsbuf,
    2463           0 :                             "Actual Retry Count: %d", count);
    2464           0 :                         break;
    2465             :                 case SKEY_NOT_READY:
    2466           0 :                         snprintf(rqsbuf, sizeof rqsbuf,
    2467           0 :                             "Progress Indicator: %d", count);
    2468           0 :                         break;
    2469             :                 default:
    2470             :                         break;
    2471             :                 }
    2472             :                 break;
    2473             :         default:
    2474             :                 break;
    2475             :         }
    2476             : 
    2477           0 :         return (rqsbuf);
    2478             : }
    2479             : 
    2480             : #ifdef SCSIDEBUG
    2481             : /*
    2482             :  * Given a scsi_xfer, dump the request, in all its glory
    2483             :  */
    2484             : void
    2485             : scsi_xs_show(struct scsi_xfer *xs)
    2486             : {
    2487             :         u_char *b = (u_char *)xs->cmd;
    2488             :         int i = 0;
    2489             : 
    2490             :         sc_print_addr(xs->sc_link);
    2491             :         printf("xs  (%p): ", xs);
    2492             : 
    2493             :         printf("flg(0x%x)", xs->flags);
    2494             :         printf("link(%p)", xs->sc_link);
    2495             :         printf("retr(0x%x)", xs->retries);
    2496             :         printf("timo(0x%x)", xs->timeout);
    2497             :         printf("data(%p)", xs->data);
    2498             :         printf("res(0x%zx)", xs->resid);
    2499             :         printf("err(0x%x)", xs->error);
    2500             :         printf("bp(%p)\n", xs->bp);
    2501             : 
    2502             :         sc_print_addr(xs->sc_link);
    2503             :         printf("cmd (%p): ", xs->cmd);
    2504             : 
    2505             :         if ((xs->flags & SCSI_RESET) == 0) {
    2506             :                 while (i < xs->cmdlen) {
    2507             :                         if (i)
    2508             :                                 printf(",");
    2509             :                         printf("%x", b[i++]);
    2510             :                 }
    2511             :                 printf("-[%d bytes]\n", xs->datalen);
    2512             :         } else
    2513             :                 printf("-RESET-\n");
    2514             : }
    2515             : 
    2516             : void
    2517             : scsi_show_mem(u_char *address, int num)
    2518             : {
    2519             :         int x;
    2520             : 
    2521             :         printf("------------------------------");
    2522             :         for (x = 0; x < num; x++) {
    2523             :                 if ((x % 16) == 0)
    2524             :                         printf("\n%03d: ", x);
    2525             :                 printf("%02x ", *address++);
    2526             :         }
    2527             :         printf("\n------------------------------\n");
    2528             : }
    2529             : #endif /* SCSIDEBUG */
    2530             : 
    2531             : void
    2532           0 : scsi_cmd_rw_decode(struct scsi_generic *cmd, u_int64_t *blkno,
    2533             :     u_int32_t *nblks)
    2534             : {
    2535           0 :         switch (cmd->opcode) {
    2536             :         case READ_COMMAND:
    2537             :         case WRITE_COMMAND: {
    2538           0 :                 struct scsi_rw *rw = (struct scsi_rw *)cmd;
    2539           0 :                 *blkno = _3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff);
    2540           0 :                 *nblks = rw->length ? rw->length : 0x100;
    2541             :                 break;
    2542             :         }
    2543             :         case READ_BIG:
    2544             :         case WRITE_BIG: {
    2545           0 :                 struct scsi_rw_big *rwb = (struct scsi_rw_big *)cmd;
    2546           0 :                 *blkno = _4btol(rwb->addr);
    2547           0 :                 *nblks = _2btol(rwb->length);
    2548             :                 break;
    2549             :         }
    2550             :         case READ_12:
    2551             :         case WRITE_12: {
    2552           0 :                 struct scsi_rw_12 *rw12 = (struct scsi_rw_12 *)cmd;
    2553           0 :                 *blkno = _4btol(rw12->addr);
    2554           0 :                 *nblks = _4btol(rw12->length);
    2555             :                 break;
    2556             :         }
    2557             :         case READ_16:
    2558             :         case WRITE_16: {
    2559           0 :                 struct scsi_rw_16 *rw16 = (struct scsi_rw_16 *)cmd;
    2560           0 :                 *blkno = _8btol(rw16->addr);
    2561           0 :                 *nblks = _4btol(rw16->length);
    2562             :                 break;
    2563             :         }
    2564             :         default:
    2565           0 :                 panic("scsi_cmd_rw_decode: bad opcode 0x%02x", cmd->opcode);
    2566             :         }
    2567           0 : }

Generated by: LCOV version 1.13