scsi_base.c revision 1.9 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.9 1994/03/29 04:29:29 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_unit(sc_link, flags)
252 struct scsi_link *sc_link;
253 u_int32 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 = SSS_START;
260
261 return scsi_scsi_cmd(sc_link, (struct scsi_generic *) &scsi_cmd,
262 sizeof(scsi_cmd), 0, 0, 2, 6000, NULL, flags);
263 }
264
265 /*
266 * Get scsi driver to send a "stop" command
267 */
268 int
269 scsi_stop_unit(sc_link, eject, flags)
270 struct scsi_link *sc_link;
271 u_int32 eject;
272 u_int32 flags;
273 {
274 struct scsi_start_stop scsi_cmd;
275
276 bzero(&scsi_cmd, sizeof(scsi_cmd));
277 scsi_cmd.op_code = START_STOP;
278 if (eject)
279 scsi_cmd.how = SSS_LOEJ;
280 else
281 scsi_cmd.how = SSS_STOP;
282
283 return scsi_scsi_cmd(sc_link, (struct scsi_generic *) &scsi_cmd,
284 sizeof(scsi_cmd), 0, 0, 2, 2000, NULL, flags);
285 }
286
287 /*
288 * This routine is called by the scsi interrupt when the transfer is complete.
289 */
290 void
291 scsi_done(xs)
292 struct scsi_xfer *xs;
293 {
294 struct scsi_link *sc_link = xs->sc_link;
295 struct buf *bp = xs->bp;
296 int retval;
297
298 SC_DEBUG(sc_link, SDEV_DB2, ("scsi_done\n"));
299 #ifdef SCSIDEBUG
300 if (sc_link->flags & SDEV_DB1)
301 show_scsi_cmd(xs);
302 #endif /*SCSIDEBUG */
303 /*
304 * If it's a user level request, bypass all usual completion processing,
305 * let the user work it out.. We take reponsibility for freeing the
306 * xs when the user returns. (and restarting the device's queue).
307 */
308 if (xs->flags & SCSI_USER) {
309 biodone(xs->bp);
310 #ifdef NOTNOW
311 SC_DEBUG(sc_link, SDEV_DB3, ("calling user done()\n"));
312 scsi_user_done(xs); /* to take a copy of the sense etc. */
313 SC_DEBUG(sc_link, SDEV_DB3, ("returned from user done()\n "));
314 #endif
315 free_xs(xs, sc_link, SCSI_NOSLEEP); /* restarts queue too */
316 SC_DEBUG(sc_link, SDEV_DB3, ("returning to adapter\n"));
317 return;
318 }
319 /*
320 * If the device has it's own done routine, call it first.
321 * If it returns a legit error value, return that, otherwise
322 * it wants us to continue with normal processing.
323 */
324
325 if (sc_link->device->done) {
326 SC_DEBUG(sc_link, SDEV_DB2, ("calling private done()\n"));
327 retval = (*sc_link->device->done) (xs);
328 if (retval == -1) {
329 free_xs(xs, sc_link, SCSI_NOSLEEP); /*XXX */
330 return; /* it did it all, finish up */
331 }
332 if (retval == -2)
333 return; /* it did it all, finish up */
334 SC_DEBUG(sc_link, SDEV_DB3, ("continuing with generic done()\n"));
335 }
336 if ((bp = xs->bp) == NULL) {
337 /*
338 * if it's a normal upper level request, then ask
339 * the upper level code to handle error checking
340 * rather than doing it here at interrupt time
341 */
342 wakeup(xs);
343 return;
344 }
345 /*
346 * Go and handle errors now.
347 * If it returns -1 then we should RETRY
348 */
349 if ((retval = sc_err1(xs)) == -1) {
350 if ((*(sc_link->adapter->scsi_cmd)) (xs)
351 == SUCCESSFULLY_QUEUED) /* don't wake the job, ok? */
352 return;
353 xs->flags |= ITSDONE;
354 }
355 free_xs(xs, sc_link, SCSI_NOSLEEP); /* does a start if needed */
356 biodone(bp);
357 }
358
359 /*
360 * ask the scsi driver to perform a command for us.
361 * tell it where to read/write the data, and how
362 * long the data is supposed to be. If we have a buf
363 * to associate with the transfer, we need that too.
364 */
365 int
366 scsi_scsi_cmd(sc_link, scsi_cmd, cmdlen, data_addr, datalen,
367 retries, timeout, bp, flags)
368 struct scsi_link *sc_link;
369 struct scsi_generic *scsi_cmd;
370 u_int32 cmdlen;
371 u_char *data_addr;
372 u_int32 datalen;
373 u_int32 retries;
374 u_int32 timeout;
375 struct buf *bp;
376 u_int32 flags;
377 {
378 struct scsi_xfer *xs;
379 int retval;
380 u_int32 s;
381
382 if (bp)
383 flags |= SCSI_NOSLEEP;
384 SC_DEBUG(sc_link, SDEV_DB2, ("scsi_cmd\n"));
385
386 xs = get_xs(sc_link, flags); /* should wait unless booting */
387 if (!xs)
388 return (ENOMEM);
389 /*
390 * Fill out the scsi_xfer structure. We don't know whose context
391 * the cmd is in, so copy it.
392 */
393 bcopy(scsi_cmd, &(xs->cmdstore), cmdlen);
394 xs->flags = INUSE | flags;
395 xs->sc_link = sc_link;
396 xs->retries = retries;
397 xs->timeout = timeout;
398 xs->cmd = &xs->cmdstore;
399 xs->cmdlen = cmdlen;
400 xs->data = data_addr;
401 xs->datalen = datalen;
402 xs->resid = datalen;
403 xs->bp = bp;
404 /*XXX*/ /*use constant not magic number */
405 if (datalen && ((caddr_t) data_addr < (caddr_t) KERNBASE)) {
406 if (bp) {
407 printf("Data buffered space not in kernel context\n");
408 #ifdef SCSIDEBUG
409 show_scsi_cmd(xs);
410 #endif /* SCSIDEBUG */
411 retval = EFAULT;
412 goto bad;
413 }
414 xs->data = malloc(datalen, M_TEMP, M_WAITOK);
415 /* I think waiting is ok *//*XXX */
416 switch (flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
417 case 0:
418 printf("No direction flags, assuming both\n");
419 #ifdef SCSIDEBUG
420 show_scsi_cmd(xs);
421 #endif /* SCSIDEBUG */
422 case SCSI_DATA_IN | SCSI_DATA_OUT: /* weird */
423 case SCSI_DATA_OUT:
424 bcopy(data_addr, xs->data, datalen);
425 break;
426 case SCSI_DATA_IN:
427 bzero(xs->data, datalen);
428 }
429 }
430 retry:
431 xs->error = XS_NOERROR;
432 #ifdef DIAGNOSTIC
433 if (datalen && ((caddr_t) xs->data < (caddr_t) KERNBASE))
434 printf("It's still wrong!\n");
435 #endif /* DIAGNOSTIC */
436 #ifdef SCSIDEBUG
437 if (sc_link->flags & SDEV_DB3)
438 show_scsi_xs(xs);
439 #endif /* SCSIDEBUG */
440 /*
441 * Do the transfer. If we are polling we will return:
442 * COMPLETE, Was poll, and scsi_done has been called
443 * TRY_AGAIN_LATER, Adapter short resources, try again
444 *
445 * if under full steam (interrupts) it will return:
446 * SUCCESSFULLY_QUEUED, will do a wakeup when complete
447 * TRY_AGAIN_LATER, (as for polling)
448 * After the wakeup, we must still check if it succeeded
449 *
450 * If we have a bp however, all the error proccessing
451 * and the buffer code both expect us to return straight
452 * to them, so as soon as the command is queued, return
453 */
454
455 retval = (*(sc_link->adapter->scsi_cmd)) (xs);
456
457 switch (retval) {
458 case SUCCESSFULLY_QUEUED:
459 if (bp)
460 return retval; /* will sleep (or not) elsewhere */
461 s = splbio();
462 while (!(xs->flags & ITSDONE))
463 tsleep(xs, PRIBIO + 1, "scsi_scsi_cmd", 0);
464 splx(s);
465 /* fall through to check success of completed command */
466 case COMPLETE: /* Polling command completed ok */
467 /*XXX*/ case HAD_ERROR: /* Polling command completed with error */
468 SC_DEBUG(sc_link, SDEV_DB3, ("back in cmd()\n"));
469 if ((retval = sc_err1(xs)) == -1)
470 goto retry;
471 break;
472
473 case TRY_AGAIN_LATER: /* adapter resource shortage */
474 SC_DEBUG(sc_link, SDEV_DB3, ("will try again \n"));
475 /* should sleep 1 sec here */
476 if (xs->retries--) {
477 xs->flags &= ~ITSDONE;
478 goto retry;
479 }
480 default:
481 retval = EIO;
482 }
483 /*
484 * If we had to copy the data out of the user's context,
485 * then do the other half (copy it back or whatever)
486 * and free the memory buffer
487 */
488 if (datalen && (xs->data != data_addr)) {
489 switch (flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
490 case 0:
491 case SCSI_DATA_IN | SCSI_DATA_OUT: /* weird */
492 case SCSI_DATA_IN:
493 bcopy(xs->data, data_addr, datalen);
494 break;
495 }
496 free(xs->data, M_TEMP);
497 }
498 /*
499 * we have finished with the xfer stuct, free it and
500 * check if anyone else needs to be started up.
501 */
502 bad:
503 free_xs(xs, sc_link, flags); /* includes the 'start' op */
504 if (bp && retval) {
505 bp->b_error = retval;
506 bp->b_flags |= B_ERROR;
507 biodone(bp);
508 }
509 return (retval);
510 }
511
512 int
513 sc_err1(xs)
514 struct scsi_xfer *xs;
515 {
516 struct buf *bp = xs->bp;
517 int retval;
518
519 SC_DEBUG(xs->sc_link, SDEV_DB3, ("sc_err1,err = 0x%x \n", xs->error));
520 /*
521 * If it has a buf, we might be working with
522 * a request from the buffer cache or some other
523 * piece of code that requires us to process
524 * errors at inetrrupt time. We have probably
525 * been called by scsi_done()
526 */
527 switch (xs->error) {
528 case XS_NOERROR: /* nearly always hit this one */
529 retval = 0;
530 if (bp) {
531 bp->b_error = 0;
532 bp->b_resid = 0;
533 }
534 break;
535
536 case XS_SENSE:
537 if (bp) {
538 bp->b_error = 0;
539 bp->b_resid = 0;
540 if (retval = (scsi_interpret_sense(xs))) {
541 bp->b_flags |= B_ERROR;
542 bp->b_error = retval;
543 bp->b_resid = bp->b_bcount;
544 }
545 SC_DEBUG(xs->sc_link, SDEV_DB3,
546 ("scsi_interpret_sense (bp) returned %d\n", retval));
547 } else {
548 retval = (scsi_interpret_sense(xs));
549 SC_DEBUG(xs->sc_link, SDEV_DB3,
550 ("scsi_interpret_sense (no bp) returned %d\n", retval));
551 }
552 break;
553
554 case XS_BUSY:
555 /*should somehow arange for a 1 sec delay here (how?) */
556 case XS_TIMEOUT:
557 /*
558 * If we can, resubmit it to the adapter.
559 */
560 if (xs->retries--) {
561 xs->error = XS_NOERROR;
562 xs->flags &= ~ITSDONE;
563 goto retry;
564 }
565 /* fall through */
566 case XS_DRIVER_STUFFUP:
567 if (bp) {
568 bp->b_flags |= B_ERROR;
569 bp->b_error = EIO;
570 }
571 retval = EIO;
572 break;
573 default:
574 retval = EIO;
575 sc_print_addr(xs->sc_link);
576 printf("unknown error category from scsi driver\n");
577 }
578 return retval;
579 retry:
580 return (-1);
581 }
582
583 /*
584 * Look at the returned sense and act on the error, determining
585 * the unix error number to pass back. (0 = report no error)
586 *
587 * THIS IS THE DEFAULT ERROR HANDLER
588 */
589 int
590 scsi_interpret_sense(xs)
591 struct scsi_xfer *xs;
592 {
593 struct scsi_sense_data *sense;
594 struct scsi_link *sc_link = xs->sc_link;
595 u_int32 key;
596 u_int32 silent;
597 u_int32 info;
598 int error;
599
600 static char *error_mes[] =
601 {"soft error (corrected)",
602 "not ready", "medium error",
603 "non-media hardware failure", "illegal request",
604 "unit attention", "readonly device",
605 "no data found", "vendor unique",
606 "copy aborted", "command aborted",
607 "search returned equal", "volume overflow",
608 "verify miscompare", "unknown error key"
609 };
610
611 /*
612 * If the flags say errs are ok, then always return ok.
613 */
614 if (xs->flags & SCSI_ERR_OK)
615 return (0);
616
617 sense = &(xs->sense);
618 #ifdef SCSIDEBUG
619 if (sc_link->flags & SDEV_DB1) {
620 u_int32 count = 0;
621 printf("code%x valid%x ",
622 sense->error_code & SSD_ERRCODE,
623 sense->error_code & SSD_ERRCODE_VALID ? 1 : 0);
624 printf("seg%x key%x ili%x eom%x fmark%x\n",
625 sense->ext.extended.segment,
626 sense->ext.extended.flags & SSD_KEY,
627 sense->ext.extended.flags & SSD_ILI ? 1 : 0,
628 sense->ext.extended.flags & SSD_EOM ? 1 : 0,
629 sense->ext.extended.flags & SSD_FILEMARK ? 1 : 0);
630 printf("info: %x %x %x %x followed by %d extra bytes\n",
631 sense->ext.extended.info[0],
632 sense->ext.extended.info[1],
633 sense->ext.extended.info[2],
634 sense->ext.extended.info[3],
635 sense->ext.extended.extra_len);
636 printf("extra: ");
637 while (count < sense->ext.extended.extra_len)
638 printf("%x ", sense->ext.extended.extra_bytes[count++]);
639 printf("\n");
640 }
641 #endif /*SCSIDEBUG */
642 /*
643 * If the device has it's own error handler, call it first.
644 * If it returns a legit error value, return that, otherwise
645 * it wants us to continue with normal error processing.
646 */
647 if (sc_link->device->err_handler) {
648 SC_DEBUG(sc_link, SDEV_DB2, ("calling private err_handler()\n"));
649 error = (*sc_link->device->err_handler) (xs);
650 if (error != -1)
651 return error; /* error >= 0 better ? */
652 }
653 /* otherwise use the default */
654 silent = (xs->flags & SCSI_SILENT);
655 switch (sense->error_code & SSD_ERRCODE) {
656 /*
657 * If it's code 70, use the extended stuff and interpret the key
658 */
659 case 0x71: /* delayed error */
660 sc_print_addr(sc_link);
661 key = sense->ext.extended.flags & SSD_KEY;
662 printf(" DELAYED ERROR, key = 0x%x\n", key);
663 case 0x70:
664 if (sense->error_code & SSD_ERRCODE_VALID)
665 info = ntohl(*((long *) sense->ext.extended.info));
666 else
667 info = 0;
668 key = sense->ext.extended.flags & SSD_KEY;
669
670 if (key && !silent) {
671 sc_print_addr(sc_link);
672 printf("%s", error_mes[key - 1]);
673 if (sense->error_code & SSD_ERRCODE_VALID) {
674 switch (key) {
675 case 0x2: /* NOT READY */
676 case 0x5: /* ILLEGAL REQUEST */
677 case 0x6: /* UNIT ATTENTION */
678 case 0x7: /* DATA PROTECT */
679 break;
680 case 0x8: /* BLANK CHECK */
681 printf(", requested size: %d (decimal)",
682 info);
683 break;
684 default:
685 printf(", info = %d (decimal)", info);
686 }
687 }
688 printf("\n");
689 }
690 switch (key) {
691 case 0x0: /* NO SENSE */
692 case 0x1: /* RECOVERED ERROR */
693 if (xs->resid == xs->datalen)
694 xs->resid = 0; /* not short read */
695 case 0xc: /* EQUAL */
696 return (0);
697 case 0x2: /* NOT READY */
698 sc_link->flags &= ~SDEV_MEDIA_LOADED;
699 return (EBUSY);
700 case 0x5: /* ILLEGAL REQUEST */
701 return (EINVAL);
702 case 0x6: /* UNIT ATTENTION */
703 sc_link->flags &= ~SDEV_MEDIA_LOADED;
704 if (sc_link->flags & SDEV_OPEN)
705 return (EIO);
706 else
707 return 0;
708 case 0x7: /* DATA PROTECT */
709 return (EACCES);
710 case 0xd: /* VOLUME OVERFLOW */
711 return (ENOSPC);
712 case 0x8: /* BLANK CHECK */
713 return (0);
714 default:
715 return (EIO);
716 }
717 /*
718 * Not code 70, just report it
719 */
720 default:
721 if (!silent) {
722 sc_print_addr(sc_link);
723 printf("error code %d",
724 sense->error_code & SSD_ERRCODE);
725 if (sense->error_code & SSD_ERRCODE_VALID) {
726 printf(" at block no. %d (decimal)",
727 (sense->ext.unextended.blockhi << 16) +
728 (sense->ext.unextended.blockmed << 8) +
729 (sense->ext.unextended.blocklow));
730 }
731 printf("\n");
732 }
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 int val;
749 u_char *bytes;
750 {
751 *bytes++ = (val & 0xff0000) >> 16;
752 *bytes++ = (val & 0xff00) >> 8;
753 *bytes = val & 0xff;
754 }
755
756 /*
757 * The reverse of lto3b
758 */
759 int
760 _3btol(bytes)
761 u_char *bytes;
762 {
763 u_int32 rc;
764 rc = (*bytes++ << 16);
765 rc += (*bytes++ << 8);
766 rc += *bytes;
767 return ((int) rc);
768 }
769
770 /*
771 * Print out the scsi_link structure's address info.
772 */
773 void
774 sc_print_addr(sc_link)
775 struct scsi_link *sc_link;
776 {
777
778 printf("%s%d(%s:%d:%d): ",
779 sc_link->device->name, sc_link->dev_unit,
780 ((struct device *)sc_link->adapter_softc)->dv_xname,
781 sc_link->target, sc_link->lun);
782 }
783
784 #ifdef SCSIDEBUG
785 /*
786 * Given a scsi_xfer, dump the request, in all it's glory
787 */
788 void
789 show_scsi_xs(xs)
790 struct scsi_xfer *xs;
791 {
792 printf("xs(0x%x): ", xs);
793 printf("flg(0x%x)", xs->flags);
794 printf("sc_link(0x%x)", xs->sc_link);
795 printf("retr(0x%x)", xs->retries);
796 printf("timo(0x%x)", xs->timeout);
797 printf("cmd(0x%x)", xs->cmd);
798 printf("len(0x%x)", xs->cmdlen);
799 printf("data(0x%x)", xs->data);
800 printf("len(0x%x)", xs->datalen);
801 printf("res(0x%x)", xs->resid);
802 printf("err(0x%x)", xs->error);
803 printf("bp(0x%x)", xs->bp);
804 show_scsi_cmd(xs);
805 }
806
807 void
808 show_scsi_cmd(struct scsi_xfer *xs)
809 {
810 u_char *b = (u_char *) xs->cmd;
811 int i = 0;
812
813 sc_print_addr(xs->sc_link);
814 printf("command: ");
815
816 if (!(xs->flags & SCSI_RESET)) {
817 while (i < xs->cmdlen) {
818 if (i)
819 printf(",");
820 printf("%x", b[i++]);
821 }
822 printf("-[%d bytes]\n", xs->datalen);
823 if (xs->datalen)
824 show_mem(xs->data, min(64, xs->datalen));
825 } else
826 printf("-RESET-\n");
827 }
828
829 void
830 show_mem(address, num)
831 unsigned char *address;
832 u_int32 num;
833 {
834 u_int32 x, y;
835 printf("------------------------------");
836 for (y = 0; y < num; y += 1) {
837 if (!(y % 16))
838 printf("\n%03d: ", y);
839 printf("%02x ", *address++);
840 }
841 printf("\n------------------------------\n");
842 }
843 #endif /*SCSIDEBUG */
844