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