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