Home | History | Annotate | Line # | Download | only in scsipi
scsipi_base.c revision 1.5
      1 /*	$NetBSD: scsipi_base.c,v 1.5 1998/02/10 19:48:51 thorpej Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1994, 1995, 1997 Charles M. 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 M. 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/systm.h>
     39 #include <sys/kernel.h>
     40 #include <sys/buf.h>
     41 #include <sys/uio.h>
     42 #include <sys/malloc.h>
     43 #include <sys/errno.h>
     44 #include <sys/device.h>
     45 #include <sys/proc.h>
     46 
     47 #include <dev/scsipi/scsipi_all.h>
     48 #include <dev/scsipi/scsi_all.h>
     49 #include <dev/scsipi/scsipi_disk.h>
     50 #include <dev/scsipi/scsipiconf.h>
     51 #include <dev/scsipi/scsipi_base.h>
     52 
     53 struct xs_free_list xs_free_list;
     54 int	sc_err1 __P((struct scsipi_xfer *, int));
     55 
     56 /*
     57  * Get a scsipi transfer structure for the caller. Charge the structure
     58  * to the device that is referenced by the sc_link structure. If the
     59  * sc_link structure has no 'credits' then the device already has the
     60  * maximum number or outstanding operations under way. In this stage,
     61  * wait on the structure so that when one is freed, we are awoken again
     62  * If the SCSI_NOSLEEP flag is set, then do not wait, but rather, return
     63  * a NULL pointer, signifying that no slots were available
     64  * Note in the link structure, that we are waiting on it.
     65  */
     66 
     67 struct scsipi_xfer *
     68 scsipi_get_xs(sc_link, flags)
     69 	struct scsipi_link *sc_link;	/* who to charge the xs to */
     70 	int flags;			/* if this call can sleep */
     71 {
     72 	struct scsipi_xfer *xs;
     73 	int s;
     74 
     75 	SC_DEBUG(sc_link, SDEV_DB3, ("scsipi_get_xs\n"));
     76 	s = splbio();
     77 	while (sc_link->openings <= 0) {
     78 		SC_DEBUG(sc_link, SDEV_DB3, ("sleeping\n"));
     79 		if ((flags & SCSI_NOSLEEP) != 0) {
     80 			splx(s);
     81 			return (0);
     82 		}
     83 		sc_link->flags |= SDEV_WAITING;
     84 		(void)tsleep(sc_link, PRIBIO, "getxs", 0);
     85 	}
     86 	sc_link->openings--;
     87 	if ((xs = xs_free_list.lh_first) != NULL) {
     88 		LIST_REMOVE(xs, free_list);
     89 		splx(s);
     90 	} else {
     91 		splx(s);
     92 		SC_DEBUG(sc_link, SDEV_DB3, ("making\n"));
     93 		xs = malloc(sizeof(*xs), M_DEVBUF,
     94 		    ((flags & SCSI_NOSLEEP) != 0 ? M_NOWAIT : M_WAITOK));
     95 		if (xs == NULL) {
     96 			sc_link->sc_print_addr(sc_link);
     97 			printf("cannot allocate scsipi xs\n");
     98 			return (0);
     99 		}
    100 	}
    101 
    102 	SC_DEBUG(sc_link, SDEV_DB3, ("returning\n"));
    103 	/*
    104 	 * zero's out the command, as ATAPI may use longer commands
    105 	 * than SCSI
    106 	 */
    107 	bzero(&xs->cmdstore, sizeof(xs->cmdstore));
    108 	xs->flags = INUSE | flags;
    109 	return (xs);
    110 }
    111 
    112 /*
    113  * Given a scsipi_xfer struct, and a device (referenced through sc_link)
    114  * return the struct to the free pool and credit the device with it
    115  * If another process is waiting for an xs, do a wakeup, let it proceed
    116  */
    117 void
    118 scsipi_free_xs(xs, flags)
    119 	struct scsipi_xfer *xs;
    120 	int flags;
    121 {
    122 	struct scsipi_link *sc_link = xs->sc_link;
    123 
    124 	xs->flags &= ~INUSE;
    125 	LIST_INSERT_HEAD(&xs_free_list, xs, free_list);
    126 
    127 	SC_DEBUG(sc_link, SDEV_DB3, ("scsipi_free_xs\n"));
    128 	/* if was 0 and someone waits, wake them up */
    129 	sc_link->openings++;
    130 	if ((sc_link->flags & SDEV_WAITING) != 0) {
    131 		sc_link->flags &= ~SDEV_WAITING;
    132 		wakeup(sc_link);
    133 	} else {
    134 		if (sc_link->device->start) {
    135 			SC_DEBUG(sc_link, SDEV_DB2,
    136 			    ("calling private start()\n"));
    137 			(*(sc_link->device->start))(sc_link->device_softc);
    138 		}
    139 	}
    140 }
    141 
    142 /*
    143  * Find out from the device what its capacity is.
    144  */
    145 u_long
    146 scsipi_size(sc_link, flags)
    147 	struct scsipi_link *sc_link;
    148 	int flags;
    149 {
    150 	struct scsipi_read_cap_data rdcap;
    151 	struct scsipi_read_capacity scsipi_cmd;
    152 
    153 	/*
    154 	 * make up a scsipi command and ask the scsipi driver to do
    155 	 * it for you.
    156 	 */
    157 	bzero(&scsipi_cmd, sizeof(scsipi_cmd));
    158 	scsipi_cmd.opcode = READ_CAPACITY;
    159 
    160 	/*
    161 	 * If the command works, interpret the result as a 4 byte
    162 	 * number of blocks
    163 	 */
    164 	if (scsipi_command(sc_link, (struct scsipi_generic *)&scsipi_cmd,
    165 	    sizeof(scsipi_cmd), (u_char *)&rdcap, sizeof(rdcap),
    166 	    2, 20000, NULL, flags | SCSI_DATA_IN) != 0) {
    167 		sc_link->sc_print_addr(sc_link);
    168 		printf("could not get size\n");
    169 		return (0);
    170 	}
    171 
    172 	return (_4btol(rdcap.addr) + 1);
    173 }
    174 
    175 /*
    176  * Get scsipi driver to send a "are you ready?" command
    177  */
    178 int
    179 scsipi_test_unit_ready(sc_link, flags)
    180 	struct scsipi_link *sc_link;
    181 	int flags;
    182 {
    183 	struct scsipi_test_unit_ready scsipi_cmd;
    184 
    185 	/* some ATAPI drives don't support TEST_UNIT_READY. Sigh */
    186 	if (sc_link->quirks & ADEV_NOTUR)
    187 		return (0);
    188 
    189 	bzero(&scsipi_cmd, sizeof(scsipi_cmd));
    190 	scsipi_cmd.opcode = TEST_UNIT_READY;
    191 
    192 	return (scsipi_command(sc_link,
    193 	    (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
    194 	    0, 0, 2, 10000, NULL, flags));
    195 }
    196 
    197 /*
    198  * Do a scsipi operation asking a device what it is
    199  * Use the scsipi_cmd routine in the switch table.
    200  * XXX actually this is only used for scsi devices, because I have the feeling
    201  * that some atapi CDROM may not implement it, althouh it marked as mandatory
    202  * in the atapi specs.
    203  */
    204 int
    205 scsipi_inquire(sc_link, inqbuf, flags)
    206 	struct scsipi_link *sc_link;
    207 	struct scsipi_inquiry_data *inqbuf;
    208 	int flags;
    209 {
    210 	struct scsipi_inquiry scsipi_cmd;
    211 
    212 	bzero(&scsipi_cmd, sizeof(scsipi_cmd));
    213 	scsipi_cmd.opcode = INQUIRY;
    214 	scsipi_cmd.length = sizeof(struct scsipi_inquiry_data);
    215 
    216 	return (scsipi_command(sc_link,
    217 	    (struct scsipi_generic *) &scsipi_cmd, sizeof(scsipi_cmd),
    218 	    (u_char *) inqbuf, sizeof(struct scsipi_inquiry_data),
    219 	    2, 10000, NULL, SCSI_DATA_IN | flags));
    220 }
    221 
    222 /*
    223  * Prevent or allow the user to remove the media
    224  */
    225 int
    226 scsipi_prevent(sc_link, type, flags)
    227 	struct scsipi_link *sc_link;
    228 	int type, flags;
    229 {
    230 	struct scsipi_prevent scsipi_cmd;
    231 
    232 	if (sc_link->quirks & ADEV_NODOORLOCK)
    233 		return (0);
    234 
    235 	bzero(&scsipi_cmd, sizeof(scsipi_cmd));
    236 	scsipi_cmd.opcode = PREVENT_ALLOW;
    237 	scsipi_cmd.how = type;
    238 	return (scsipi_command(sc_link,
    239 	    (struct scsipi_generic *) &scsipi_cmd, sizeof(scsipi_cmd),
    240 	    0, 0, 2, 5000, NULL, flags));
    241 }
    242 
    243 /*
    244  * Get scsipi driver to send a "start up" command
    245  */
    246 int
    247 scsipi_start(sc_link, type, flags)
    248 	struct scsipi_link *sc_link;
    249 	int type, flags;
    250 {
    251 	struct scsipi_start_stop scsipi_cmd;
    252 
    253 	bzero(&scsipi_cmd, sizeof(scsipi_cmd));
    254 	scsipi_cmd.opcode = START_STOP;
    255 	scsipi_cmd.byte2 = 0x00;
    256 	scsipi_cmd.how = type;
    257 	return (scsipi_command(sc_link,
    258 	    (struct scsipi_generic *) &scsipi_cmd, sizeof(scsipi_cmd),
    259 	    0, 0, 2, type == SSS_START ? 30000 : 10000, NULL, flags));
    260 }
    261 
    262 /*
    263  * This routine is called by the scsipi interrupt when the transfer is
    264  * complete.
    265  */
    266 void
    267 scsipi_done(xs)
    268 	struct scsipi_xfer *xs;
    269 {
    270 	struct scsipi_link *sc_link = xs->sc_link;
    271 	struct buf *bp;
    272 	int error;
    273 
    274 	SC_DEBUG(sc_link, SDEV_DB2, ("scsipi_done\n"));
    275 #ifdef	SCSIDEBUG
    276 	if ((sc_link->flags & SDEV_DB1) != 0)
    277 		show_scsipi_cmd(xs);
    278 #endif /* SCSIDEBUG */
    279 
    280 	/*
    281 	 * If it's a user level request, bypass all usual completion
    282 	 * processing, let the user work it out..  We take
    283 	 * reponsibility for freeing the xs when the user returns.
    284 	 * (and restarting the device's queue).
    285 	 */
    286 	if ((xs->flags & SCSI_USER) != 0) {
    287 		SC_DEBUG(sc_link, SDEV_DB3, ("calling user done()\n"));
    288 		scsipi_user_done(xs); /* to take a copy of the sense etc. */
    289 		SC_DEBUG(sc_link, SDEV_DB3, ("returned from user done()\n "));
    290 
    291 		scsipi_free_xs(xs, SCSI_NOSLEEP); /* restarts queue too */
    292 		SC_DEBUG(sc_link, SDEV_DB3, ("returning to adapter\n"));
    293 		return;
    294 	}
    295 
    296 	if (!((xs->flags & (SCSI_NOSLEEP | SCSI_POLL)) == SCSI_NOSLEEP)) {
    297 		/*
    298 		 * if it's a normal upper level request, then ask
    299 		 * the upper level code to handle error checking
    300 		 * rather than doing it here at interrupt time
    301 		 */
    302 		wakeup(xs);
    303 		return;
    304 	}
    305 
    306 	/*
    307 	 * Go and handle errors now.
    308 	 * If it returns ERESTART then we should RETRY
    309 	 */
    310 retry:
    311 	error = sc_err1(xs, 1);
    312 	if (error == ERESTART)
    313 		switch (scsipi_command_direct(xs)) {
    314 		case SUCCESSFULLY_QUEUED:
    315 			return;
    316 
    317 		case TRY_AGAIN_LATER:
    318 			xs->error = XS_BUSY;
    319 		case COMPLETE:
    320 			goto retry;
    321 		}
    322 
    323 	bp = xs->bp;
    324 	if (bp) {
    325 		if (error) {
    326 			bp->b_error = error;
    327 			bp->b_flags |= B_ERROR;
    328 			bp->b_resid = bp->b_bcount;
    329 		} else {
    330 			bp->b_error = 0;
    331 			bp->b_resid = xs->resid;
    332 		}
    333 	}
    334 	if (sc_link->device->done) {
    335 		/*
    336 		 * Tell the device the operation is actually complete.
    337 		 * No more will happen with this xfer.  This for
    338 		 * notification of the upper-level driver only; they
    339 		 * won't be returning any meaningful information to us.
    340 		 */
    341 		(*sc_link->device->done)(xs);
    342 	}
    343 	scsipi_free_xs(xs, SCSI_NOSLEEP);
    344 	if (bp)
    345 		biodone(bp);
    346 }
    347 
    348 int
    349 scsipi_execute_xs(xs)
    350 	struct scsipi_xfer *xs;
    351 {
    352 	int error;
    353 	int s;
    354 
    355 	xs->flags &= ~ITSDONE;
    356 	xs->error = XS_NOERROR;
    357 	xs->resid = xs->datalen;
    358 	xs->status = 0;
    359 
    360 retry:
    361 	/*
    362 	 * Do the transfer. If we are polling we will return:
    363 	 * COMPLETE,  Was poll, and scsipi_done has been called
    364 	 * TRY_AGAIN_LATER, Adapter short resources, try again
    365 	 *
    366 	 * if under full steam (interrupts) it will return:
    367 	 * SUCCESSFULLY_QUEUED, will do a wakeup when complete
    368 	 * TRY_AGAIN_LATER, (as for polling)
    369 	 * After the wakeup, we must still check if it succeeded
    370 	 *
    371 	 * If we have a SCSI_NOSLEEP (typically because we have a buf)
    372 	 * we just return.  All the error proccessing and the buffer
    373 	 * code both expect us to return straight to them, so as soon
    374 	 * as the command is queued, return.
    375 	 */
    376 #ifdef SCSIDEBUG
    377 	if (xs->sc_link->flags & SDEV_DB3) {
    378 		printf("scsipi_exec_cmd: ");
    379 		show_scsipi_xs(xs);
    380 		printf("\n");
    381 	}
    382 #endif
    383 	switch (scsipi_command_direct(xs)) {
    384 	case SUCCESSFULLY_QUEUED:
    385 		if ((xs->flags & (SCSI_NOSLEEP | SCSI_POLL)) == SCSI_NOSLEEP)
    386 			return (EJUSTRETURN);
    387 #ifdef DIAGNOSTIC
    388 		if (xs->flags & SCSI_NOSLEEP)
    389 			panic("scsipi_execute_xs: NOSLEEP and POLL");
    390 #endif
    391 		s = splbio();
    392 		while ((xs->flags & ITSDONE) == 0)
    393 			tsleep(xs, PRIBIO + 1, "scsipi_cmd", 0);
    394 		splx(s);
    395 	case COMPLETE:		/* Polling command completed ok */
    396 		if (xs->bp)
    397 			return (EJUSTRETURN);
    398 	doit:
    399 		SC_DEBUG(xs->sc_link, SDEV_DB3, ("back in cmd()\n"));
    400 		if ((error = sc_err1(xs, 0)) != ERESTART)
    401 			return (error);
    402 		goto retry;
    403 
    404 	case TRY_AGAIN_LATER:	/* adapter resource shortage */
    405 		xs->error = XS_BUSY;
    406 		goto doit;
    407 
    408 	default:
    409 		panic("scsipi_execute_xs: invalid return code");
    410 	}
    411 
    412 #ifdef DIAGNOSTIC
    413 	panic("scsipi_execute_xs: impossible");
    414 #endif
    415 	return (EINVAL);
    416 }
    417 
    418 int
    419 sc_err1(xs, async)
    420 	struct scsipi_xfer *xs;
    421 	int async;
    422 {
    423 	int error;
    424 
    425 	SC_DEBUG(xs->sc_link, SDEV_DB3, ("sc_err1,err = 0x%x \n", xs->error));
    426 
    427 	/*
    428 	 * If it has a buf, we might be working with
    429 	 * a request from the buffer cache or some other
    430 	 * piece of code that requires us to process
    431 	 * errors at inetrrupt time. We have probably
    432 	 * been called by scsipi_done()
    433 	 */
    434 	switch (xs->error) {
    435 	case XS_NOERROR:	/* nearly always hit this one */
    436 		error = 0;
    437 		break;
    438 
    439 	case XS_SENSE:
    440 		if ((error = (*xs->sc_link->scsipi_interpret_sense)(xs)) ==
    441 		    ERESTART)
    442 			goto retry;
    443 		SC_DEBUG(xs->sc_link, SDEV_DB3,
    444 		    ("scsipi_interpret_sense returned %d\n", error));
    445 		break;
    446 
    447 	case XS_BUSY:
    448 		if (xs->retries) {
    449 			if ((xs->flags & SCSI_POLL) != 0)
    450 				delay(1000000);
    451 			else if ((xs->flags & SCSI_NOSLEEP) == 0)
    452 				tsleep(&lbolt, PRIBIO, "scbusy", 0);
    453 			else
    454 #if 0
    455 				timeout(scsipi_requeue, xs, hz);
    456 #else
    457 				goto lose;
    458 #endif
    459 		}
    460 	case XS_TIMEOUT:
    461 	retry:
    462 		if (xs->retries--) {
    463 			xs->error = XS_NOERROR;
    464 			xs->flags &= ~ITSDONE;
    465 			return (ERESTART);
    466 		}
    467 	case XS_DRIVER_STUFFUP:
    468 	lose:
    469 		error = EIO;
    470 		break;
    471 
    472 	case XS_SELTIMEOUT:
    473 		/* XXX Disable device? */
    474 		error = EIO;
    475 		break;
    476 
    477 	default:
    478 		(*xs->sc_link->sc_print_addr)(xs->sc_link);
    479 		printf("unknown error category from scsipi driver\n");
    480 		error = EIO;
    481 		break;
    482 	}
    483 
    484 	return (error);
    485 }
    486 
    487 #ifdef	SCSIDEBUG
    488 /*
    489  * Given a scsipi_xfer, dump the request, in all it's glory
    490  */
    491 void
    492 show_scsipi_xs(xs)
    493 	struct scsipi_xfer *xs;
    494 {
    495 
    496 	printf("xs(%p): ", xs);
    497 	printf("flg(0x%x)", xs->flags);
    498 	printf("sc_link(%p)", xs->sc_link);
    499 	printf("retr(0x%x)", xs->retries);
    500 	printf("timo(0x%x)", xs->timeout);
    501 	printf("cmd(%p)", xs->cmd);
    502 	printf("len(0x%x)", xs->cmdlen);
    503 	printf("data(%p)", xs->data);
    504 	printf("len(0x%x)", xs->datalen);
    505 	printf("res(0x%x)", xs->resid);
    506 	printf("err(0x%x)", xs->error);
    507 	printf("bp(%p)", xs->bp);
    508 	show_scsipi_cmd(xs);
    509 }
    510 
    511 void
    512 show_scsipi_cmd(xs)
    513 	struct scsipi_xfer *xs;
    514 {
    515 	u_char *b = (u_char *) xs->cmd;
    516 	int i = 0;
    517 
    518 	(*xs->sc_link->sc_print_addr)(xs->sc_link);
    519 	printf("command: ");
    520 
    521 	if ((xs->flags & SCSI_RESET) == 0) {
    522 		while (i < xs->cmdlen) {
    523 			if (i)
    524 				printf(",");
    525 			printf("0x%x", b[i++]);
    526 		}
    527 		printf("-[%d bytes]\n", xs->datalen);
    528 		if (xs->datalen)
    529 			show_mem(xs->data, min(64, xs->datalen));
    530 	} else
    531 		printf("-RESET-\n");
    532 }
    533 
    534 void
    535 show_mem(address, num)
    536 	u_char *address;
    537 	int num;
    538 {
    539 	int x;
    540 
    541 	printf("------------------------------");
    542 	for (x = 0; x < num; x++) {
    543 		if ((x % 16) == 0)
    544 			printf("\n%03d: ", x);
    545 		printf("%02x ", *address++);
    546 	}
    547 	printf("\n------------------------------\n");
    548 }
    549 #endif /*SCSIDEBUG */
    550 
    551