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