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