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