[BACK]Return to scsi_base.c CVS log [TXT][DIR] Up to [local] / sys / scsi

Annotation of sys/scsi/scsi_base.c, Revision 1.1.1.1

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

CVSweb