xref: /netbsd-src/sys/dev/scsipi/scsi_base.c (revision d9158b13b5dfe46201430699a3f7a235ecf28df3)
1 /*
2  * Copyright (c) 1994 Charles Hannum.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  * 3. All advertising materials mentioning features or use of this software
13  *    must display the following acknowledgement:
14  *	This product includes software developed by Charles Hannum.
15  * 4. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *      $Id: scsi_base.c,v 1.13 1994/05/09 07:40:52 chopps Exp $
30  */
31 
32 /*
33  * Originally written by Julian Elischer (julian@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 			info = ntohl(*((long *) sense->extended_info));
622 		else
623 			info = 0;
624 		key = sense->extended_flags & SSD_KEY;
625 
626 		if (key && !silent) {
627 			sc_print_addr(sc_link);
628 			printf("%s", error_mes[key - 1]);
629 			if (sense->error_code & SSD_ERRCODE_VALID) {
630 				switch (key) {
631 				case 0x2:	/* NOT READY */
632 				case 0x5:	/* ILLEGAL REQUEST */
633 				case 0x6:	/* UNIT ATTENTION */
634 				case 0x7:	/* DATA PROTECT */
635 					break;
636 				case 0x8:	/* BLANK CHECK */
637 					printf(", requested size: %d (decimal)",
638 					    info);
639 					break;
640 				default:
641 					printf(", info = %d (decimal)", info);
642 				}
643 			}
644 			printf("\n");
645 		}
646 		switch (key) {
647 		case 0x0:	/* NO SENSE */
648 		case 0x1:	/* RECOVERED ERROR */
649 			if (xs->resid == xs->datalen)
650 				xs->resid = 0;	/* not short read */
651 		case 0xc:	/* EQUAL */
652 			return 0;
653 		case 0x2:	/* NOT READY */
654 			sc_link->flags &= ~SDEV_MEDIA_LOADED;
655 			return EBUSY;
656 		case 0x5:	/* ILLEGAL REQUEST */
657 			return EINVAL;
658 		case 0x6:	/* UNIT ATTENTION */
659 			sc_link->flags &= ~SDEV_MEDIA_LOADED;
660 			if (sc_link->flags & SDEV_OPEN)
661 				return EIO;
662 			else
663 				return 0;
664 		case 0x7:	/* DATA PROTECT */
665 			return EACCES;
666 		case 0xd:	/* VOLUME OVERFLOW */
667 			return ENOSPC;
668 		case 0x8:	/* BLANK CHECK */
669 			return 0;
670 		default:
671 			return EIO;
672 		}
673 	/*
674 	 * Not code 70, just report it
675 	 */
676 	default:
677 		if (!silent) {
678 			sc_print_addr(sc_link);
679 			printf("error code %d",
680 			    sense->error_code & SSD_ERRCODE);
681 			if (sense->error_code & SSD_ERRCODE_VALID) {
682 				printf(" at block no. %d (decimal)",
683 				    (sense->XXX_unextended_blockhi << 16) +
684 				    (sense->XXX_unextended_blockmed << 8) +
685 				    (sense->XXX_unextended_blocklow));
686 			}
687 			printf("\n");
688 		}
689 		return EIO;
690 	}
691 }
692 
693 /*
694  * Utility routines often used in SCSI stuff
695  */
696 
697 /*
698  * convert a physical address to 3 bytes,
699  * MSB at the lowest address,
700  * LSB at the highest.
701  */
702 void
703 lto3b(val, bytes)
704 	int	val;
705 	u_char	*bytes;
706 {
707 	*bytes++ = (val & 0xff0000) >> 16;
708 	*bytes++ = (val & 0xff00) >> 8;
709 	*bytes = val & 0xff;
710 }
711 
712 /*
713  * The reverse of lto3b
714  */
715 int
716 _3btol(bytes)
717 	u_char *bytes;
718 {
719 	u_int32 rc;
720 	rc = (*bytes++ << 16);
721 	rc += (*bytes++ << 8);
722 	rc += *bytes;
723 	return ((int) rc);
724 }
725 
726 /*
727  * Print out the scsi_link structure's address info.
728  */
729 void
730 sc_print_addr(sc_link)
731 	struct	scsi_link *sc_link;
732 {
733 
734 	printf("%s%d(%s:%d:%d): ",
735 		sc_link->device->name, sc_link->dev_unit,
736 		((struct device *)sc_link->adapter_softc)->dv_xname,
737 		sc_link->target, sc_link->lun);
738 }
739 
740 #ifdef	SCSIDEBUG
741 /*
742  * Given a scsi_xfer, dump the request, in all it's glory
743  */
744 void
745 show_scsi_xs(xs)
746 	struct scsi_xfer *xs;
747 {
748 	printf("xs(0x%x): ", xs);
749 	printf("flg(0x%x)", xs->flags);
750 	printf("sc_link(0x%x)", xs->sc_link);
751 	printf("retr(0x%x)", xs->retries);
752 	printf("timo(0x%x)", xs->timeout);
753 	printf("cmd(0x%x)", xs->cmd);
754 	printf("len(0x%x)", xs->cmdlen);
755 	printf("data(0x%x)", xs->data);
756 	printf("len(0x%x)", xs->datalen);
757 	printf("res(0x%x)", xs->resid);
758 	printf("err(0x%x)", xs->error);
759 	printf("bp(0x%x)", xs->bp);
760 	show_scsi_cmd(xs);
761 }
762 
763 void
764 show_scsi_cmd(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