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