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