Home | History | Annotate | Line # | Download | only in scsipi
scsi_base.c revision 1.91.8.1
      1  1.91.8.1       snj /*	$NetBSD: scsi_base.c,v 1.91.8.1 2017/06/21 18:18:55 snj Exp $	*/
      2      1.14       cgd 
      3      1.65   mycroft /*-
      4      1.82   mycroft  * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
      5      1.65   mycroft  * All rights reserved.
      6      1.65   mycroft  *
      7      1.65   mycroft  * This code is derived from software contributed to The NetBSD Foundation
      8      1.65   mycroft  * by Charles M. Hannum.
      9       1.9   mycroft  *
     10       1.9   mycroft  * Redistribution and use in source and binary forms, with or without
     11       1.9   mycroft  * modification, are permitted provided that the following conditions
     12       1.9   mycroft  * are met:
     13       1.9   mycroft  * 1. Redistributions of source code must retain the above copyright
     14       1.9   mycroft  *    notice, this list of conditions and the following disclaimer.
     15       1.9   mycroft  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.9   mycroft  *    notice, this list of conditions and the following disclaimer in the
     17       1.9   mycroft  *    documentation and/or other materials provided with the distribution.
     18       1.9   mycroft  *
     19      1.65   mycroft  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20      1.65   mycroft  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21      1.65   mycroft  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22      1.65   mycroft  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23      1.65   mycroft  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24      1.65   mycroft  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25      1.65   mycroft  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26      1.65   mycroft  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27      1.65   mycroft  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28      1.65   mycroft  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29      1.65   mycroft  * POSSIBILITY OF SUCH DAMAGE.
     30       1.1   mycroft  */
     31      1.76     lukem 
     32      1.76     lukem #include <sys/cdefs.h>
     33  1.91.8.1       snj __KERNEL_RCSID(0, "$NetBSD: scsi_base.c,v 1.91.8.1 2017/06/21 18:18:55 snj Exp $");
     34      1.49     enami 
     35       1.1   mycroft #include <sys/param.h>
     36      1.30   thorpej #include <sys/systm.h>
     37      1.11   mycroft #include <sys/kernel.h>
     38       1.1   mycroft #include <sys/buf.h>
     39       1.1   mycroft #include <sys/uio.h>
     40       1.1   mycroft #include <sys/malloc.h>
     41       1.1   mycroft #include <sys/errno.h>
     42       1.1   mycroft #include <sys/device.h>
     43      1.33  christos #include <sys/proc.h>
     44       1.2   mycroft 
     45      1.47    bouyer #include <dev/scsipi/scsipi_all.h>
     46      1.47    bouyer #include <dev/scsipi/scsi_all.h>
     47      1.47    bouyer #include <dev/scsipi/scsi_disk.h>
     48      1.47    bouyer #include <dev/scsipi/scsiconf.h>
     49      1.47    bouyer #include <dev/scsipi/scsipi_base.h>
     50      1.47    bouyer 
     51      1.90    bouyer static void scsi_print_xfer_mode(struct scsipi_periph *);
     52       1.1   mycroft /*
     53       1.1   mycroft  * Do a scsi operation, asking a device to run as SCSI-II if it can.
     54       1.1   mycroft  */
     55      1.50     enami int
     56      1.79   thorpej scsi_change_def(struct scsipi_periph *periph, int flags)
     57       1.1   mycroft {
     58      1.84   mycroft 	struct scsi_changedef cmd;
     59       1.1   mycroft 
     60      1.84   mycroft 	memset(&cmd, 0, sizeof(cmd));
     61      1.84   mycroft 	cmd.opcode = SCSI_CHANGE_DEFINITION;
     62      1.84   mycroft 	cmd.how = SC_SCSI_2;
     63      1.84   mycroft 
     64      1.84   mycroft 	return (scsipi_command(periph, (void *)&cmd, sizeof(cmd), 0, 0,
     65      1.84   mycroft 	    SCSIPIRETRIES, 100000, NULL, flags));
     66      1.22   mycroft }
     67      1.22   mycroft 
     68      1.22   mycroft /*
     69      1.22   mycroft  * ask the scsi driver to perform a command for us.
     70      1.22   mycroft  * tell it where to read/write the data, and how
     71      1.22   mycroft  * long the data is supposed to be. If we have  a buf
     72      1.22   mycroft  * to associate with the transfer, we need that too.
     73      1.22   mycroft  */
     74      1.82   mycroft void
     75      1.82   mycroft scsi_scsipi_cmd(struct scsipi_xfer *xs)
     76      1.22   mycroft {
     77      1.82   mycroft 	struct scsipi_periph *periph = xs->xs_periph;
     78      1.22   mycroft 
     79      1.74    bouyer 	SC_DEBUG(periph, SCSIPI_DB2, ("scsi_scsipi_cmd\n"));
     80      1.22   mycroft 
     81      1.58       cgd 	/*
     82      1.58       cgd 	 * Set the LUN in the CDB if we have an older device.  We also
     83      1.74    bouyer 	 * set it for more modern SCSI-2 devices "just in case".
     84      1.58       cgd 	 */
     85      1.74    bouyer 	if (periph->periph_version <= 2)
     86      1.58       cgd 		xs->cmd->bytes[0] |=
     87      1.74    bouyer 		    ((periph->periph_lun << SCSI_CMD_LUN_SHIFT) &
     88      1.58       cgd 			SCSI_CMD_LUN_MASK);
     89       1.1   mycroft }
     90       1.1   mycroft 
     91       1.1   mycroft /*
     92       1.1   mycroft  * Utility routines often used in SCSI stuff
     93       1.1   mycroft  */
     94       1.1   mycroft 
     95       1.1   mycroft /*
     96      1.74    bouyer  * Print out the periph's address info.
     97       1.1   mycroft  */
     98       1.1   mycroft void
     99      1.79   thorpej scsi_print_addr(struct scsipi_periph *periph)
    100       1.1   mycroft {
    101      1.74    bouyer 	struct scsipi_channel *chan = periph->periph_channel;
    102      1.74    bouyer 	struct scsipi_adapter *adapt = chan->chan_adapter;
    103       1.1   mycroft 
    104      1.74    bouyer 	printf("%s(%s:%d:%d:%d): ", periph->periph_dev != NULL ?
    105      1.88    cegger 	    device_xname(periph->periph_dev) : "probe",
    106      1.88    cegger 	    device_xname(adapt->adapt_dev),
    107      1.74    bouyer 	    chan->chan_channel, periph->periph_target,
    108      1.74    bouyer 	    periph->periph_lun);
    109      1.70     enami }
    110      1.70     enami 
    111      1.70     enami /*
    112      1.74    bouyer  * Kill off all pending xfers for a periph.
    113      1.70     enami  *
    114      1.91   mlelstv  * Must be called with channel lock held
    115      1.70     enami  */
    116      1.70     enami void
    117      1.87  christos scsi_kill_pending(struct scsipi_periph *periph)
    118      1.70     enami {
    119  1.91.8.1       snj 	struct scsipi_xfer *xs;
    120  1.91.8.1       snj 
    121  1.91.8.1       snj 	TAILQ_FOREACH(xs, &periph->periph_xferq, device_q) {
    122  1.91.8.1       snj 		callout_stop(&xs->xs_callout);
    123  1.91.8.1       snj 		scsi_print_addr(periph);
    124  1.91.8.1       snj 		printf("killed ");
    125  1.91.8.1       snj 		scsipi_print_cdb(xs->cmd);
    126  1.91.8.1       snj 		xs->error = XS_DRIVER_STUFFUP;
    127  1.91.8.1       snj 		scsipi_done(xs);
    128  1.91.8.1       snj 	}
    129       1.1   mycroft }
    130      1.90    bouyer 
    131      1.90    bouyer /*
    132      1.90    bouyer  * scsi_print_xfer_mode:
    133      1.90    bouyer  *
    134      1.90    bouyer  *	Print a parallel SCSI periph's capabilities.
    135      1.90    bouyer  */
    136      1.90    bouyer static void
    137      1.90    bouyer scsi_print_xfer_mode(struct scsipi_periph *periph)
    138      1.90    bouyer {
    139      1.90    bouyer 	int period, freq, speed, mbs;
    140      1.90    bouyer 
    141      1.90    bouyer 	aprint_normal_dev(periph->periph_dev, "");
    142      1.90    bouyer 	if (periph->periph_mode & (PERIPH_CAP_SYNC | PERIPH_CAP_DT)) {
    143      1.90    bouyer 		period = scsipi_sync_factor_to_period(periph->periph_period);
    144      1.90    bouyer 		aprint_normal("sync (%d.%02dns offset %d)",
    145      1.90    bouyer 		    period / 100, period % 100, periph->periph_offset);
    146      1.90    bouyer 	} else
    147      1.90    bouyer 		aprint_normal("async");
    148      1.90    bouyer 
    149      1.90    bouyer 	if (periph->periph_mode & PERIPH_CAP_WIDE32)
    150      1.90    bouyer 		aprint_normal(", 32-bit");
    151      1.90    bouyer 	else if (periph->periph_mode & (PERIPH_CAP_WIDE16 | PERIPH_CAP_DT))
    152      1.90    bouyer 		aprint_normal(", 16-bit");
    153      1.90    bouyer 	else
    154      1.90    bouyer 		aprint_normal(", 8-bit");
    155      1.90    bouyer 
    156      1.90    bouyer 	if (periph->periph_mode & (PERIPH_CAP_SYNC | PERIPH_CAP_DT)) {
    157      1.90    bouyer 		freq = scsipi_sync_factor_to_freq(periph->periph_period);
    158      1.90    bouyer 		speed = freq;
    159      1.90    bouyer 		if (periph->periph_mode & PERIPH_CAP_WIDE32)
    160      1.90    bouyer 			speed *= 4;
    161      1.90    bouyer 		else if (periph->periph_mode &
    162      1.90    bouyer 		    (PERIPH_CAP_WIDE16 | PERIPH_CAP_DT))
    163      1.90    bouyer 			speed *= 2;
    164      1.90    bouyer 		mbs = speed / 1000;
    165      1.90    bouyer 		if (mbs > 0) {
    166      1.90    bouyer 			aprint_normal(" (%d.%03dMB/s)", mbs,
    167      1.90    bouyer 			    speed % 1000);
    168      1.90    bouyer 		} else
    169      1.90    bouyer 			aprint_normal(" (%dKB/s)", speed % 1000);
    170      1.90    bouyer 	}
    171      1.90    bouyer 
    172      1.90    bouyer 	aprint_normal(" transfers");
    173      1.90    bouyer 
    174      1.90    bouyer 	if (periph->periph_mode & PERIPH_CAP_TQING)
    175      1.90    bouyer 		aprint_normal(", tagged queueing");
    176      1.90    bouyer 
    177      1.90    bouyer 	aprint_normal("\n");
    178      1.90    bouyer }
    179      1.90    bouyer 
    180      1.90    bouyer /*
    181      1.90    bouyer  * scsi_async_event_xfer_mode:
    182      1.90    bouyer  *
    183      1.90    bouyer  *	Update the xfer mode for all parallel SCSI periphs sharing the
    184      1.90    bouyer  *	specified I_T Nexus.
    185      1.90    bouyer  */
    186      1.90    bouyer void
    187      1.90    bouyer scsi_async_event_xfer_mode(struct scsipi_channel *chan, void *arg)
    188      1.90    bouyer {
    189      1.90    bouyer 	struct scsipi_xfer_mode *xm = arg;
    190      1.90    bouyer 	struct scsipi_periph *periph;
    191      1.90    bouyer 	int lun, announce, mode, period, offset;
    192      1.90    bouyer 
    193      1.90    bouyer 	for (lun = 0; lun < chan->chan_nluns; lun++) {
    194      1.91   mlelstv 		periph = scsipi_lookup_periph_locked(chan, xm->xm_target, lun);
    195      1.90    bouyer 		if (periph == NULL)
    196      1.90    bouyer 			continue;
    197      1.90    bouyer 		announce = 0;
    198      1.90    bouyer 
    199      1.90    bouyer 		/*
    200      1.90    bouyer 		 * Clamp the xfer mode down to this periph's capabilities.
    201      1.90    bouyer 		 */
    202      1.90    bouyer 		mode = xm->xm_mode & periph->periph_cap;
    203      1.90    bouyer 		if (mode & PERIPH_CAP_SYNC) {
    204      1.90    bouyer 			period = xm->xm_period;
    205      1.90    bouyer 			offset = xm->xm_offset;
    206      1.90    bouyer 		} else {
    207      1.90    bouyer 			period = 0;
    208      1.90    bouyer 			offset = 0;
    209      1.90    bouyer 		}
    210      1.90    bouyer 
    211      1.90    bouyer 		/*
    212      1.90    bouyer 		 * If we do not have a valid xfer mode yet, or the parameters
    213      1.90    bouyer 		 * are different, announce them.
    214      1.90    bouyer 		 */
    215      1.90    bouyer 		if ((periph->periph_flags & PERIPH_MODE_VALID) == 0 ||
    216      1.90    bouyer 		    periph->periph_mode != mode ||
    217      1.90    bouyer 		    periph->periph_period != period ||
    218      1.90    bouyer 		    periph->periph_offset != offset)
    219      1.90    bouyer 			announce = 1;
    220      1.90    bouyer 
    221      1.90    bouyer 		periph->periph_mode = mode;
    222      1.90    bouyer 		periph->periph_period = period;
    223      1.90    bouyer 		periph->periph_offset = offset;
    224      1.90    bouyer 		periph->periph_flags |= PERIPH_MODE_VALID;
    225      1.90    bouyer 
    226      1.90    bouyer 		if (announce)
    227      1.90    bouyer 			scsi_print_xfer_mode(periph);
    228      1.90    bouyer 	}
    229      1.90    bouyer }
    230      1.90    bouyer 
    231      1.90    bouyer /*
    232      1.90    bouyer  * scsipi_async_event_xfer_mode:
    233      1.90    bouyer  *
    234      1.90    bouyer  *	Update the xfer mode for all SAS/FC periphs sharing the
    235      1.90    bouyer  *	specified I_T Nexus.
    236      1.90    bouyer  */
    237      1.90    bouyer void
    238      1.90    bouyer scsi_fc_sas_async_event_xfer_mode(struct scsipi_channel *chan, void *arg)
    239      1.90    bouyer {
    240      1.90    bouyer 	struct scsipi_xfer_mode *xm = arg;
    241      1.90    bouyer 	struct scsipi_periph *periph;
    242      1.90    bouyer 	int lun, announce, mode;
    243      1.90    bouyer 
    244      1.90    bouyer 	for (lun = 0; lun < chan->chan_nluns; lun++) {
    245      1.91   mlelstv 		periph = scsipi_lookup_periph_locked(chan, xm->xm_target, lun);
    246      1.90    bouyer 		if (periph == NULL)
    247      1.90    bouyer 			continue;
    248      1.90    bouyer 		announce = 0;
    249      1.90    bouyer 
    250      1.90    bouyer 		/*
    251      1.90    bouyer 		 * Clamp the xfer mode down to this periph's capabilities.
    252      1.90    bouyer 		 */
    253      1.90    bouyer 		mode = xm->xm_mode & periph->periph_cap;
    254      1.90    bouyer 		/*
    255      1.90    bouyer 		 * If we do not have a valid xfer mode yet, or the parameters
    256      1.90    bouyer 		 * are different, announce them.
    257      1.90    bouyer 		 */
    258      1.90    bouyer 		if ((periph->periph_flags & PERIPH_MODE_VALID) == 0 ||
    259      1.90    bouyer 		    periph->periph_mode != mode)
    260      1.90    bouyer 			announce = 1;
    261      1.90    bouyer 
    262      1.90    bouyer 		periph->periph_mode = mode;
    263      1.90    bouyer 		periph->periph_flags |= PERIPH_MODE_VALID;
    264      1.90    bouyer 
    265      1.90    bouyer 		if (announce &&
    266      1.90    bouyer 		    (periph->periph_mode & PERIPH_CAP_TQING) != 0) {
    267      1.90    bouyer 			aprint_normal_dev(periph->periph_dev,
    268      1.90    bouyer 			    "tagged queueing\n");
    269      1.90    bouyer 		}
    270      1.90    bouyer 	}
    271      1.90    bouyer }
    272