scsi_base.c revision 1.30 1 /* $NetBSD: scsi_base.c,v 1.30 1995/09/26 19:26:55 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1994, 1995 Charles Hannum. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Charles Hannum.
17 * 4. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Originally written by Julian Elischer (julian (at) dialix.oz.au)
34 */
35
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/buf.h>
41 #include <sys/uio.h>
42 #include <sys/malloc.h>
43 #include <sys/errno.h>
44 #include <sys/device.h>
45
46 #include <scsi/scsi_all.h>
47 #include <scsi/scsi_disk.h>
48 #include <scsi/scsiconf.h>
49
50 void scsi_error __P((struct scsi_xfer *, int));
51
52 LIST_HEAD(xs_free_list, scsi_xfer) xs_free_list;
53
54 /*
55 * Get a scsi transfer structure for the caller. Charge the structure
56 * to the device that is referenced by the sc_link structure. If the
57 * sc_link structure has no 'credits' then the device already has the
58 * maximum number or outstanding operations under way. In this stage,
59 * wait on the structure so that when one is freed, we are awoken again
60 * If the SCSI_NOSLEEP flag is set, then do not wait, but rather, return
61 * a NULL pointer, signifying that no slots were available
62 * Note in the link structure, that we are waiting on it.
63 */
64
65 struct scsi_xfer *
66 scsi_get_xs(sc_link, flags)
67 struct scsi_link *sc_link; /* who to charge the xs to */
68 int flags; /* if this call can sleep */
69 {
70 struct scsi_xfer *xs;
71 int s;
72
73 SC_DEBUG(sc_link, SDEV_DB3, ("scsi_get_xs\n"));
74 s = splbio();
75 while (sc_link->openings <= 0) {
76 SC_DEBUG(sc_link, SDEV_DB3, ("sleeping\n"));
77 if ((flags & SCSI_NOSLEEP) != 0) {
78 splx(s);
79 return 0;
80 }
81 sc_link->flags |= SDEV_WAITING;
82 (void) tsleep(sc_link, PRIBIO, "getxs", 0);
83 }
84 sc_link->openings--;
85 if (xs = xs_free_list.lh_first) {
86 LIST_REMOVE(xs, free_list);
87 splx(s);
88 } else {
89 splx(s);
90 SC_DEBUG(sc_link, SDEV_DB3, ("making\n"));
91 xs = malloc(sizeof(*xs), M_DEVBUF,
92 ((flags & SCSI_NOSLEEP) != 0 ? M_NOWAIT : M_WAITOK));
93 if (!xs) {
94 sc_print_addr(sc_link);
95 printf("cannot allocate scsi xs\n");
96 return 0;
97 }
98 }
99
100 SC_DEBUG(sc_link, SDEV_DB3, ("returning\n"));
101 xs->flags = INUSE | flags;
102 return xs;
103 }
104
105 /*
106 * Given a scsi_xfer struct, and a device (referenced through sc_link)
107 * return the struct to the free pool and credit the device with it
108 * If another process is waiting for an xs, do a wakeup, let it proceed
109 */
110 void
111 scsi_free_xs(xs, flags)
112 struct scsi_xfer *xs;
113 int flags;
114 {
115 struct scsi_link *sc_link = xs->sc_link;
116
117 xs->flags &= ~INUSE;
118 LIST_INSERT_HEAD(&xs_free_list, xs, free_list);
119
120 SC_DEBUG(sc_link, SDEV_DB3, ("scsi_free_xs\n"));
121 /* if was 0 and someone waits, wake them up */
122 sc_link->openings++;
123 if ((sc_link->flags & SDEV_WAITING) != 0) {
124 sc_link->flags &= ~SDEV_WAITING;
125 wakeup(sc_link);
126 } else {
127 if (sc_link->device->start) {
128 SC_DEBUG(sc_link, SDEV_DB2, ("calling private start()\n"));
129 (*(sc_link->device->start)) (sc_link->device_softc);
130 }
131 }
132 }
133
134 /*
135 * Make a scsi_xfer, and return a pointer to it.
136 */
137 static __inline struct scsi_xfer *
138 scsi_make_xs(sc_link, scsi_cmd, cmdlen, data_addr, datalen,
139 retries, timeout, bp, flags)
140 struct scsi_link *sc_link;
141 struct scsi_generic *scsi_cmd;
142 int cmdlen;
143 u_char *data_addr;
144 int datalen;
145 int retries;
146 int timeout;
147 struct buf *bp;
148 int flags;
149 {
150 struct scsi_xfer *xs;
151
152 if ((xs = scsi_get_xs(sc_link, flags)) == NULL)
153 return NULL;
154
155 /*
156 * Fill out the scsi_xfer structure. We don't know whose context
157 * the cmd is in, so copy it.
158 */
159 xs->sc_link = sc_link;
160 bcopy(scsi_cmd, &xs->cmdstore, cmdlen);
161 xs->cmd = &xs->cmdstore;
162 xs->cmdlen = cmdlen;
163 xs->data = data_addr;
164 xs->datalen = datalen;
165 xs->retries = retries;
166 xs->timeout = timeout;
167 xs->bp = bp;
168
169 return xs;
170 }
171
172 /*
173 * Find out from the device what its capacity is.
174 */
175 u_long
176 scsi_size(sc_link, flags)
177 struct scsi_link *sc_link;
178 int flags;
179 {
180 struct scsi_read_cap_data rdcap;
181 struct scsi_read_capacity scsi_cmd;
182 u_long size;
183
184 /*
185 * make up a scsi command and ask the scsi driver to do
186 * it for you.
187 */
188 bzero(&scsi_cmd, sizeof(scsi_cmd));
189 scsi_cmd.opcode = READ_CAPACITY;
190
191 /*
192 * If the command works, interpret the result as a 4 byte
193 * number of blocks
194 */
195 if (scsi_scsi_cmd(sc_link, (struct scsi_generic *)&scsi_cmd,
196 sizeof(scsi_cmd), (u_char *)&rdcap, sizeof(rdcap),
197 2, 20000, NULL, flags | SCSI_DATA_IN) != 0) {
198 sc_print_addr(sc_link);
199 printf("could not get size\n");
200 return 0;
201 } else {
202 size = rdcap.addr_0 + 1;
203 size += rdcap.addr_1 << 8;
204 size += rdcap.addr_2 << 16;
205 size += rdcap.addr_3 << 24;
206 }
207 return size;
208 }
209
210 /*
211 * Get scsi driver to send a "are you ready?" command
212 */
213 int
214 scsi_test_unit_ready(sc_link, flags)
215 struct scsi_link *sc_link;
216 int flags;
217 {
218 struct scsi_test_unit_ready scsi_cmd;
219
220 bzero(&scsi_cmd, sizeof(scsi_cmd));
221 scsi_cmd.opcode = TEST_UNIT_READY;
222
223 return scsi_scsi_cmd(sc_link, (struct scsi_generic *) &scsi_cmd,
224 sizeof(scsi_cmd), 0, 0, 2, 10000, NULL, flags);
225 }
226
227 /*
228 * Do a scsi operation, asking a device to run as SCSI-II if it can.
229 */
230 int
231 scsi_change_def(sc_link, flags)
232 struct scsi_link *sc_link;
233 int flags;
234 {
235 struct scsi_changedef scsi_cmd;
236
237 bzero(&scsi_cmd, sizeof(scsi_cmd));
238 scsi_cmd.opcode = CHANGE_DEFINITION;
239 scsi_cmd.how = SC_SCSI_2;
240
241 return scsi_scsi_cmd(sc_link, (struct scsi_generic *) &scsi_cmd,
242 sizeof(scsi_cmd), 0, 0, 2, 100000, NULL, flags);
243 }
244
245 /*
246 * Do a scsi operation asking a device what it is
247 * Use the scsi_cmd routine in the switch table.
248 */
249 int
250 scsi_inquire(sc_link, inqbuf, flags)
251 struct scsi_link *sc_link;
252 struct scsi_inquiry_data *inqbuf;
253 int flags;
254 {
255 struct scsi_inquiry scsi_cmd;
256
257 bzero(&scsi_cmd, sizeof(scsi_cmd));
258 scsi_cmd.opcode = INQUIRY;
259 scsi_cmd.length = sizeof(struct scsi_inquiry_data);
260
261 return scsi_scsi_cmd(sc_link, (struct scsi_generic *) &scsi_cmd,
262 sizeof(scsi_cmd), (u_char *) inqbuf,
263 sizeof(struct scsi_inquiry_data), 2, 10000, NULL,
264 SCSI_DATA_IN | flags);
265 }
266
267 /*
268 * Prevent or allow the user to remove the media
269 */
270 int
271 scsi_prevent(sc_link, type, flags)
272 struct scsi_link *sc_link;
273 int type, flags;
274 {
275 struct scsi_prevent scsi_cmd;
276
277 bzero(&scsi_cmd, sizeof(scsi_cmd));
278 scsi_cmd.opcode = PREVENT_ALLOW;
279 scsi_cmd.how = type;
280 return scsi_scsi_cmd(sc_link, (struct scsi_generic *) &scsi_cmd,
281 sizeof(scsi_cmd), 0, 0, 2, 5000, NULL, flags);
282 }
283
284 /*
285 * Get scsi driver to send a "start up" command
286 */
287 int
288 scsi_start(sc_link, type, flags)
289 struct scsi_link *sc_link;
290 int type, flags;
291 {
292 struct scsi_start_stop scsi_cmd;
293
294 bzero(&scsi_cmd, sizeof(scsi_cmd));
295 scsi_cmd.opcode = START_STOP;
296 scsi_cmd.byte2 = 0x00;
297 scsi_cmd.how = type;
298 return scsi_scsi_cmd(sc_link, (struct scsi_generic *) &scsi_cmd,
299 sizeof(scsi_cmd), 0, 0, 2,
300 type == SSS_START ? 30000 : 10000, NULL, flags);
301 }
302
303 /*
304 * This routine is called by the scsi interrupt when the transfer is complete.
305 */
306 void
307 scsi_done(xs)
308 struct scsi_xfer *xs;
309 {
310 struct scsi_link *sc_link = xs->sc_link;
311 int error;
312
313 SC_DEBUG(sc_link, SDEV_DB2, ("scsi_done\n"));
314 #ifdef SCSIDEBUG
315 if ((sc_link->flags & SDEV_DB1) != 0)
316 show_scsi_cmd(xs);
317 #endif /* SCSIDEBUG */
318
319 /*
320 * If it's a user level request, bypass all usual completion processing,
321 * let the user work it out.. We take reponsibility for freeing the
322 * xs when the user returns. (and restarting the device's queue).
323 */
324 if ((xs->flags & SCSI_USER) != 0) {
325 SC_DEBUG(sc_link, SDEV_DB3, ("calling user done()\n"));
326 scsi_user_done(xs); /* to take a copy of the sense etc. */
327 SC_DEBUG(sc_link, SDEV_DB3, ("returned from user done()\n "));
328
329 scsi_free_xs(xs, SCSI_NOSLEEP); /* restarts queue too */
330 SC_DEBUG(sc_link, SDEV_DB3, ("returning to adapter\n"));
331 return;
332 }
333
334 /*
335 * If the device has it's own done routine, call it first.
336 * If it returns a legit error value, return that, otherwise
337 * it wants us to continue with normal processing.
338 */
339 if (sc_link->device->done) {
340 SC_DEBUG(sc_link, SDEV_DB2, ("calling private done()\n"));
341 error = (*sc_link->device->done) (xs);
342 if (error == EJUSTRETURN)
343 goto done;
344 SC_DEBUG(sc_link, SDEV_DB3, ("continuing with generic done()\n"));
345 }
346 if (xs->bp == NULL) {
347 /*
348 * if it's a normal upper level request, then ask
349 * the upper level code to handle error checking
350 * rather than doing it here at interrupt time
351 */
352 wakeup(xs);
353 return;
354 }
355 /*
356 * Go and handle errors now.
357 * If it returns ERESTART then we should RETRY
358 */
359 retry:
360 if (sc_err1(xs, 1) == ERESTART) {
361 switch ((*(sc_link->adapter->scsi_cmd)) (xs)) {
362 case SUCCESSFULLY_QUEUED:
363 return;
364
365 case TRY_AGAIN_LATER:
366 xs->error = XS_BUSY;
367 case COMPLETE:
368 goto retry;
369 }
370 }
371 done:
372 scsi_free_xs(xs, SCSI_NOSLEEP);
373 }
374
375 int
376 scsi_execute_xs(xs)
377 struct scsi_xfer *xs;
378 {
379 int error;
380 int s;
381
382 xs->flags &= ~ITSDONE;
383 xs->error = XS_NOERROR;
384 xs->resid = xs->datalen;
385
386 retry:
387 /*
388 * Do the transfer. If we are polling we will return:
389 * COMPLETE, Was poll, and scsi_done has been called
390 * TRY_AGAIN_LATER, Adapter short resources, try again
391 *
392 * if under full steam (interrupts) it will return:
393 * SUCCESSFULLY_QUEUED, will do a wakeup when complete
394 * TRY_AGAIN_LATER, (as for polling)
395 * After the wakeup, we must still check if it succeeded
396 *
397 * If we have a bp however, all the error proccessing
398 * and the buffer code both expect us to return straight
399 * to them, so as soon as the command is queued, return
400 */
401 switch ((*(xs->sc_link->adapter->scsi_cmd)) (xs)) {
402 case SUCCESSFULLY_QUEUED:
403 if (xs->bp)
404 return EJUSTRETURN;
405 s = splbio();
406 while ((xs->flags & ITSDONE) == 0)
407 tsleep(xs, PRIBIO + 1, "scsi_scsi_cmd", 0);
408 splx(s);
409 case COMPLETE: /* Polling command completed ok */
410 if (xs->bp)
411 return EJUSTRETURN;
412 doit:
413 SC_DEBUG(xs->sc_link, SDEV_DB3, ("back in cmd()\n"));
414 if ((error = sc_err1(xs, 0)) != ERESTART)
415 return error;
416 goto retry;
417
418 case TRY_AGAIN_LATER: /* adapter resource shortage */
419 xs->error = XS_BUSY;
420 goto doit;
421
422 default:
423 panic("scsi_execute_xs: invalid return code");
424 }
425
426 #ifdef DIAGNOSTIC
427 panic("scsi_execute_xs: impossible");
428 #endif
429 }
430
431 /*
432 * ask the scsi driver to perform a command for us.
433 * tell it where to read/write the data, and how
434 * long the data is supposed to be. If we have a buf
435 * to associate with the transfer, we need that too.
436 */
437 int
438 scsi_scsi_cmd(sc_link, scsi_cmd, cmdlen, data_addr, datalen,
439 retries, timeout, bp, flags)
440 struct scsi_link *sc_link;
441 struct scsi_generic *scsi_cmd;
442 int cmdlen;
443 u_char *data_addr;
444 int datalen;
445 int retries;
446 int timeout;
447 struct buf *bp;
448 int flags;
449 {
450 struct scsi_xfer *xs;
451 int error;
452
453 SC_DEBUG(sc_link, SDEV_DB2, ("scsi_cmd\n"));
454
455 #ifdef DIAGNOSTIC
456 if (bp != 0 && (flags & SCSI_NOSLEEP) == 0)
457 panic("scsi_scsi_cmd: buffer without nosleep");
458 #endif
459
460 if ((xs = scsi_make_xs(sc_link, scsi_cmd, cmdlen, data_addr, datalen,
461 retries, timeout, bp, flags)) == NULL)
462 return ENOMEM;
463
464 if ((error = scsi_execute_xs(xs)) == EJUSTRETURN)
465 return 0;
466
467 /*
468 * we have finished with the xfer stuct, free it and
469 * check if anyone else needs to be started up.
470 */
471 scsi_free_xs(xs, flags);
472 return error;
473 }
474
475 int
476 sc_err1(xs, async)
477 struct scsi_xfer *xs;
478 int async;
479 {
480 int error;
481
482 SC_DEBUG(xs->sc_link, SDEV_DB3, ("sc_err1,err = 0x%x \n", xs->error));
483
484 /*
485 * If it has a buf, we might be working with
486 * a request from the buffer cache or some other
487 * piece of code that requires us to process
488 * errors at inetrrupt time. We have probably
489 * been called by scsi_done()
490 */
491 switch (xs->error) {
492 case XS_NOERROR: /* nearly always hit this one */
493 error = 0;
494 break;
495
496 case XS_SENSE:
497 if ((error = scsi_interpret_sense(xs)) == ERESTART)
498 goto retry;
499 SC_DEBUG(xs->sc_link, SDEV_DB3,
500 ("scsi_interpret_sense returned %d\n", error));
501 break;
502
503 case XS_BUSY:
504 if (xs->retries) {
505 if ((xs->flags & SCSI_POLL) != 0)
506 delay(1000000);
507 else if ((xs->flags & SCSI_NOSLEEP) == 0)
508 tsleep(&lbolt, PRIBIO, "scbusy", 0);
509 else
510 #if 0
511 timeout(scsi_requeue, xs, hz);
512 #else
513 goto lose;
514 #endif
515 }
516 case XS_TIMEOUT:
517 retry:
518 if (xs->retries--) {
519 xs->error = XS_NOERROR;
520 xs->flags &= ~ITSDONE;
521 return ERESTART;
522 }
523 case XS_DRIVER_STUFFUP:
524 lose:
525 error = EIO;
526 break;
527
528 case XS_SELTIMEOUT:
529 /* XXX Disable device? */
530 error = EIO;
531 break;
532
533 default:
534 sc_print_addr(xs->sc_link);
535 printf("unknown error category from scsi driver\n");
536 error = EIO;
537 break;
538 }
539
540 scsi_error(xs, error);
541 return error;
542 }
543
544 void
545 scsi_error(xs, error)
546 struct scsi_xfer *xs;
547 int error;
548 {
549 struct buf *bp = xs->bp;
550
551 if (bp) {
552 if (error) {
553 bp->b_error = error;
554 bp->b_flags |= B_ERROR;
555 bp->b_resid = bp->b_bcount;
556 } else {
557 bp->b_error = 0;
558 bp->b_resid = xs->resid;
559 }
560 biodone(bp);
561 }
562 }
563
564 /*
565 * Look at the returned sense and act on the error, determining
566 * the unix error number to pass back. (0 = report no error)
567 *
568 * THIS IS THE DEFAULT ERROR HANDLER
569 */
570 int
571 scsi_interpret_sense(xs)
572 struct scsi_xfer *xs;
573 {
574 struct scsi_sense_data *sense;
575 struct scsi_link *sc_link = xs->sc_link;
576 u_int8_t key;
577 u_int32_t info;
578 int error;
579
580 static char *error_mes[] = {
581 "soft error (corrected)",
582 "not ready", "medium error",
583 "non-media hardware failure", "illegal request",
584 "unit attention", "readonly device",
585 "no data found", "vendor unique",
586 "copy aborted", "command aborted",
587 "search returned equal", "volume overflow",
588 "verify miscompare", "unknown error key"
589 };
590
591 sense = &xs->sense;
592 #ifdef SCSIDEBUG
593 if ((sc_link->flags & SDEV_DB1) != 0) {
594 int count;
595 printf("code%x valid%x ",
596 sense->error_code & SSD_ERRCODE,
597 sense->error_code & SSD_ERRCODE_VALID ? 1 : 0);
598 printf("seg%x key%x ili%x eom%x fmark%x\n",
599 sense->extended_segment,
600 sense->extended_flags & SSD_KEY,
601 sense->extended_flags & SSD_ILI ? 1 : 0,
602 sense->extended_flags & SSD_EOM ? 1 : 0,
603 sense->extended_flags & SSD_FILEMARK ? 1 : 0);
604 printf("info: %x %x %x %x followed by %d extra bytes\n",
605 sense->extended_info[0],
606 sense->extended_info[1],
607 sense->extended_info[2],
608 sense->extended_info[3],
609 sense->extended_extra_len);
610 printf("extra: ");
611 for (count = 0; count < sense->extended_extra_len; count++)
612 printf("%x ", sense->extended_extra_bytes[count]);
613 printf("\n");
614 }
615 #endif /*SCSIDEBUG */
616 /*
617 * If the device has it's own error handler, call it first.
618 * If it returns a legit error value, return that, otherwise
619 * it wants us to continue with normal error processing.
620 */
621 if (sc_link->device->err_handler) {
622 SC_DEBUG(sc_link, SDEV_DB2, ("calling private err_handler()\n"));
623 error = (*sc_link->device->err_handler) (xs);
624 if (error != -1)
625 return error; /* error >= 0 better ? */
626 }
627 /* otherwise use the default */
628 switch (sense->error_code & SSD_ERRCODE) {
629 /*
630 * If it's code 70, use the extended stuff and interpret the key
631 */
632 case 0x71: /* delayed error */
633 sc_print_addr(sc_link);
634 key = sense->extended_flags & SSD_KEY;
635 printf(" DELAYED ERROR, key = 0x%x\n", key);
636 case 0x70:
637 if ((sense->error_code & SSD_ERRCODE_VALID) != 0) {
638 bcopy(sense->extended_info, &info, sizeof info);
639 info = ntohl(info);
640 } else
641 info = 0;
642 key = sense->extended_flags & SSD_KEY;
643
644 switch (key) {
645 case 0x0: /* NO SENSE */
646 case 0x1: /* RECOVERED ERROR */
647 if (xs->resid == xs->datalen)
648 xs->resid = 0; /* not short read */
649 case 0xc: /* EQUAL */
650 error = 0;
651 break;
652 case 0x2: /* NOT READY */
653 if ((sc_link->flags & SDEV_REMOVABLE) != 0)
654 sc_link->flags &= ~SDEV_MEDIA_LOADED;
655 if ((xs->flags & SCSI_IGNORE_NOT_READY) != 0)
656 return 0;
657 if ((xs->flags & SCSI_SILENT) != 0)
658 return EIO;
659 error = EIO;
660 break;
661 case 0x5: /* ILLEGAL REQUEST */
662 if ((xs->flags & SCSI_IGNORE_ILLEGAL_REQUEST) != 0)
663 return 0;
664 error = EINVAL;
665 break;
666 case 0x6: /* UNIT ATTENTION */
667 if ((sc_link->flags & SDEV_REMOVABLE) != 0)
668 sc_link->flags &= ~SDEV_MEDIA_LOADED;
669 if ((xs->flags & SCSI_IGNORE_MEDIA_CHANGE) != 0 ||
670 /* XXX Should reupload any transient state. */
671 (sc_link->flags & SDEV_REMOVABLE) == 0)
672 return ERESTART;
673 if ((xs->flags & SCSI_SILENT) != 0)
674 return EIO;
675 error = EIO;
676 break;
677 case 0x7: /* DATA PROTECT */
678 error = EACCES;
679 break;
680 case 0x8: /* BLANK CHECK */
681 error = 0;
682 break;
683 case 0xd: /* VOLUME OVERFLOW */
684 error = ENOSPC;
685 break;
686 default:
687 error = EIO;
688 break;
689 }
690
691 if (key) {
692 sc_print_addr(sc_link);
693 printf("%s", error_mes[key - 1]);
694 if ((sense->error_code & SSD_ERRCODE_VALID) != 0) {
695 switch (key) {
696 case 0x2: /* NOT READY */
697 case 0x5: /* ILLEGAL REQUEST */
698 case 0x6: /* UNIT ATTENTION */
699 case 0x7: /* DATA PROTECT */
700 break;
701 case 0x8: /* BLANK CHECK */
702 printf(", requested size: %d (decimal)",
703 info);
704 break;
705 default:
706 printf(", info = %d (decimal)", info);
707 }
708 }
709 if (sense->extended_extra_len != 0) {
710 int n;
711 printf(", data =");
712 for (n = 0; n < sense->extended_extra_len; n++)
713 printf(" %02x", sense->extended_extra_bytes[n]);
714 }
715 printf("\n");
716 }
717 return error;
718
719 /*
720 * Not code 70, just report it
721 */
722 default:
723 sc_print_addr(sc_link);
724 printf("error code %d",
725 sense->error_code & SSD_ERRCODE);
726 if ((sense->error_code & SSD_ERRCODE_VALID) != 0) {
727 printf(" at block no. %d (decimal)",
728 (sense->XXX_unextended_blockhi << 16) +
729 (sense->XXX_unextended_blockmed << 8) +
730 (sense->XXX_unextended_blocklow));
731 }
732 printf("\n");
733 return EIO;
734 }
735 }
736
737 /*
738 * Utility routines often used in SCSI stuff
739 */
740
741 /*
742 * convert a physical address to 3 bytes,
743 * MSB at the lowest address,
744 * LSB at the highest.
745 */
746 void
747 lto3b(val, bytes)
748 u_int32_t val;
749 u_int8_t *bytes;
750 {
751
752 *bytes++ = (val >> 16) & 0xff;
753 *bytes++ = (val >> 8) & 0xff;
754 *bytes = val & 0xff;
755 }
756
757 /*
758 * The reverse of lto3b
759 */
760 u_int32_t
761 _3btol(bytes)
762 u_int8_t *bytes;
763 {
764 u_int32_t rc;
765
766 rc = (*bytes++ << 16);
767 rc += (*bytes++ << 8);
768 rc += *bytes;
769 return (rc);
770 }
771
772 /*
773 * Print out the scsi_link structure's address info.
774 */
775 void
776 sc_print_addr(sc_link)
777 struct scsi_link *sc_link;
778 {
779
780 printf("%s(%s:%d:%d): ",
781 sc_link->device_softc ?
782 ((struct device *)sc_link->device_softc)->dv_xname : "probe",
783 ((struct device *)sc_link->adapter_softc)->dv_xname,
784 sc_link->target, sc_link->lun);
785 }
786
787 #ifdef SCSIDEBUG
788 /*
789 * Given a scsi_xfer, dump the request, in all it's glory
790 */
791 void
792 show_scsi_xs(xs)
793 struct scsi_xfer *xs;
794 {
795 printf("xs(0x%x): ", xs);
796 printf("flg(0x%x)", xs->flags);
797 printf("sc_link(0x%x)", xs->sc_link);
798 printf("retr(0x%x)", xs->retries);
799 printf("timo(0x%x)", xs->timeout);
800 printf("cmd(0x%x)", xs->cmd);
801 printf("len(0x%x)", xs->cmdlen);
802 printf("data(0x%x)", xs->data);
803 printf("len(0x%x)", xs->datalen);
804 printf("res(0x%x)", xs->resid);
805 printf("err(0x%x)", xs->error);
806 printf("bp(0x%x)", xs->bp);
807 show_scsi_cmd(xs);
808 }
809
810 void
811 show_scsi_cmd(xs)
812 struct scsi_xfer *xs;
813 {
814 u_char *b = (u_char *) xs->cmd;
815 int i = 0;
816
817 sc_print_addr(xs->sc_link);
818 printf("command: ");
819
820 if ((xs->flags & SCSI_RESET) == 0) {
821 while (i < xs->cmdlen) {
822 if (i)
823 printf(",");
824 printf("%x", b[i++]);
825 }
826 printf("-[%d bytes]\n", xs->datalen);
827 if (xs->datalen)
828 show_mem(xs->data, min(64, xs->datalen));
829 } else
830 printf("-RESET-\n");
831 }
832
833 void
834 show_mem(address, num)
835 u_char *address;
836 int num;
837 {
838 int x;
839
840 printf("------------------------------");
841 for (x = 0; x < num; x++) {
842 if ((x % 16) == 0)
843 printf("\n%03d: ", x);
844 printf("%02x ", *address++);
845 }
846 printf("\n------------------------------\n");
847 }
848 #endif /*SCSIDEBUG */
849