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