Home | History | Annotate | Line # | Download | only in scsipi
scsipi_base.c revision 1.36
      1  1.36      fvdl /*	$NetBSD: scsipi_base.c,v 1.36 2000/05/27 23:59:58 fvdl Exp $	*/
      2   1.2    bouyer 
      3   1.8   mycroft /*-
      4   1.8   mycroft  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5   1.8   mycroft  * All rights reserved.
      6   1.8   mycroft  *
      7   1.8   mycroft  * This code is derived from software contributed to The NetBSD Foundation
      8   1.8   mycroft  * by Charles M. Hannum.
      9   1.2    bouyer  *
     10   1.2    bouyer  * Redistribution and use in source and binary forms, with or without
     11   1.2    bouyer  * modification, are permitted provided that the following conditions
     12   1.2    bouyer  * are met:
     13   1.2    bouyer  * 1. Redistributions of source code must retain the above copyright
     14   1.2    bouyer  *    notice, this list of conditions and the following disclaimer.
     15   1.2    bouyer  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.2    bouyer  *    notice, this list of conditions and the following disclaimer in the
     17   1.2    bouyer  *    documentation and/or other materials provided with the distribution.
     18   1.2    bouyer  * 3. All advertising materials mentioning features or use of this software
     19   1.2    bouyer  *    must display the following acknowledgement:
     20   1.8   mycroft  *        This product includes software developed by the NetBSD
     21   1.8   mycroft  *        Foundation, Inc. and its contributors.
     22   1.8   mycroft  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23   1.8   mycroft  *    contributors may be used to endorse or promote products derived
     24   1.8   mycroft  *    from this software without specific prior written permission.
     25   1.2    bouyer  *
     26   1.8   mycroft  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27   1.8   mycroft  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28   1.8   mycroft  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29   1.8   mycroft  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30   1.8   mycroft  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31   1.8   mycroft  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32   1.8   mycroft  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33   1.8   mycroft  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34   1.8   mycroft  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35   1.8   mycroft  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36   1.8   mycroft  * POSSIBILITY OF SUCH DAMAGE.
     37   1.2    bouyer  */
     38   1.2    bouyer 
     39  1.13    bouyer #include "opt_scsi.h"
     40  1.13    bouyer 
     41   1.2    bouyer #include <sys/types.h>
     42   1.2    bouyer #include <sys/param.h>
     43   1.2    bouyer #include <sys/systm.h>
     44   1.2    bouyer #include <sys/kernel.h>
     45   1.2    bouyer #include <sys/buf.h>
     46   1.2    bouyer #include <sys/uio.h>
     47   1.2    bouyer #include <sys/malloc.h>
     48   1.6   thorpej #include <sys/pool.h>
     49   1.2    bouyer #include <sys/errno.h>
     50   1.2    bouyer #include <sys/device.h>
     51   1.2    bouyer #include <sys/proc.h>
     52   1.2    bouyer 
     53   1.2    bouyer #include <dev/scsipi/scsipi_all.h>
     54   1.2    bouyer #include <dev/scsipi/scsipi_disk.h>
     55   1.2    bouyer #include <dev/scsipi/scsipiconf.h>
     56   1.2    bouyer #include <dev/scsipi/scsipi_base.h>
     57   1.2    bouyer 
     58   1.6   thorpej struct pool scsipi_xfer_pool;
     59   1.6   thorpej 
     60   1.3     enami int	sc_err1 __P((struct scsipi_xfer *, int));
     61   1.2    bouyer 
     62   1.2    bouyer /*
     63   1.6   thorpej  * Called when a scsibus is attached to initialize global data.
     64   1.6   thorpej  */
     65   1.6   thorpej void
     66   1.6   thorpej scsipi_init()
     67   1.6   thorpej {
     68   1.6   thorpej 	static int scsipi_init_done;
     69   1.6   thorpej 
     70   1.6   thorpej 	if (scsipi_init_done)
     71   1.6   thorpej 		return;
     72   1.6   thorpej 	scsipi_init_done = 1;
     73   1.6   thorpej 
     74   1.6   thorpej 	/* Initialize the scsipi_xfer pool. */
     75   1.6   thorpej 	pool_init(&scsipi_xfer_pool, sizeof(struct scsipi_xfer), 0,
     76   1.6   thorpej 	    0, 0, "scxspl", 0, NULL, NULL, M_DEVBUF);
     77   1.6   thorpej }
     78   1.6   thorpej 
     79   1.6   thorpej /*
     80   1.2    bouyer  * Get a scsipi transfer structure for the caller. Charge the structure
     81   1.3     enami  * to the device that is referenced by the sc_link structure. If the
     82   1.2    bouyer  * sc_link structure has no 'credits' then the device already has the
     83   1.2    bouyer  * maximum number or outstanding operations under way. In this stage,
     84   1.2    bouyer  * wait on the structure so that when one is freed, we are awoken again
     85  1.24   thorpej  * If the XS_CTL_NOSLEEP flag is set, then do not wait, but rather, return
     86   1.2    bouyer  * a NULL pointer, signifying that no slots were available
     87   1.2    bouyer  * Note in the link structure, that we are waiting on it.
     88   1.2    bouyer  */
     89   1.2    bouyer 
     90   1.2    bouyer struct scsipi_xfer *
     91   1.2    bouyer scsipi_get_xs(sc_link, flags)
     92   1.2    bouyer 	struct scsipi_link *sc_link;	/* who to charge the xs to */
     93   1.2    bouyer 	int flags;			/* if this call can sleep */
     94   1.2    bouyer {
     95   1.2    bouyer 	struct scsipi_xfer *xs;
     96   1.2    bouyer 	int s;
     97   1.2    bouyer 
     98   1.2    bouyer 	SC_DEBUG(sc_link, SDEV_DB3, ("scsipi_get_xs\n"));
     99   1.6   thorpej 
    100  1.24   thorpej 	/*
    101  1.24   thorpej 	 * If we're cold, make sure we poll.
    102  1.24   thorpej 	 */
    103  1.24   thorpej 	if (cold)
    104  1.24   thorpej 		flags |= XS_CTL_NOSLEEP | XS_CTL_POLL;
    105  1.24   thorpej 
    106   1.2    bouyer 	s = splbio();
    107  1.35    bouyer 	while ((sc_link->active >= sc_link->openings) &&
    108  1.35    bouyer 	    ((flags & XS_CTL_URGENT) == 0)) {
    109   1.2    bouyer 		SC_DEBUG(sc_link, SDEV_DB3, ("sleeping\n"));
    110  1.24   thorpej 		if ((flags & XS_CTL_NOSLEEP) != 0) {
    111   1.2    bouyer 			splx(s);
    112   1.3     enami 			return (0);
    113   1.2    bouyer 		}
    114   1.2    bouyer 		sc_link->flags |= SDEV_WAITING;
    115   1.3     enami 		(void)tsleep(sc_link, PRIBIO, "getxs", 0);
    116   1.2    bouyer 	}
    117   1.6   thorpej 	SC_DEBUG(sc_link, SDEV_DB3, ("calling pool_get\n"));
    118   1.6   thorpej 	xs = pool_get(&scsipi_xfer_pool,
    119  1.24   thorpej 	    ((flags & XS_CTL_NOSLEEP) != 0 ? PR_NOWAIT : PR_WAITOK));
    120   1.6   thorpej 	if (xs != NULL)
    121  1.24   thorpej 		sc_link->active++;
    122   1.6   thorpej 	else {
    123   1.6   thorpej 		(*sc_link->sc_print_addr)(sc_link);
    124   1.6   thorpej 		printf("cannot allocate scsipi xs\n");
    125   1.2    bouyer 	}
    126   1.6   thorpej 	splx(s);
    127   1.2    bouyer 
    128   1.2    bouyer 	SC_DEBUG(sc_link, SDEV_DB3, ("returning\n"));
    129   1.6   thorpej 
    130   1.3     enami 	/*
    131   1.7    scottr 	 * zeroes out the command, as ATAPI may use longer commands
    132   1.3     enami 	 * than SCSI
    133   1.3     enami 	 */
    134   1.7    scottr 	if (xs != NULL) {
    135  1.30   thorpej 		callout_init(&xs->xs_callout);
    136  1.24   thorpej 		xs->xs_control = flags;
    137  1.15   thorpej 		TAILQ_INSERT_TAIL(&sc_link->pending_xfers, xs, device_q);
    138   1.7    scottr 		bzero(&xs->cmdstore, sizeof(xs->cmdstore));
    139   1.7    scottr 	}
    140   1.3     enami 	return (xs);
    141   1.2    bouyer }
    142   1.2    bouyer 
    143   1.2    bouyer /*
    144   1.2    bouyer  * Given a scsipi_xfer struct, and a device (referenced through sc_link)
    145   1.2    bouyer  * return the struct to the free pool and credit the device with it
    146   1.2    bouyer  * If another process is waiting for an xs, do a wakeup, let it proceed
    147   1.6   thorpej  *
    148   1.6   thorpej  * MUST BE CALLED AT splbio()!!
    149   1.2    bouyer  */
    150   1.3     enami void
    151   1.2    bouyer scsipi_free_xs(xs, flags)
    152   1.2    bouyer 	struct scsipi_xfer *xs;
    153   1.2    bouyer 	int flags;
    154   1.2    bouyer {
    155   1.2    bouyer 	struct scsipi_link *sc_link = xs->sc_link;
    156   1.2    bouyer 
    157  1.15   thorpej 	TAILQ_REMOVE(&sc_link->pending_xfers, xs, device_q);
    158  1.15   thorpej 	if (TAILQ_FIRST(&sc_link->pending_xfers) == NULL &&
    159  1.16   thorpej 	    (sc_link->flags & SDEV_WAITDRAIN) != 0) {
    160  1.16   thorpej 		sc_link->flags &= ~SDEV_WAITDRAIN;
    161  1.15   thorpej 		wakeup(&sc_link->pending_xfers);
    162  1.16   thorpej 	}
    163   1.6   thorpej 	pool_put(&scsipi_xfer_pool, xs);
    164   1.2    bouyer 
    165   1.2    bouyer 	SC_DEBUG(sc_link, SDEV_DB3, ("scsipi_free_xs\n"));
    166   1.2    bouyer 	/* if was 0 and someone waits, wake them up */
    167  1.24   thorpej 	sc_link->active--;
    168   1.2    bouyer 	if ((sc_link->flags & SDEV_WAITING) != 0) {
    169   1.2    bouyer 		sc_link->flags &= ~SDEV_WAITING;
    170   1.2    bouyer 		wakeup(sc_link);
    171   1.2    bouyer 	} else {
    172   1.2    bouyer 		if (sc_link->device->start) {
    173   1.3     enami 			SC_DEBUG(sc_link, SDEV_DB2,
    174   1.3     enami 			    ("calling private start()\n"));
    175   1.3     enami 			(*(sc_link->device->start))(sc_link->device_softc);
    176   1.2    bouyer 		}
    177   1.2    bouyer 	}
    178  1.15   thorpej }
    179  1.15   thorpej 
    180  1.15   thorpej /*
    181  1.15   thorpej  * Wait for a scsipi_link's pending xfers to drain.
    182  1.15   thorpej  */
    183  1.15   thorpej void
    184  1.15   thorpej scsipi_wait_drain(sc_link)
    185  1.15   thorpej 	struct scsipi_link *sc_link;
    186  1.15   thorpej {
    187  1.15   thorpej 	int s;
    188  1.15   thorpej 
    189  1.15   thorpej 	s = splbio();
    190  1.16   thorpej 	while (TAILQ_FIRST(&sc_link->pending_xfers) != NULL) {
    191  1.15   thorpej 		sc_link->flags |= SDEV_WAITDRAIN;
    192  1.15   thorpej 		(void) tsleep(&sc_link->pending_xfers, PRIBIO, "sxdrn", 0);
    193  1.15   thorpej 	}
    194  1.15   thorpej 	splx(s);
    195  1.23   thorpej }
    196  1.23   thorpej 
    197  1.23   thorpej /*
    198  1.23   thorpej  * Kill off all pending xfers for a scsipi_link.
    199  1.23   thorpej  *
    200  1.23   thorpej  * Must be called at splbio().
    201  1.23   thorpej  */
    202  1.23   thorpej void
    203  1.23   thorpej scsipi_kill_pending(sc_link)
    204  1.23   thorpej 	struct scsipi_link *sc_link;
    205  1.23   thorpej {
    206  1.23   thorpej 
    207  1.27     enami 	(*sc_link->scsipi_kill_pending)(sc_link);
    208  1.34     enami 	scsipi_wait_drain(sc_link);
    209   1.2    bouyer }
    210   1.2    bouyer 
    211   1.2    bouyer /*
    212  1.13    bouyer  * Look at the returned sense and act on the error, determining
    213  1.13    bouyer  * the unix error number to pass back.  (0 = report no error)
    214  1.13    bouyer  *
    215  1.13    bouyer  * THIS IS THE DEFAULT ERROR HANDLER FOR SCSI DEVICES
    216  1.13    bouyer  */
    217  1.13    bouyer int
    218  1.13    bouyer scsipi_interpret_sense(xs)
    219  1.13    bouyer 	struct scsipi_xfer *xs;
    220  1.13    bouyer {
    221  1.13    bouyer 	struct scsipi_sense_data *sense;
    222  1.13    bouyer 	struct scsipi_link *sc_link = xs->sc_link;
    223  1.13    bouyer 	u_int8_t key;
    224  1.13    bouyer 	u_int32_t info;
    225  1.13    bouyer 	int error;
    226  1.13    bouyer #ifndef	SCSIVERBOSE
    227  1.13    bouyer 	static char *error_mes[] = {
    228  1.13    bouyer 		"soft error (corrected)",
    229  1.13    bouyer 		"not ready", "medium error",
    230  1.13    bouyer 		"non-media hardware failure", "illegal request",
    231  1.13    bouyer 		"unit attention", "readonly device",
    232  1.13    bouyer 		"no data found", "vendor unique",
    233  1.13    bouyer 		"copy aborted", "command aborted",
    234  1.13    bouyer 		"search returned equal", "volume overflow",
    235  1.13    bouyer 		"verify miscompare", "unknown error key"
    236  1.13    bouyer 	};
    237  1.13    bouyer #endif
    238  1.13    bouyer 
    239  1.13    bouyer 	sense = &xs->sense.scsi_sense;
    240  1.13    bouyer #ifdef	SCSIDEBUG
    241  1.13    bouyer 	if ((sc_link->flags & SDEV_DB1) != 0) {
    242  1.13    bouyer 		int count;
    243  1.13    bouyer 		printf("code 0x%x valid 0x%x ",
    244  1.13    bouyer 			sense->error_code & SSD_ERRCODE,
    245  1.13    bouyer 			sense->error_code & SSD_ERRCODE_VALID ? 1 : 0);
    246  1.13    bouyer 		printf("seg 0x%x key 0x%x ili 0x%x eom 0x%x fmark 0x%x\n",
    247  1.13    bouyer 			sense->segment,
    248  1.13    bouyer 			sense->flags & SSD_KEY,
    249  1.13    bouyer 			sense->flags & SSD_ILI ? 1 : 0,
    250  1.13    bouyer 			sense->flags & SSD_EOM ? 1 : 0,
    251  1.13    bouyer 			sense->flags & SSD_FILEMARK ? 1 : 0);
    252  1.13    bouyer 		printf("info: 0x%x 0x%x 0x%x 0x%x followed by %d extra bytes\n",
    253  1.13    bouyer 			sense->info[0],
    254  1.13    bouyer 			sense->info[1],
    255  1.13    bouyer 			sense->info[2],
    256  1.13    bouyer 			sense->info[3],
    257  1.13    bouyer 			sense->extra_len);
    258  1.13    bouyer 		printf("extra: ");
    259  1.13    bouyer 		for (count = 0; count < ADD_BYTES_LIM(sense); count++)
    260  1.13    bouyer 			printf("0x%x ", sense->cmd_spec_info[count]);
    261  1.13    bouyer 		printf("\n");
    262  1.13    bouyer 	}
    263  1.13    bouyer #endif	/* SCSIDEBUG */
    264  1.13    bouyer 	/*
    265  1.13    bouyer 	 * If the device has it's own error handler, call it first.
    266  1.13    bouyer 	 * If it returns a legit error value, return that, otherwise
    267  1.13    bouyer 	 * it wants us to continue with normal error processing.
    268  1.13    bouyer 	 */
    269  1.13    bouyer 	if (sc_link->device->err_handler) {
    270  1.13    bouyer 		SC_DEBUG(sc_link, SDEV_DB2,
    271  1.13    bouyer 		    ("calling private err_handler()\n"));
    272  1.13    bouyer 		error = (*sc_link->device->err_handler)(xs);
    273  1.13    bouyer 		if (error != SCSIRET_CONTINUE)
    274  1.13    bouyer 			return (error);		/* error >= 0  better ? */
    275  1.13    bouyer 	}
    276  1.13    bouyer 	/* otherwise use the default */
    277  1.13    bouyer 	switch (sense->error_code & SSD_ERRCODE) {
    278  1.13    bouyer 		/*
    279  1.13    bouyer 		 * If it's code 70, use the extended stuff and
    280  1.13    bouyer 		 * interpret the key
    281  1.13    bouyer 		 */
    282  1.13    bouyer 	case 0x71:		/* delayed error */
    283  1.13    bouyer 		sc_link->sc_print_addr(sc_link);
    284  1.13    bouyer 		key = sense->flags & SSD_KEY;
    285  1.13    bouyer 		printf(" DEFERRED ERROR, key = 0x%x\n", key);
    286  1.13    bouyer 		/* FALLTHROUGH */
    287  1.13    bouyer 	case 0x70:
    288  1.13    bouyer 		if ((sense->error_code & SSD_ERRCODE_VALID) != 0)
    289  1.13    bouyer 			info = _4btol(sense->info);
    290  1.13    bouyer 		else
    291  1.13    bouyer 			info = 0;
    292  1.13    bouyer 		key = sense->flags & SSD_KEY;
    293  1.13    bouyer 
    294  1.13    bouyer 		switch (key) {
    295  1.13    bouyer 		case SKEY_NO_SENSE:
    296  1.13    bouyer 		case SKEY_RECOVERED_ERROR:
    297  1.13    bouyer 			if (xs->resid == xs->datalen && xs->datalen) {
    298  1.13    bouyer 				/*
    299  1.13    bouyer 				 * Why is this here?
    300  1.13    bouyer 				 */
    301  1.13    bouyer 				xs->resid = 0;	/* not short read */
    302  1.13    bouyer 			}
    303  1.13    bouyer 		case SKEY_EQUAL:
    304  1.13    bouyer 			error = 0;
    305  1.13    bouyer 			break;
    306  1.13    bouyer 		case SKEY_NOT_READY:
    307  1.13    bouyer 			if ((sc_link->flags & SDEV_REMOVABLE) != 0)
    308  1.13    bouyer 				sc_link->flags &= ~SDEV_MEDIA_LOADED;
    309  1.24   thorpej 			if ((xs->xs_control & XS_CTL_IGNORE_NOT_READY) != 0)
    310  1.13    bouyer 				return (0);
    311  1.19    bouyer 			if (sense->add_sense_code == 0x3A &&
    312  1.19    bouyer 			    sense->add_sense_code_qual == 0x00)
    313  1.19    bouyer 				error = ENODEV; /* Medium not present */
    314  1.19    bouyer 			else
    315  1.19    bouyer 				error = EIO;
    316  1.24   thorpej 			if ((xs->xs_control & XS_CTL_SILENT) != 0)
    317  1.19    bouyer 				return (error);
    318  1.13    bouyer 			break;
    319  1.13    bouyer 		case SKEY_ILLEGAL_REQUEST:
    320  1.24   thorpej 			if ((xs->xs_control &
    321  1.24   thorpej 			     XS_CTL_IGNORE_ILLEGAL_REQUEST) != 0)
    322  1.13    bouyer 				return (0);
    323  1.24   thorpej 			/*
    324  1.24   thorpej 			 * Handle the case where a device reports
    325  1.24   thorpej 			 * Logical Unit Not Supported during discovery.
    326  1.24   thorpej 			 */
    327  1.24   thorpej 			if ((xs->xs_control & XS_CTL_DISCOVERY) != 0 &&
    328  1.24   thorpej 			    sense->add_sense_code == 0x25 &&
    329  1.24   thorpej 			    sense->add_sense_code_qual == 0x00)
    330  1.24   thorpej 				return (EINVAL);
    331  1.24   thorpej 			if ((xs->xs_control & XS_CTL_SILENT) != 0)
    332  1.13    bouyer 				return (EIO);
    333  1.13    bouyer 			error = EINVAL;
    334  1.13    bouyer 			break;
    335  1.13    bouyer 		case SKEY_UNIT_ATTENTION:
    336  1.20    bouyer 			if (sense->add_sense_code == 0x29 &&
    337  1.20    bouyer 			    sense->add_sense_code_qual == 0x00)
    338  1.20    bouyer 				return (ERESTART); /* device or bus reset */
    339  1.13    bouyer 			if ((sc_link->flags & SDEV_REMOVABLE) != 0)
    340  1.13    bouyer 				sc_link->flags &= ~SDEV_MEDIA_LOADED;
    341  1.24   thorpej 			if ((xs->xs_control &
    342  1.24   thorpej 			     XS_CTL_IGNORE_MEDIA_CHANGE) != 0 ||
    343  1.13    bouyer 				/* XXX Should reupload any transient state. */
    344  1.13    bouyer 				(sc_link->flags & SDEV_REMOVABLE) == 0)
    345  1.13    bouyer 				return (ERESTART);
    346  1.24   thorpej 			if ((xs->xs_control & XS_CTL_SILENT) != 0)
    347  1.13    bouyer 				return (EIO);
    348  1.13    bouyer 			error = EIO;
    349  1.13    bouyer 			break;
    350  1.13    bouyer 		case SKEY_WRITE_PROTECT:
    351  1.13    bouyer 			error = EROFS;
    352  1.13    bouyer 			break;
    353  1.13    bouyer 		case SKEY_BLANK_CHECK:
    354  1.13    bouyer 			error = 0;
    355  1.13    bouyer 			break;
    356  1.13    bouyer 		case SKEY_ABORTED_COMMAND:
    357  1.13    bouyer 			error = ERESTART;
    358  1.13    bouyer 			break;
    359  1.13    bouyer 		case SKEY_VOLUME_OVERFLOW:
    360  1.13    bouyer 			error = ENOSPC;
    361  1.13    bouyer 			break;
    362  1.13    bouyer 		default:
    363  1.13    bouyer 			error = EIO;
    364  1.13    bouyer 			break;
    365  1.13    bouyer 		}
    366  1.13    bouyer 
    367  1.13    bouyer #ifdef SCSIVERBOSE
    368  1.32  augustss 		if (key && (xs->xs_control & XS_CTL_SILENT) == 0)
    369  1.13    bouyer 			scsipi_print_sense(xs, 0);
    370  1.13    bouyer #else
    371  1.13    bouyer 		if (key) {
    372  1.13    bouyer 			sc_link->sc_print_addr(sc_link);
    373  1.13    bouyer 			printf("%s", error_mes[key - 1]);
    374  1.13    bouyer 			if ((sense->error_code & SSD_ERRCODE_VALID) != 0) {
    375  1.13    bouyer 				switch (key) {
    376  1.13    bouyer 				case SKEY_NOT_READY:
    377  1.13    bouyer 				case SKEY_ILLEGAL_REQUEST:
    378  1.13    bouyer 				case SKEY_UNIT_ATTENTION:
    379  1.13    bouyer 				case SKEY_WRITE_PROTECT:
    380  1.13    bouyer 					break;
    381  1.13    bouyer 				case SKEY_BLANK_CHECK:
    382  1.13    bouyer 					printf(", requested size: %d (decimal)",
    383  1.13    bouyer 					    info);
    384  1.13    bouyer 					break;
    385  1.13    bouyer 				case SKEY_ABORTED_COMMAND:
    386  1.13    bouyer 					if (xs->retries)
    387  1.13    bouyer 						printf(", retrying");
    388  1.13    bouyer 					printf(", cmd 0x%x, info 0x%x",
    389  1.13    bouyer 					    xs->cmd->opcode, info);
    390  1.13    bouyer 					break;
    391  1.13    bouyer 				default:
    392  1.13    bouyer 					printf(", info = %d (decimal)", info);
    393  1.13    bouyer 				}
    394  1.13    bouyer 			}
    395  1.13    bouyer 			if (sense->extra_len != 0) {
    396  1.13    bouyer 				int n;
    397  1.13    bouyer 				printf(", data =");
    398  1.13    bouyer 				for (n = 0; n < sense->extra_len; n++)
    399  1.13    bouyer 					printf(" %02x",
    400  1.13    bouyer 					    sense->cmd_spec_info[n]);
    401  1.13    bouyer 			}
    402  1.13    bouyer 			printf("\n");
    403  1.13    bouyer 		}
    404  1.13    bouyer #endif
    405  1.13    bouyer 		return (error);
    406  1.13    bouyer 
    407  1.13    bouyer 	/*
    408  1.13    bouyer 	 * Not code 70, just report it
    409  1.13    bouyer 	 */
    410  1.13    bouyer 	default:
    411  1.28    mjacob #if	defined(SCSIDEBUG) || defined(DEBUG)
    412  1.28    mjacob 	{
    413  1.28    mjacob 		static char *uc = "undecodable sense error";
    414  1.28    mjacob 		int i;
    415  1.28    mjacob 		u_int8_t *cptr = (u_int8_t *) sense;
    416  1.28    mjacob 		sc_link->sc_print_addr(sc_link);
    417  1.28    mjacob 		if (xs->cmd == &xs->cmdstore) {
    418  1.28    mjacob 			printf("%s for opcode 0x%x, data=",
    419  1.28    mjacob 			    uc, xs->cmdstore.opcode);
    420  1.28    mjacob 		} else {
    421  1.28    mjacob 			printf("%s, data=", uc);
    422  1.28    mjacob 		}
    423  1.28    mjacob 		for (i = 0; i < sizeof (sense); i++)
    424  1.28    mjacob 			printf(" 0x%02x", *(cptr++) & 0xff);
    425  1.28    mjacob 		printf("\n");
    426  1.28    mjacob 	}
    427  1.28    mjacob #else
    428  1.13    bouyer 		sc_link->sc_print_addr(sc_link);
    429  1.17    mjacob 		printf("Sense Error Code 0x%x",
    430  1.17    mjacob 			sense->error_code & SSD_ERRCODE);
    431  1.13    bouyer 		if ((sense->error_code & SSD_ERRCODE_VALID) != 0) {
    432  1.13    bouyer 			struct scsipi_sense_data_unextended *usense =
    433  1.13    bouyer 			    (struct scsipi_sense_data_unextended *)sense;
    434  1.13    bouyer 			printf(" at block no. %d (decimal)",
    435  1.13    bouyer 			    _3btol(usense->block));
    436  1.13    bouyer 		}
    437  1.13    bouyer 		printf("\n");
    438  1.28    mjacob #endif
    439  1.13    bouyer 		return (EIO);
    440  1.13    bouyer 	}
    441  1.13    bouyer }
    442  1.13    bouyer 
    443  1.13    bouyer /*
    444   1.2    bouyer  * Find out from the device what its capacity is.
    445   1.2    bouyer  */
    446   1.2    bouyer u_long
    447   1.2    bouyer scsipi_size(sc_link, flags)
    448   1.2    bouyer 	struct scsipi_link *sc_link;
    449   1.2    bouyer 	int flags;
    450   1.2    bouyer {
    451   1.2    bouyer 	struct scsipi_read_cap_data rdcap;
    452   1.2    bouyer 	struct scsipi_read_capacity scsipi_cmd;
    453   1.2    bouyer 
    454   1.2    bouyer 	/*
    455   1.2    bouyer 	 * make up a scsipi command and ask the scsipi driver to do
    456   1.2    bouyer 	 * it for you.
    457   1.2    bouyer 	 */
    458   1.2    bouyer 	bzero(&scsipi_cmd, sizeof(scsipi_cmd));
    459   1.2    bouyer 	scsipi_cmd.opcode = READ_CAPACITY;
    460   1.2    bouyer 
    461   1.2    bouyer 	/*
    462   1.2    bouyer 	 * If the command works, interpret the result as a 4 byte
    463   1.2    bouyer 	 * number of blocks
    464   1.2    bouyer 	 */
    465   1.4   thorpej 	if (scsipi_command(sc_link, (struct scsipi_generic *)&scsipi_cmd,
    466   1.3     enami 	    sizeof(scsipi_cmd), (u_char *)&rdcap, sizeof(rdcap),
    467  1.29    bouyer 	    SCSIPIRETRIES, 20000, NULL, flags | XS_CTL_DATA_IN) != 0) {
    468   1.2    bouyer 		sc_link->sc_print_addr(sc_link);
    469   1.2    bouyer 		printf("could not get size\n");
    470   1.3     enami 		return (0);
    471   1.2    bouyer 	}
    472   1.2    bouyer 
    473   1.3     enami 	return (_4btol(rdcap.addr) + 1);
    474   1.2    bouyer }
    475   1.2    bouyer 
    476   1.2    bouyer /*
    477   1.2    bouyer  * Get scsipi driver to send a "are you ready?" command
    478   1.2    bouyer  */
    479   1.3     enami int
    480   1.2    bouyer scsipi_test_unit_ready(sc_link, flags)
    481   1.2    bouyer 	struct scsipi_link *sc_link;
    482   1.2    bouyer 	int flags;
    483   1.2    bouyer {
    484   1.2    bouyer 	struct scsipi_test_unit_ready scsipi_cmd;
    485   1.2    bouyer 
    486   1.2    bouyer 	/* some ATAPI drives don't support TEST_UNIT_READY. Sigh */
    487   1.2    bouyer 	if (sc_link->quirks & ADEV_NOTUR)
    488   1.3     enami 		return (0);
    489   1.2    bouyer 
    490   1.2    bouyer 	bzero(&scsipi_cmd, sizeof(scsipi_cmd));
    491   1.2    bouyer 	scsipi_cmd.opcode = TEST_UNIT_READY;
    492   1.2    bouyer 
    493   1.4   thorpej 	return (scsipi_command(sc_link,
    494   1.3     enami 	    (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
    495  1.29    bouyer 	    0, 0, SCSIPIRETRIES, 10000, NULL, flags));
    496   1.2    bouyer }
    497   1.2    bouyer 
    498   1.2    bouyer /*
    499   1.2    bouyer  * Do a scsipi operation asking a device what it is
    500   1.2    bouyer  * Use the scsipi_cmd routine in the switch table.
    501   1.2    bouyer  * XXX actually this is only used for scsi devices, because I have the feeling
    502   1.2    bouyer  * that some atapi CDROM may not implement it, althouh it marked as mandatory
    503   1.2    bouyer  * in the atapi specs.
    504   1.2    bouyer  */
    505   1.3     enami int
    506   1.2    bouyer scsipi_inquire(sc_link, inqbuf, flags)
    507   1.2    bouyer 	struct scsipi_link *sc_link;
    508   1.2    bouyer 	struct scsipi_inquiry_data *inqbuf;
    509   1.2    bouyer 	int flags;
    510   1.2    bouyer {
    511   1.2    bouyer 	struct scsipi_inquiry scsipi_cmd;
    512   1.2    bouyer 
    513   1.2    bouyer 	bzero(&scsipi_cmd, sizeof(scsipi_cmd));
    514   1.2    bouyer 	scsipi_cmd.opcode = INQUIRY;
    515   1.2    bouyer 	scsipi_cmd.length = sizeof(struct scsipi_inquiry_data);
    516   1.2    bouyer 
    517   1.4   thorpej 	return (scsipi_command(sc_link,
    518   1.3     enami 	    (struct scsipi_generic *) &scsipi_cmd, sizeof(scsipi_cmd),
    519   1.3     enami 	    (u_char *) inqbuf, sizeof(struct scsipi_inquiry_data),
    520  1.29    bouyer 	    SCSIPIRETRIES, 10000, NULL, XS_CTL_DATA_IN | flags));
    521   1.2    bouyer }
    522   1.2    bouyer 
    523   1.2    bouyer /*
    524   1.2    bouyer  * Prevent or allow the user to remove the media
    525   1.2    bouyer  */
    526   1.3     enami int
    527   1.2    bouyer scsipi_prevent(sc_link, type, flags)
    528   1.2    bouyer 	struct scsipi_link *sc_link;
    529   1.2    bouyer 	int type, flags;
    530   1.2    bouyer {
    531   1.2    bouyer 	struct scsipi_prevent scsipi_cmd;
    532   1.2    bouyer 
    533   1.2    bouyer 	if (sc_link->quirks & ADEV_NODOORLOCK)
    534   1.3     enami 		return (0);
    535   1.2    bouyer 
    536   1.2    bouyer 	bzero(&scsipi_cmd, sizeof(scsipi_cmd));
    537   1.2    bouyer 	scsipi_cmd.opcode = PREVENT_ALLOW;
    538   1.2    bouyer 	scsipi_cmd.how = type;
    539   1.4   thorpej 	return (scsipi_command(sc_link,
    540   1.3     enami 	    (struct scsipi_generic *) &scsipi_cmd, sizeof(scsipi_cmd),
    541  1.29    bouyer 	    0, 0, SCSIPIRETRIES, 5000, NULL, flags));
    542   1.2    bouyer }
    543   1.2    bouyer 
    544   1.2    bouyer /*
    545   1.2    bouyer  * Get scsipi driver to send a "start up" command
    546   1.2    bouyer  */
    547   1.3     enami int
    548   1.2    bouyer scsipi_start(sc_link, type, flags)
    549   1.2    bouyer 	struct scsipi_link *sc_link;
    550   1.2    bouyer 	int type, flags;
    551   1.2    bouyer {
    552   1.2    bouyer 	struct scsipi_start_stop scsipi_cmd;
    553  1.18    bouyer 
    554  1.18    bouyer 	if (sc_link->quirks & SDEV_NOSTARTUNIT)
    555  1.18    bouyer 		return 0;
    556   1.2    bouyer 
    557   1.2    bouyer 	bzero(&scsipi_cmd, sizeof(scsipi_cmd));
    558   1.2    bouyer 	scsipi_cmd.opcode = START_STOP;
    559   1.2    bouyer 	scsipi_cmd.byte2 = 0x00;
    560   1.2    bouyer 	scsipi_cmd.how = type;
    561   1.4   thorpej 	return (scsipi_command(sc_link,
    562   1.3     enami 	    (struct scsipi_generic *) &scsipi_cmd, sizeof(scsipi_cmd),
    563  1.29    bouyer 	    0, 0, SCSIPIRETRIES, (type & SSS_START) ? 60000 : 10000,
    564  1.29    bouyer 	    NULL, flags));
    565   1.2    bouyer }
    566   1.2    bouyer 
    567   1.2    bouyer /*
    568   1.3     enami  * This routine is called by the scsipi interrupt when the transfer is
    569   1.3     enami  * complete.
    570   1.2    bouyer  */
    571   1.3     enami void
    572   1.2    bouyer scsipi_done(xs)
    573   1.2    bouyer 	struct scsipi_xfer *xs;
    574   1.2    bouyer {
    575   1.2    bouyer 	struct scsipi_link *sc_link = xs->sc_link;
    576   1.2    bouyer 	struct buf *bp;
    577  1.31     enami 	int error, s;
    578   1.2    bouyer 
    579   1.2    bouyer 	SC_DEBUG(sc_link, SDEV_DB2, ("scsipi_done\n"));
    580   1.2    bouyer #ifdef	SCSIDEBUG
    581   1.2    bouyer 	if ((sc_link->flags & SDEV_DB1) != 0)
    582   1.2    bouyer 		show_scsipi_cmd(xs);
    583   1.2    bouyer #endif /* SCSIDEBUG */
    584   1.2    bouyer 
    585   1.2    bouyer 	/*
    586   1.3     enami 	 * If it's a user level request, bypass all usual completion
    587   1.3     enami 	 * processing, let the user work it out..  We take
    588   1.3     enami 	 * reponsibility for freeing the xs when the user returns.
    589   1.3     enami 	 * (and restarting the device's queue).
    590   1.3     enami 	 */
    591  1.24   thorpej 	if ((xs->xs_control & XS_CTL_USERCMD) != 0) {
    592   1.2    bouyer 		SC_DEBUG(sc_link, SDEV_DB3, ("calling user done()\n"));
    593   1.2    bouyer 		scsipi_user_done(xs); /* to take a copy of the sense etc. */
    594   1.2    bouyer 		SC_DEBUG(sc_link, SDEV_DB3, ("returned from user done()\n "));
    595   1.2    bouyer 
    596   1.9    scottr 		/*
    597   1.9    scottr 		 * If this was an asynchronous operation (i.e. adapter
    598   1.9    scottr 		 * returned SUCCESSFULLY_QUEUED when the command was
    599   1.9    scottr 		 * submitted), we need to free the scsipi_xfer here.
    600   1.9    scottr 		 */
    601  1.31     enami 		if (xs->xs_control & XS_CTL_ASYNC) {
    602  1.31     enami 			s = splbio();
    603  1.24   thorpej 			scsipi_free_xs(xs, XS_CTL_NOSLEEP);
    604  1.31     enami 			splx(s);
    605  1.31     enami 		}
    606   1.2    bouyer 		SC_DEBUG(sc_link, SDEV_DB3, ("returning to adapter\n"));
    607   1.2    bouyer 		return;
    608   1.2    bouyer 	}
    609   1.2    bouyer 
    610  1.24   thorpej 	if ((xs->xs_control & XS_CTL_ASYNC) == 0) {
    611   1.2    bouyer 		/*
    612   1.2    bouyer 		 * if it's a normal upper level request, then ask
    613   1.2    bouyer 		 * the upper level code to handle error checking
    614   1.2    bouyer 		 * rather than doing it here at interrupt time
    615   1.2    bouyer 		 */
    616   1.2    bouyer 		wakeup(xs);
    617   1.2    bouyer 		return;
    618   1.2    bouyer 	}
    619   1.2    bouyer 
    620   1.2    bouyer 	/*
    621   1.2    bouyer 	 * Go and handle errors now.
    622   1.2    bouyer 	 * If it returns ERESTART then we should RETRY
    623   1.2    bouyer 	 */
    624   1.2    bouyer retry:
    625   1.2    bouyer 	error = sc_err1(xs, 1);
    626  1.20    bouyer 	if (error == ERESTART) {
    627   1.4   thorpej 		switch (scsipi_command_direct(xs)) {
    628   1.2    bouyer 		case SUCCESSFULLY_QUEUED:
    629   1.2    bouyer 			return;
    630   1.2    bouyer 
    631   1.2    bouyer 		case TRY_AGAIN_LATER:
    632   1.2    bouyer 			xs->error = XS_BUSY;
    633   1.2    bouyer 		case COMPLETE:
    634   1.2    bouyer 			goto retry;
    635   1.2    bouyer 		}
    636  1.20    bouyer 	}
    637   1.2    bouyer 
    638   1.2    bouyer 	bp = xs->bp;
    639   1.2    bouyer 	if (bp) {
    640   1.2    bouyer 		if (error) {
    641   1.2    bouyer 			bp->b_error = error;
    642   1.2    bouyer 			bp->b_flags |= B_ERROR;
    643   1.2    bouyer 			bp->b_resid = bp->b_bcount;
    644   1.2    bouyer 		} else {
    645   1.2    bouyer 			bp->b_error = 0;
    646   1.2    bouyer 			bp->b_resid = xs->resid;
    647   1.2    bouyer 		}
    648   1.2    bouyer 	}
    649   1.2    bouyer 	if (sc_link->device->done) {
    650   1.2    bouyer 		/*
    651   1.2    bouyer 		 * Tell the device the operation is actually complete.
    652   1.2    bouyer 		 * No more will happen with this xfer.  This for
    653   1.2    bouyer 		 * notification of the upper-level driver only; they
    654   1.2    bouyer 		 * won't be returning any meaningful information to us.
    655   1.2    bouyer 		 */
    656   1.2    bouyer 		(*sc_link->device->done)(xs);
    657   1.2    bouyer 	}
    658   1.9    scottr 	/*
    659   1.9    scottr 	 * If this was an asynchronous operation (i.e. adapter
    660   1.9    scottr 	 * returned SUCCESSFULLY_QUEUED when the command was
    661   1.9    scottr 	 * submitted), we need to free the scsipi_xfer here.
    662   1.9    scottr 	 */
    663  1.24   thorpej 	if (xs->xs_control & XS_CTL_ASYNC) {
    664  1.31     enami 		s = splbio();
    665  1.24   thorpej 		scsipi_free_xs(xs, XS_CTL_NOSLEEP);
    666  1.22        pk 		splx(s);
    667  1.22        pk 	}
    668   1.2    bouyer 	if (bp)
    669   1.2    bouyer 		biodone(bp);
    670   1.2    bouyer }
    671   1.2    bouyer 
    672   1.2    bouyer int
    673   1.2    bouyer scsipi_execute_xs(xs)
    674   1.2    bouyer 	struct scsipi_xfer *xs;
    675   1.2    bouyer {
    676  1.11    scottr 	int async;
    677   1.2    bouyer 	int error;
    678   1.2    bouyer 	int s;
    679   1.2    bouyer 
    680  1.24   thorpej 	xs->xs_status &= ~XS_STS_DONE;
    681   1.2    bouyer 	xs->error = XS_NOERROR;
    682   1.2    bouyer 	xs->resid = xs->datalen;
    683   1.5   thorpej 	xs->status = 0;
    684   1.2    bouyer 
    685   1.2    bouyer retry:
    686   1.2    bouyer 	/*
    687   1.2    bouyer 	 * Do the transfer. If we are polling we will return:
    688   1.2    bouyer 	 * COMPLETE,  Was poll, and scsipi_done has been called
    689   1.2    bouyer 	 * TRY_AGAIN_LATER, Adapter short resources, try again
    690   1.3     enami 	 *
    691   1.2    bouyer 	 * if under full steam (interrupts) it will return:
    692   1.2    bouyer 	 * SUCCESSFULLY_QUEUED, will do a wakeup when complete
    693   1.2    bouyer 	 * TRY_AGAIN_LATER, (as for polling)
    694   1.2    bouyer 	 * After the wakeup, we must still check if it succeeded
    695   1.3     enami 	 *
    696  1.24   thorpej 	 * If we have a XS_CTL_ASYNC (typically because we have a buf)
    697   1.2    bouyer 	 * we just return.  All the error proccessing and the buffer
    698   1.2    bouyer 	 * code both expect us to return straight to them, so as soon
    699   1.2    bouyer 	 * as the command is queued, return.
    700   1.2    bouyer 	 */
    701   1.2    bouyer #ifdef SCSIDEBUG
    702   1.2    bouyer 	if (xs->sc_link->flags & SDEV_DB3) {
    703   1.2    bouyer 		printf("scsipi_exec_cmd: ");
    704   1.2    bouyer 		show_scsipi_xs(xs);
    705   1.2    bouyer 		printf("\n");
    706   1.2    bouyer 	}
    707   1.2    bouyer #endif
    708  1.24   thorpej 	async = (xs->xs_control & XS_CTL_ASYNC);
    709   1.4   thorpej 	switch (scsipi_command_direct(xs)) {
    710   1.2    bouyer 	case SUCCESSFULLY_QUEUED:
    711  1.11    scottr 		if (async) {
    712  1.11    scottr 			/* scsipi_done() will free the scsipi_xfer. */
    713   1.3     enami 			return (EJUSTRETURN);
    714   1.9    scottr 		}
    715   1.2    bouyer #ifdef DIAGNOSTIC
    716  1.24   thorpej 		if (xs->xs_control & XS_CTL_ASYNC)
    717  1.24   thorpej 			panic("scsipi_execute_xs: ASYNC and POLL");
    718   1.2    bouyer #endif
    719  1.11    scottr 		s = splbio();
    720  1.24   thorpej 		while ((xs->xs_status & XS_STS_DONE) == 0)
    721   1.2    bouyer 			tsleep(xs, PRIBIO + 1, "scsipi_cmd", 0);
    722   1.2    bouyer 		splx(s);
    723   1.2    bouyer 	case COMPLETE:		/* Polling command completed ok */
    724   1.2    bouyer 		if (xs->bp)
    725   1.9    scottr 			return (0);
    726   1.2    bouyer 	doit:
    727   1.2    bouyer 		SC_DEBUG(xs->sc_link, SDEV_DB3, ("back in cmd()\n"));
    728   1.2    bouyer 		if ((error = sc_err1(xs, 0)) != ERESTART)
    729   1.3     enami 			return (error);
    730   1.2    bouyer 		goto retry;
    731   1.2    bouyer 
    732   1.2    bouyer 	case TRY_AGAIN_LATER:	/* adapter resource shortage */
    733   1.2    bouyer 		xs->error = XS_BUSY;
    734   1.2    bouyer 		goto doit;
    735   1.2    bouyer 
    736   1.2    bouyer 	default:
    737   1.2    bouyer 		panic("scsipi_execute_xs: invalid return code");
    738   1.2    bouyer 	}
    739   1.2    bouyer 
    740   1.2    bouyer #ifdef DIAGNOSTIC
    741   1.2    bouyer 	panic("scsipi_execute_xs: impossible");
    742   1.2    bouyer #endif
    743   1.3     enami 	return (EINVAL);
    744   1.2    bouyer }
    745   1.2    bouyer 
    746   1.3     enami int
    747   1.2    bouyer sc_err1(xs, async)
    748   1.2    bouyer 	struct scsipi_xfer *xs;
    749   1.2    bouyer 	int async;
    750   1.2    bouyer {
    751   1.2    bouyer 	int error;
    752   1.2    bouyer 
    753   1.2    bouyer 	SC_DEBUG(xs->sc_link, SDEV_DB3, ("sc_err1,err = 0x%x \n", xs->error));
    754   1.2    bouyer 
    755   1.2    bouyer 	/*
    756   1.2    bouyer 	 * If it has a buf, we might be working with
    757   1.2    bouyer 	 * a request from the buffer cache or some other
    758   1.2    bouyer 	 * piece of code that requires us to process
    759   1.2    bouyer 	 * errors at inetrrupt time. We have probably
    760   1.2    bouyer 	 * been called by scsipi_done()
    761   1.2    bouyer 	 */
    762   1.2    bouyer 	switch (xs->error) {
    763   1.2    bouyer 	case XS_NOERROR:	/* nearly always hit this one */
    764   1.2    bouyer 		error = 0;
    765   1.2    bouyer 		break;
    766   1.2    bouyer 
    767   1.2    bouyer 	case XS_SENSE:
    768  1.13    bouyer 	case XS_SHORTSENSE:
    769   1.3     enami 		if ((error = (*xs->sc_link->scsipi_interpret_sense)(xs)) ==
    770   1.3     enami 		    ERESTART)
    771   1.2    bouyer 			goto retry;
    772   1.2    bouyer 		SC_DEBUG(xs->sc_link, SDEV_DB3,
    773   1.2    bouyer 		    ("scsipi_interpret_sense returned %d\n", error));
    774   1.2    bouyer 		break;
    775   1.2    bouyer 
    776   1.2    bouyer 	case XS_BUSY:
    777   1.2    bouyer 		if (xs->retries) {
    778  1.24   thorpej 			if ((xs->xs_control & XS_CTL_POLL) != 0)
    779   1.2    bouyer 				delay(1000000);
    780  1.36      fvdl 			else if (!async && (xs->xs_control &
    781  1.33     enami 			    (XS_CTL_NOSLEEP|XS_CTL_DISCOVERY)) == 0)
    782   1.2    bouyer 				tsleep(&lbolt, PRIBIO, "scbusy", 0);
    783   1.2    bouyer 			else
    784   1.2    bouyer #if 0
    785   1.2    bouyer 				timeout(scsipi_requeue, xs, hz);
    786   1.2    bouyer #else
    787  1.36      fvdl 				goto retry;
    788   1.2    bouyer #endif
    789   1.2    bouyer 		}
    790   1.2    bouyer 	case XS_TIMEOUT:
    791   1.2    bouyer 	retry:
    792  1.12   thorpej 		if (xs->retries) {
    793  1.12   thorpej 			xs->retries--;
    794   1.2    bouyer 			xs->error = XS_NOERROR;
    795  1.24   thorpej 			xs->xs_status &= ~XS_STS_DONE;
    796   1.3     enami 			return (ERESTART);
    797   1.2    bouyer 		}
    798   1.2    bouyer 	case XS_DRIVER_STUFFUP:
    799   1.2    bouyer 		error = EIO;
    800   1.2    bouyer 		break;
    801   1.2    bouyer 
    802   1.2    bouyer 	case XS_SELTIMEOUT:
    803   1.2    bouyer 		/* XXX Disable device? */
    804  1.12   thorpej 		error = EIO;
    805  1.12   thorpej 		break;
    806  1.12   thorpej 
    807  1.12   thorpej 	case XS_RESET:
    808  1.12   thorpej 		if (xs->retries) {
    809  1.12   thorpej 			SC_DEBUG(xs->sc_link, SDEV_DB3,
    810  1.12   thorpej 			    ("restarting command destroyed by reset\n"));
    811  1.12   thorpej 			goto retry;
    812  1.12   thorpej 		}
    813   1.2    bouyer 		error = EIO;
    814   1.2    bouyer 		break;
    815   1.2    bouyer 
    816   1.2    bouyer 	default:
    817   1.3     enami 		(*xs->sc_link->sc_print_addr)(xs->sc_link);
    818   1.2    bouyer 		printf("unknown error category from scsipi driver\n");
    819   1.2    bouyer 		error = EIO;
    820   1.2    bouyer 		break;
    821   1.2    bouyer 	}
    822   1.2    bouyer 
    823   1.3     enami 	return (error);
    824   1.2    bouyer }
    825   1.2    bouyer 
    826  1.14   thorpej /*
    827  1.14   thorpej  * Add a reference to the adapter pointed to by the provided
    828  1.14   thorpej  * link, enabling the adapter if necessary.
    829  1.14   thorpej  */
    830  1.14   thorpej int
    831  1.14   thorpej scsipi_adapter_addref(link)
    832  1.14   thorpej 	struct scsipi_link *link;
    833  1.14   thorpej {
    834  1.14   thorpej 	struct scsipi_adapter *adapter = link->adapter;
    835  1.14   thorpej 	int s, error = 0;
    836  1.14   thorpej 
    837  1.14   thorpej 	s = splbio();
    838  1.14   thorpej 	if (adapter->scsipi_refcnt++ == 0 &&
    839  1.14   thorpej 	    adapter->scsipi_enable != NULL) {
    840  1.14   thorpej 		error = (*adapter->scsipi_enable)(link->adapter_softc, 1);
    841  1.14   thorpej 		if (error)
    842  1.14   thorpej 			adapter->scsipi_refcnt--;
    843  1.14   thorpej 	}
    844  1.14   thorpej 	splx(s);
    845  1.14   thorpej 	return (error);
    846  1.14   thorpej }
    847  1.14   thorpej 
    848  1.14   thorpej /*
    849  1.14   thorpej  * Delete a reference to the adapter pointed to by the provided
    850  1.14   thorpej  * link, disabling the adapter if possible.
    851  1.14   thorpej  */
    852  1.14   thorpej void
    853  1.14   thorpej scsipi_adapter_delref(link)
    854  1.14   thorpej 	struct scsipi_link *link;
    855  1.14   thorpej {
    856  1.14   thorpej 	struct scsipi_adapter *adapter = link->adapter;
    857  1.14   thorpej 	int s;
    858  1.14   thorpej 
    859  1.14   thorpej 	s = splbio();
    860  1.14   thorpej 	if (adapter->scsipi_refcnt-- == 1 &&
    861  1.14   thorpej 	    adapter->scsipi_enable != NULL)
    862  1.14   thorpej 		(void) (*adapter->scsipi_enable)(link->adapter_softc, 0);
    863  1.14   thorpej 	splx(s);
    864  1.14   thorpej }
    865  1.14   thorpej 
    866   1.2    bouyer #ifdef	SCSIDEBUG
    867   1.2    bouyer /*
    868   1.2    bouyer  * Given a scsipi_xfer, dump the request, in all it's glory
    869   1.2    bouyer  */
    870   1.2    bouyer void
    871   1.2    bouyer show_scsipi_xs(xs)
    872   1.2    bouyer 	struct scsipi_xfer *xs;
    873   1.2    bouyer {
    874   1.3     enami 
    875   1.2    bouyer 	printf("xs(%p): ", xs);
    876  1.24   thorpej 	printf("xs_control(0x%08x)", xs->xs_control);
    877  1.24   thorpej 	printf("xs_status(0x%08x)", xs->xs_status);
    878   1.2    bouyer 	printf("sc_link(%p)", xs->sc_link);
    879   1.2    bouyer 	printf("retr(0x%x)", xs->retries);
    880   1.2    bouyer 	printf("timo(0x%x)", xs->timeout);
    881   1.2    bouyer 	printf("cmd(%p)", xs->cmd);
    882   1.2    bouyer 	printf("len(0x%x)", xs->cmdlen);
    883   1.2    bouyer 	printf("data(%p)", xs->data);
    884   1.2    bouyer 	printf("len(0x%x)", xs->datalen);
    885   1.2    bouyer 	printf("res(0x%x)", xs->resid);
    886   1.2    bouyer 	printf("err(0x%x)", xs->error);
    887   1.2    bouyer 	printf("bp(%p)", xs->bp);
    888   1.2    bouyer 	show_scsipi_cmd(xs);
    889   1.2    bouyer }
    890   1.2    bouyer 
    891   1.2    bouyer void
    892   1.2    bouyer show_scsipi_cmd(xs)
    893   1.2    bouyer 	struct scsipi_xfer *xs;
    894   1.2    bouyer {
    895   1.2    bouyer 	u_char *b = (u_char *) xs->cmd;
    896   1.3     enami 	int i = 0;
    897   1.2    bouyer 
    898   1.3     enami 	(*xs->sc_link->sc_print_addr)(xs->sc_link);
    899   1.2    bouyer 	printf("command: ");
    900   1.2    bouyer 
    901  1.24   thorpej 	if ((xs->xs_control & XS_CTL_RESET) == 0) {
    902   1.2    bouyer 		while (i < xs->cmdlen) {
    903   1.2    bouyer 			if (i)
    904   1.2    bouyer 				printf(",");
    905   1.2    bouyer 			printf("0x%x", b[i++]);
    906   1.2    bouyer 		}
    907   1.2    bouyer 		printf("-[%d bytes]\n", xs->datalen);
    908   1.2    bouyer 		if (xs->datalen)
    909   1.2    bouyer 			show_mem(xs->data, min(64, xs->datalen));
    910   1.2    bouyer 	} else
    911   1.2    bouyer 		printf("-RESET-\n");
    912   1.2    bouyer }
    913   1.2    bouyer 
    914   1.2    bouyer void
    915   1.2    bouyer show_mem(address, num)
    916   1.2    bouyer 	u_char *address;
    917   1.2    bouyer 	int num;
    918   1.2    bouyer {
    919   1.2    bouyer 	int x;
    920   1.2    bouyer 
    921   1.2    bouyer 	printf("------------------------------");
    922   1.2    bouyer 	for (x = 0; x < num; x++) {
    923   1.2    bouyer 		if ((x % 16) == 0)
    924   1.2    bouyer 			printf("\n%03d: ", x);
    925   1.2    bouyer 		printf("%02x ", *address++);
    926   1.2    bouyer 	}
    927   1.2    bouyer 	printf("\n------------------------------\n");
    928   1.2    bouyer }
    929   1.2    bouyer #endif /*SCSIDEBUG */
    930