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