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