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