b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * CDDL HEADER START
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth *
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * The contents of this file are subject to the terms of the
36c5fee33fa8b822175d410202aebcf592c8d342mcneal * Common Development and Distribution License (the "License").
36c5fee33fa8b822175d410202aebcf592c8d342mcneal * You may not use this file except in compliance with the License.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth *
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * or http://www.opensolaris.org/os/licensing.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * See the License for the specific language governing permissions
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * and limitations under the License.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth *
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * When distributing Covered Code, include this CDDL HEADER in each
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * If applicable, add the following below this CDDL HEADER, with the
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * fields enclosed by brackets "[]" replaced with your own identifying
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * information: Portions Copyright [yyyy] [name of copyright owner]
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth *
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * CDDL HEADER END
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/*
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Use is subject to license terms.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * pseudo scsi disk driver
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <sys/scsi/scsi.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <sys/ddi.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <sys/sunddi.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <sys/kmem.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <sys/taskq.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <sys/disp.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <sys/types.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <sys/buf.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <sys/emul64.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <sys/emul64cmd.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <sys/emul64var.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Mode sense/select page control
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#define MODE_SENSE_PC_CURRENT 0
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#define MODE_SENSE_PC_CHANGEABLE 1
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#define MODE_SENSE_PC_DEFAULT 2
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#define MODE_SENSE_PC_SAVED 3
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Byte conversion macros
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#if defined(_BIG_ENDIAN)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#define ushort_to_scsi_ushort(n) (n)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#define uint32_to_scsi_uint32(n) (n)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#define uint64_to_scsi_uint64(n) (n)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#elif defined(_LITTLE_ENDIAN)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#define ushort_to_scsi_ushort(n) \
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth ((((n) & 0x00ff) << 8) | \
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (((n) & 0xff00) >> 8))
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#define uint32_to_scsi_uint32(n) \
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth ((((n) & 0x000000ff) << 24) | \
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (((n) & 0x0000ff00) << 8) | \
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (((n) & 0x00ff0000) >> 8) | \
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (((n) & 0xff000000) >> 24))
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#define uint64_to_scsi_uint64(n) \
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth ((((n) & 0x00000000000000ff) << 56) | \
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (((n) & 0x000000000000ff00) << 40) | \
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (((n) & 0x0000000000ff0000) << 24) | \
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (((n) & 0x00000000ff000000) << 8) | \
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (((n) & 0x000000ff00000000) >> 8) | \
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (((n) & 0x0000ff0000000000) >> 24) | \
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (((n) & 0x00ff000000000000) >> 40) | \
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (((n) & 0xff00000000000000) >> 56))
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#else
b1dd958f54f8bfa984d306bb8ca8264855761d7bctherror no _BIG_ENDIAN or _LITTLE_ENDIAN
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#endif
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#define uint_to_byte0(n) ((n) & 0xff)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#define uint_to_byte1(n) (((n)>>8) & 0xff)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#define uint_to_byte2(n) (((n)>>16) & 0xff)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#define uint_to_byte3(n) (((n)>>24) & 0xff)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * struct prop_map
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth *
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * This structure maps a property name to the place to store its value.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstruct prop_map {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth char *pm_name; /* Name of the property. */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int *pm_value; /* Place to store the value. */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth};
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int emul64_debug_blklist = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Some interesting statistics. These are protected by the
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * emul64_stats_mutex. It would be nice to have an ioctl to print them out,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * but we don't have the development time for that now. You can at least
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * look at them with adb.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint emul64_collect_stats = 1; /* Collect stats if non-zero */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthkmutex_t emul64_stats_mutex; /* Protect these variables */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthlong emul64_nowrite_count = 0; /* # active nowrite ranges */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic uint64_t emul64_skipped_io = 0; /* Skipped I/O operations, because of */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /* EMUL64_WRITE_OFF. */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic uint64_t emul64_skipped_blk = 0; /* Skipped blocks because of */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /* EMUL64_WRITE_OFF. */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic uint64_t emul64_io_ops = 0; /* Total number of I/O operations */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /* including skipped and actual. */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic uint64_t emul64_io_blocks = 0; /* Total number of blocks involved */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /* in I/O operations. */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic uint64_t emul64_nonzero = 0; /* Number of non-zero data blocks */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /* currently held in memory */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic uint64_t emul64_max_list_length = 0; /* Maximum size of a linked */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /* list of non-zero blocks. */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthuint64_t emul64_taskq_max = 0; /* emul64_scsi_start uses the taskq */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /* mechanism to dispatch work. */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /* If the number of entries in the */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /* exceeds the maximum for the queue */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /* the queue a 1 second delay is */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /* encountered in taskq_ent_alloc. */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /* This counter counts the number */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /* times that this happens. */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Since emul64 does no physical I/O, operations that would normally be I/O
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * intensive become CPU bound. An example of this is RAID 5
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * initialization. When the kernel becomes CPU bound, it looks as if the
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * machine is hung.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth *
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * To avoid this problem, we provide a function, emul64_yield_check, that does a
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * delay from time to time to yield up the CPU. The following variables
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * are tunables for this algorithm.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth *
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * emul64_num_delay_called Number of times we called delay. This is
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * not really a tunable. Rather it is a
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * counter that provides useful information
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * for adjusting the tunables.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * emul64_yield_length Number of microseconds to yield the CPU.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * emul64_yield_period Number of I/O operations between yields.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * emul64_yield_enable emul64 will yield the CPU, only if this
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * variable contains a non-zero value. This
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * allows the yield functionality to be turned
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * off for experimentation purposes.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth *
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * The value of 1000 for emul64_yield_period has been determined by
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * experience with running the tests.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic uint64_t emul64_num_delay_called = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int emul64_yield_length = 1000;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int emul64_yield_period = 1000;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int emul64_yield_enable = 1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic kmutex_t emul64_yield_mutex;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic kcondvar_t emul64_yield_cv;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * This array establishes a set of tunable variables that can be set by
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * defining properties in the emul64.conf file.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstruct prop_map emul64_properties[] = {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "emul64_collect_stats", &emul64_collect_stats,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "emul64_yield_length", &emul64_yield_length,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "emul64_yield_period", &emul64_yield_period,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "emul64_yield_enable", &emul64_yield_enable,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "emul64_max_task", &emul64_max_task,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "emul64_task_nthreads", &emul64_task_nthreads
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth};
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic unsigned char *emul64_zeros = NULL; /* Block of 0s for comparison */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthextern void emul64_check_cond(struct scsi_pkt *pkt, uchar_t key,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth uchar_t asc, uchar_t ascq);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/* ncyl=250000 acyl=2 nhead=24 nsect=357 */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthuint_t dkg_rpm = 3600;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int bsd_mode_sense_dad_mode_geometry(struct scsi_pkt *);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int bsd_mode_sense_dad_mode_err_recov(struct scsi_pkt *);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int bsd_mode_sense_modepage_disco_reco(struct scsi_pkt *);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int bsd_mode_sense_dad_mode_format(struct scsi_pkt *);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int bsd_mode_sense_dad_mode_cache(struct scsi_pkt *);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int bsd_readblks(struct emul64 *, ushort_t, ushort_t, diskaddr_t,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int, unsigned char *);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int bsd_writeblks(struct emul64 *, ushort_t, ushort_t, diskaddr_t,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int, unsigned char *);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthemul64_tgt_t *find_tgt(struct emul64 *, ushort_t, ushort_t);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic blklist_t *bsd_findblk(emul64_tgt_t *, diskaddr_t, avl_index_t *);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic void bsd_allocblk(emul64_tgt_t *, diskaddr_t, caddr_t, avl_index_t);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic void bsd_freeblk(emul64_tgt_t *, blklist_t *);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic void emul64_yield_check();
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic emul64_rng_overlap_t bsd_tgt_overlap(emul64_tgt_t *, diskaddr_t, int);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthchar *emul64_name = "emul64";
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Initialize globals in this file.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthvoid
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthemul64_bsd_init()
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_zeros = (unsigned char *) kmem_zalloc(DEV_BSIZE, KM_SLEEP);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_init(&emul64_stats_mutex, NULL, MUTEX_DRIVER, NULL);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_init(&emul64_yield_mutex, NULL, MUTEX_DRIVER, NULL);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cv_init(&emul64_yield_cv, NULL, CV_DRIVER, NULL);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Clean up globals in this file.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthvoid
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthemul64_bsd_fini()
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cv_destroy(&emul64_yield_cv);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_destroy(&emul64_yield_mutex);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_destroy(&emul64_stats_mutex);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64_zeros != NULL) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth kmem_free(emul64_zeros, DEV_BSIZE);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_zeros = NULL;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Attempt to get the values of the properties that are specified in the
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * emul64_properties array. If the property exists, copy its value to the
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * specified location. All the properties have been assigned default
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * values in this driver, so if we cannot get the property that is not a
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * problem.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthvoid
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthemul64_bsd_get_props(dev_info_t *dip)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth uint_t count;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth uint_t i;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct prop_map *pmp;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int *properties;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth for (pmp = emul64_properties, i = 0;
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne i < sizeof (emul64_properties) / sizeof (struct prop_map);
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne i++, pmp++) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne DDI_PROP_DONTPASS, pmp->pm_name, &properties,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne &count) == DDI_PROP_SUCCESS) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (count >= 1) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth *pmp->pm_value = *properties;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth ddi_prop_free((void *) properties);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthemul64_bsd_blkcompare(const void *a1, const void *b1)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth blklist_t *a = (blklist_t *)a1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth blklist_t *b = (blklist_t *)b1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (a->bl_blkno < b->bl_blkno)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (-1);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (a->bl_blkno == b->bl_blkno)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (1);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/* ARGSUSED 0 */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_scsi_start_stop_unit(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/* ARGSUSED 0 */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_scsi_test_unit_ready(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/* ARGSUSED 0 */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_scsi_request_sense(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_scsi_inq_page0(struct scsi_pkt *pkt, uchar_t pqdtype)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct emul64_cmd *sp = PKT2CMD(pkt);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (sp->cmd_count < 6) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_scsi_inq_page0: size %d required\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, 6);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (EIO);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[0] = pqdtype; /* periph qual., dtype */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[1] = 0; /* page code */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[2] = 0; /* reserved */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[3] = 6 - 3; /* length */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[4] = 0; /* 1st page */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[5] = 0x83; /* 2nd page */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_resid = sp->cmd_count - 6;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_scsi_inq_page83(struct scsi_pkt *pkt, uchar_t pqdtype)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct emul64 *emul64 = PKT2EMUL64(pkt);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct emul64_cmd *sp = PKT2CMD(pkt);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int instance = ddi_get_instance(emul64->emul64_dip);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (sp->cmd_count < 22) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_scsi_inq_page83: size %d required\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, 22);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (EIO);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[0] = pqdtype; /* periph qual., dtype */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[1] = 0x83; /* page code */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[2] = 0; /* reserved */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[3] = (22 - 8) + 4; /* length */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[4] = 1; /* code set - binary */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[5] = 3; /* association and device ID type 3 */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[6] = 0; /* reserved */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[7] = 22 - 8; /* ID length */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[8] = 0xde; /* @8: identifier, byte 0 */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[9] = 0xca;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[10] = 0xde;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[11] = 0x80;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[12] = 0xba;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[13] = 0xbe;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[14] = 0xab;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[15] = 0xba;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /* @22: */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Instances seem to be assigned sequentially, so it unlikely that we
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * will have more than 65535 of them.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[16] = uint_to_byte1(instance);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[17] = uint_to_byte0(instance);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[18] = uint_to_byte1(TGT(sp));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[19] = uint_to_byte0(TGT(sp));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[20] = uint_to_byte1(LUN(sp));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[21] = uint_to_byte0(LUN(sp));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_resid = sp->cmd_count - 22;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_scsi_inquiry(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct emul64_cmd *sp = PKT2CMD(pkt);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth union scsi_cdb *cdb = (union scsi_cdb *)pkt->pkt_cdbp;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_tgt_t *tgt;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth uchar_t pqdtype;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct scsi_inquiry inq;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth EMUL64_MUTEX_ENTER(sp->cmd_emul64);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth tgt = find_tgt(sp->cmd_emul64,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_address.a_target, pkt->pkt_address.a_lun);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth EMUL64_MUTEX_EXIT(sp->cmd_emul64);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (sp->cmd_count < sizeof (inq)) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_scsi_inquiry: size %d required\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, (int)sizeof (inq));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (EIO);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (cdb->cdb_opaque[1] & 0xfc) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_WARN, "%s: bsd_scsi_inquiry: 0x%x",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, cdb->cdb_opaque[1]);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_check_cond(pkt, 0x5, 0x24, 0x0); /* inv. fld in cdb */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pqdtype = tgt->emul64_tgt_dtype;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (cdb->cdb_opaque[1] & 0x1) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth switch (cdb->cdb_opaque[2]) {
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne case 0x00:
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne return (bsd_scsi_inq_page0(pkt, pqdtype));
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne case 0x83:
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne return (bsd_scsi_inq_page83(pkt, pqdtype));
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne default:
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne cmn_err(CE_WARN, "%s: bsd_scsi_inquiry: "
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne "unsupported 0x%x",
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne emul64_name, cdb->cdb_opaque[2]);
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /* set up the inquiry data we return */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bzero((void *)&inq, sizeof (inq));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth inq.inq_dtype = pqdtype;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth inq.inq_ansi = 2;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth inq.inq_rdf = 2;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth inq.inq_len = sizeof (inq) - 4;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth inq.inq_wbus16 = 1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth inq.inq_cmdque = 1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bcopy(tgt->emul64_tgt_inq, inq.inq_vid,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sizeof (tgt->emul64_tgt_inq));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bcopy("1", inq.inq_revision, 2);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bcopy((void *)&inq, sp->cmd_addr, sizeof (inq));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_resid = sp->cmd_count - sizeof (inq);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/* ARGSUSED 0 */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_scsi_format(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_scsi_io(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct emul64_cmd *sp = PKT2CMD(pkt);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth union scsi_cdb *cdb = (union scsi_cdb *)pkt->pkt_cdbp;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth diskaddr_t lblkno;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int nblks;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth switch (cdb->scc_cmd) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case SCMD_READ:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth lblkno = (uint32_t)GETG0ADDR(cdb);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth nblks = GETG0COUNT(cdb);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_resid = bsd_readblks(sp->cmd_emul64,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne pkt->pkt_address.a_target, pkt->pkt_address.a_lun,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne lblkno, nblks, sp->cmd_addr);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64debug) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_scsi_io: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "read g0 blk=%lld (0x%llx) nblks=%d\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, lblkno, lblkno, nblks);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case SCMD_WRITE:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth lblkno = (uint32_t)GETG0ADDR(cdb);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth nblks = GETG0COUNT(cdb);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_resid = bsd_writeblks(sp->cmd_emul64,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne pkt->pkt_address.a_target, pkt->pkt_address.a_lun,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne lblkno, nblks, sp->cmd_addr);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64debug) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_scsi_io: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "write g0 blk=%lld (0x%llx) nblks=%d\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, lblkno, lblkno, nblks);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case SCMD_READ_G1:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth lblkno = (uint32_t)GETG1ADDR(cdb);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth nblks = GETG1COUNT(cdb);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_resid = bsd_readblks(sp->cmd_emul64,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne pkt->pkt_address.a_target, pkt->pkt_address.a_lun,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne lblkno, nblks, sp->cmd_addr);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64debug) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_scsi_io: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "read g1 blk=%lld (0x%llx) nblks=%d\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, lblkno, lblkno, nblks);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case SCMD_WRITE_G1:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth lblkno = (uint32_t)GETG1ADDR(cdb);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth nblks = GETG1COUNT(cdb);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_resid = bsd_writeblks(sp->cmd_emul64,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne pkt->pkt_address.a_target, pkt->pkt_address.a_lun,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne lblkno, nblks, sp->cmd_addr);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64debug) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_scsi_io: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "write g1 blk=%lld (0x%llx) nblks=%d\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, lblkno, lblkno, nblks);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case SCMD_READ_G4:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth lblkno = GETG4ADDR(cdb);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth lblkno <<= 32;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth lblkno |= (uint32_t)GETG4ADDRTL(cdb);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth nblks = GETG4COUNT(cdb);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_resid = bsd_readblks(sp->cmd_emul64,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne pkt->pkt_address.a_target, pkt->pkt_address.a_lun,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne lblkno, nblks, sp->cmd_addr);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64debug) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_scsi_io: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "read g4 blk=%lld (0x%llx) nblks=%d\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, lblkno, lblkno, nblks);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case SCMD_WRITE_G4:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth lblkno = GETG4ADDR(cdb);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth lblkno <<= 32;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth lblkno |= (uint32_t)GETG4ADDRTL(cdb);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth nblks = GETG4COUNT(cdb);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_resid = bsd_writeblks(sp->cmd_emul64,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne pkt->pkt_address.a_target, pkt->pkt_address.a_lun,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne lblkno, nblks, sp->cmd_addr);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64debug) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_scsi_io: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "write g4 blk=%lld (0x%llx) nblks=%d\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, lblkno, lblkno, nblks);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth default:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_WARN, "%s: bsd_scsi_io: unhandled I/O: 0x%x",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, cdb->scc_cmd);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (pkt->pkt_resid != 0)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_WARN, "%s: bsd_scsi_io: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "pkt_resid: 0x%lx, lblkno %lld, nblks %d",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, pkt->pkt_resid, lblkno, nblks);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_scsi_log_sense(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth union scsi_cdb *cdb = (union scsi_cdb *)pkt->pkt_cdbp;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct emul64_cmd *sp = PKT2CMD(pkt);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int page_code;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (sp->cmd_count < 9) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_scsi_log_sense size %d required\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, 9);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (EIO);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page_code = cdb->cdb_opaque[2] & 0x3f;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (page_code) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_scsi_log_sense: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "page 0x%x not supported\n", emul64_name, page_code);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_check_cond(pkt, 0x5, 0x24, 0x0); /* inv. fld in cdb */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[0] = 0; /* page code */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[1] = 0; /* reserved */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[2] = 0; /* MSB of page length */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[3] = 8 - 3; /* LSB of page length */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[4] = 0; /* MSB of parameter code */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[5] = 0; /* LSB of parameter code */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[6] = 0; /* parameter control byte */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[7] = 4 - 3; /* parameter length */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sp->cmd_addr[8] = 0x0; /* parameter value */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_resid = sp->cmd_count - 9;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_scsi_mode_sense(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth union scsi_cdb *cdb = (union scsi_cdb *)pkt->pkt_cdbp;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int page_control;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int page_code;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int rval = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth switch (cdb->scc_cmd) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case SCMD_MODE_SENSE:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page_code = cdb->cdb_opaque[2] & 0x3f;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page_control = (cdb->cdb_opaque[2] >> 6) & 0x03;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64debug) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_scsi_mode_sense: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "page=0x%x control=0x%x nbytes=%d\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, page_code, page_control,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth GETG0COUNT(cdb));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case SCMD_MODE_SENSE_G1:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page_code = cdb->cdb_opaque[2] & 0x3f;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page_control = (cdb->cdb_opaque[2] >> 6) & 0x03;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64debug) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_scsi_mode_sense: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "page=0x%x control=0x%x nbytes=%d\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, page_code, page_control,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth GETG1COUNT(cdb));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth default:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_scsi_mode_sense: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "cmd 0x%x not supported\n", emul64_name, cdb->scc_cmd);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (EIO);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth switch (page_code) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case DAD_MODE_GEOMETRY:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth rval = bsd_mode_sense_dad_mode_geometry(pkt);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case DAD_MODE_ERR_RECOV:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth rval = bsd_mode_sense_dad_mode_err_recov(pkt);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODEPAGE_DISCO_RECO:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth rval = bsd_mode_sense_modepage_disco_reco(pkt);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case DAD_MODE_FORMAT:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth rval = bsd_mode_sense_dad_mode_format(pkt);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case DAD_MODE_CACHE:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth rval = bsd_mode_sense_dad_mode_cache(pkt);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth default:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_scsi_mode_sense: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "page 0x%x not supported\n", emul64_name, page_code);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth rval = EIO;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (rval);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_mode_sense_dad_mode_geometry(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct emul64_cmd *sp = PKT2CMD(pkt);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth union scsi_cdb *cdb = (union scsi_cdb *)pkt->pkt_cdbp;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth uchar_t *addr = (uchar_t *)sp->cmd_addr;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_tgt_t *tgt;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int page_control;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct mode_header header;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct mode_geometry page4;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int ncyl;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int rval = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page_control = (cdb->cdb_opaque[2] >> 6) & 0x03;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64debug) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_mode_sense_dad_mode_geometry: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "pc=%d n=%d\n", emul64_name, page_control, sp->cmd_count);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (sp->cmd_count < (sizeof (header) + sizeof (page4))) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_mode_sense_dad_mode_geometry: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "size %d required\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, (int)(sizeof (header) + sizeof (page4)));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (EIO);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bzero(&header, sizeof (header));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bzero(&page4, sizeof (page4));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth header.length = sizeof (header) + sizeof (page4) - 1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth header.bdesc_length = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page4.mode_page.code = DAD_MODE_GEOMETRY;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page4.mode_page.ps = 1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page4.mode_page.length = sizeof (page4) - sizeof (struct mode_page);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth switch (page_control) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_CURRENT:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_DEFAULT:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_SAVED:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth EMUL64_MUTEX_ENTER(sp->cmd_emul64);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth tgt = find_tgt(sp->cmd_emul64,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_address.a_target, pkt->pkt_address.a_lun);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth EMUL64_MUTEX_EXIT(sp->cmd_emul64);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth ncyl = tgt->emul64_tgt_ncyls;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page4.cyl_ub = uint_to_byte2(ncyl);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page4.cyl_mb = uint_to_byte1(ncyl);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page4.cyl_lb = uint_to_byte0(ncyl);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page4.heads = uint_to_byte0(tgt->emul64_tgt_nheads);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page4.rpm = ushort_to_scsi_ushort(dkg_rpm);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_CHANGEABLE:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page4.cyl_ub = 0xff;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page4.cyl_mb = 0xff;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page4.cyl_lb = 0xff;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page4.heads = 0xff;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page4.rpm = 0xffff;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bcopy(&header, addr, sizeof (header));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bcopy(&page4, addr + sizeof (header), sizeof (page4));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_resid = sp->cmd_count - sizeof (page4) - sizeof (header);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth rval = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (rval);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_mode_sense_dad_mode_err_recov(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct emul64_cmd *sp = PKT2CMD(pkt);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth union scsi_cdb *cdb = (union scsi_cdb *)pkt->pkt_cdbp;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth uchar_t *addr = (uchar_t *)sp->cmd_addr;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int page_control;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct mode_header header;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct mode_err_recov page1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int rval = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page_control = (cdb->cdb_opaque[2] >> 6) & 0x03;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64debug) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_mode_sense_dad_mode_err_recov: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "pc=%d n=%d\n", emul64_name, page_control, sp->cmd_count);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (sp->cmd_count < (sizeof (header) + sizeof (page1))) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_mode_sense_dad_mode_err_recov: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "size %d required\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, (int)(sizeof (header) + sizeof (page1)));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (EIO);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bzero(&header, sizeof (header));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bzero(&page1, sizeof (page1));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth header.length = sizeof (header) + sizeof (page1) - 1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth header.bdesc_length = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page1.mode_page.code = DAD_MODE_ERR_RECOV;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page1.mode_page.ps = 1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page1.mode_page.length = sizeof (page1) - sizeof (struct mode_page);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth switch (page_control) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_CURRENT:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_DEFAULT:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_SAVED:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_CHANGEABLE:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bcopy(&header, addr, sizeof (header));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bcopy(&page1, addr + sizeof (header), sizeof (page1));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_resid = sp->cmd_count - sizeof (page1) - sizeof (header);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth rval = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (rval);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_mode_sense_modepage_disco_reco(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct emul64_cmd *sp = PKT2CMD(pkt);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth union scsi_cdb *cdb = (union scsi_cdb *)pkt->pkt_cdbp;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int rval = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth uchar_t *addr = (uchar_t *)sp->cmd_addr;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int page_control;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct mode_header header;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct mode_disco_reco page2;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page_control = (cdb->cdb_opaque[2] >> 6) & 0x03;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64debug) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_mode_sense_modepage_disco_reco: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "pc=%d n=%d\n", emul64_name, page_control, sp->cmd_count);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (sp->cmd_count < (sizeof (header) + sizeof (page2))) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_mode_sense_modepage_disco_reco: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "size %d required\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, (int)(sizeof (header) + sizeof (page2)));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (EIO);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bzero(&header, sizeof (header));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bzero(&page2, sizeof (page2));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth header.length = sizeof (header) + sizeof (page2) - 1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth header.bdesc_length = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page2.mode_page.code = MODEPAGE_DISCO_RECO;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page2.mode_page.ps = 1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page2.mode_page.length = sizeof (page2) - sizeof (struct mode_page);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth switch (page_control) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_CURRENT:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_DEFAULT:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_SAVED:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_CHANGEABLE:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bcopy(&header, addr, sizeof (header));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bcopy(&page2, addr + sizeof (header), sizeof (page2));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_resid = sp->cmd_count - sizeof (page2) - sizeof (header);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth rval = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (rval);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_mode_sense_dad_mode_format(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct emul64_cmd *sp = PKT2CMD(pkt);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth union scsi_cdb *cdb = (union scsi_cdb *)pkt->pkt_cdbp;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth uchar_t *addr = (uchar_t *)sp->cmd_addr;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_tgt_t *tgt;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int page_control;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct mode_header header;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct mode_format page3;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int rval = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page_control = (cdb->cdb_opaque[2] >> 6) & 0x03;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64debug) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_mode_sense_dad_mode_format: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "pc=%d n=%d\n", emul64_name, page_control, sp->cmd_count);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (sp->cmd_count < (sizeof (header) + sizeof (page3))) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_mode_sense_dad_mode_format: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "size %d required\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, (int)(sizeof (header) + sizeof (page3)));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (EIO);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bzero(&header, sizeof (header));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bzero(&page3, sizeof (page3));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth header.length = sizeof (header) + sizeof (page3) - 1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth header.bdesc_length = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page3.mode_page.code = DAD_MODE_FORMAT;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page3.mode_page.ps = 1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page3.mode_page.length = sizeof (page3) - sizeof (struct mode_page);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth switch (page_control) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_CURRENT:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_DEFAULT:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_SAVED:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page3.data_bytes_sect = ushort_to_scsi_ushort(DEV_BSIZE);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page3.interleave = ushort_to_scsi_ushort(1);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth EMUL64_MUTEX_ENTER(sp->cmd_emul64);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth tgt = find_tgt(sp->cmd_emul64,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne pkt->pkt_address.a_target, pkt->pkt_address.a_lun);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth EMUL64_MUTEX_EXIT(sp->cmd_emul64);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page3.sect_track = ushort_to_scsi_ushort(tgt->emul64_tgt_nsect);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_CHANGEABLE:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bcopy(&header, addr, sizeof (header));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bcopy(&page3, addr + sizeof (header), sizeof (page3));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_resid = sp->cmd_count - sizeof (page3) - sizeof (header);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth rval = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (rval);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_mode_sense_dad_mode_cache(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct emul64_cmd *sp = PKT2CMD(pkt);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth union scsi_cdb *cdb = (union scsi_cdb *)pkt->pkt_cdbp;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth uchar_t *addr = (uchar_t *)sp->cmd_addr;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int page_control;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct mode_header header;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct mode_cache page8;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int rval = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page_control = (cdb->cdb_opaque[2] >> 6) & 0x03;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64debug) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_mode_sense_dad_mode_cache: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "pc=%d n=%d\n", emul64_name, page_control, sp->cmd_count);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (sp->cmd_count < (sizeof (header) + sizeof (page8))) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_mode_sense_dad_mode_cache: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "size %d required\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, (int)(sizeof (header) + sizeof (page8)));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (EIO);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bzero(&header, sizeof (header));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bzero(&page8, sizeof (page8));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth header.length = sizeof (header) + sizeof (page8) - 1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth header.bdesc_length = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page8.mode_page.code = DAD_MODE_CACHE;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page8.mode_page.ps = 1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth page8.mode_page.length = sizeof (page8) - sizeof (struct mode_page);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth switch (page_control) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_CURRENT:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_DEFAULT:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_SAVED:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case MODE_SENSE_PC_CHANGEABLE:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bcopy(&header, addr, sizeof (header));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bcopy(&page8, addr + sizeof (header), sizeof (page8));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_resid = sp->cmd_count - sizeof (page8) - sizeof (header);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth rval = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (rval);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/* ARGSUSED 0 */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_scsi_mode_select(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_scsi_read_capacity_8(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct emul64_cmd *sp = PKT2CMD(pkt);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_tgt_t *tgt;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct scsi_capacity cap;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int rval = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth EMUL64_MUTEX_ENTER(sp->cmd_emul64);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth tgt = find_tgt(sp->cmd_emul64,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne pkt->pkt_address.a_target, pkt->pkt_address.a_lun);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth EMUL64_MUTEX_EXIT(sp->cmd_emul64);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (tgt->emul64_tgt_sectors > 0xffffffff)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cap.capacity = 0xffffffff;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth else
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cap.capacity =
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth uint32_to_scsi_uint32(tgt->emul64_tgt_sectors);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cap.lbasize = uint32_to_scsi_uint32((uint_t)DEV_BSIZE);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_resid = sp->cmd_count - sizeof (struct scsi_capacity);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bcopy(&cap, (caddr_t)sp->cmd_addr,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne sizeof (struct scsi_capacity));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (rval);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_scsi_read_capacity_16(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct emul64_cmd *sp = PKT2CMD(pkt);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_tgt_t *tgt;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth struct scsi_capacity_16 cap;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int rval = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth EMUL64_MUTEX_ENTER(sp->cmd_emul64);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth tgt = find_tgt(sp->cmd_emul64,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne pkt->pkt_address.a_target, pkt->pkt_address.a_lun);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth EMUL64_MUTEX_EXIT(sp->cmd_emul64);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cap.sc_capacity = uint64_to_scsi_uint64(tgt->emul64_tgt_sectors);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cap.sc_lbasize = uint32_to_scsi_uint32((uint_t)DEV_BSIZE);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cap.sc_rto_en = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cap.sc_prot_en = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cap.sc_rsvd0 = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth bzero(&cap.sc_rsvd1[0], sizeof (cap.sc_rsvd1));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_resid = sp->cmd_count - sizeof (struct scsi_capacity_16);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bcopy(&cap, (caddr_t)sp->cmd_addr,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne sizeof (struct scsi_capacity_16));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (rval);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_scsi_read_capacity(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (bsd_scsi_read_capacity_8(pkt));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/* ARGSUSED 0 */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_scsi_reserve(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/* ARGSUSED 0 */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_scsi_release(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_scsi_read_defect_list(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth pkt->pkt_resid = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/* ARGSUSED 0 */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_scsi_reassign_block(struct scsi_pkt *pkt)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int
cd210bb4840e6add5921c775aa07cebd6891f738Chris Hornebsd_readblks(struct emul64 *emul64, ushort_t target, ushort_t lun,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne diskaddr_t blkno, int nblks, unsigned char *bufaddr)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_tgt_t *tgt;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth blklist_t *blk;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_rng_overlap_t overlap;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int i = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64debug) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_readblks: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "<%d,%d> blk %llu (0x%llx) nblks %d\n",
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne emul64_name, target, lun, blkno, blkno, nblks);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_yield_check();
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth EMUL64_MUTEX_ENTER(emul64);
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne tgt = find_tgt(emul64, target, lun);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth EMUL64_MUTEX_EXIT(emul64);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (tgt == NULL) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_WARN, "%s: bsd_readblks: no target for %d,%d\n",
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne emul64_name, target, lun);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth goto unlocked_out;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64_collect_stats) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_enter(&emul64_stats_mutex);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_io_ops++;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_io_blocks += nblks;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_exit(&emul64_stats_mutex);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_enter(&tgt->emul64_tgt_blk_lock);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Keep the ioctls from changing the nowrite list for the duration
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * of this I/O by grabbing emul64_tgt_nw_lock. This will keep the
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * results from our call to bsd_tgt_overlap from changing while we
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * do the I/O.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth rw_enter(&tgt->emul64_tgt_nw_lock, RW_READER);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth overlap = bsd_tgt_overlap(tgt, blkno, nblks);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth switch (overlap) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case O_SAME:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case O_SUBSET:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case O_OVERLAP:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_WARN, "%s: bsd_readblks: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "read to blocked area %lld,%d\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, blkno, nblks);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth rw_exit(&tgt->emul64_tgt_nw_lock);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth goto errout;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case O_NONE:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth for (i = 0; i < nblks; i++) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64_debug_blklist)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_readblks: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "%d of %d: blkno %lld\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, i+1, nblks, blkno);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (blkno > tgt->emul64_tgt_sectors)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth blk = bsd_findblk(tgt, blkno, NULL);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (blk) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bcopy(blk->bl_data, bufaddr, DEV_BSIZE);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth } else {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bzero(bufaddr, DEV_BSIZE);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth blkno++;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth bufaddr += DEV_BSIZE;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth rw_exit(&tgt->emul64_tgt_nw_lock);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bctherrout:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_exit(&tgt->emul64_tgt_blk_lock);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthunlocked_out:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return ((nblks - i) * DEV_BSIZE);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int
cd210bb4840e6add5921c775aa07cebd6891f738Chris Hornebsd_writeblks(struct emul64 *emul64, ushort_t target, ushort_t lun,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne diskaddr_t blkno, int nblks, unsigned char *bufaddr)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_tgt_t *tgt;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth blklist_t *blk;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_rng_overlap_t overlap;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth avl_index_t where;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int i = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64debug) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_writeblks: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "<%d,%d> blk %llu (0x%llx) nblks %d\n",
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne emul64_name, target, lun, blkno, blkno, nblks);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_yield_check();
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth EMUL64_MUTEX_ENTER(emul64);
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne tgt = find_tgt(emul64, target, lun);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth EMUL64_MUTEX_EXIT(emul64);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (tgt == NULL) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_WARN, "%s: bsd_writeblks: no target for %d,%d\n",
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne emul64_name, target, lun);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth goto unlocked_out;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64_collect_stats) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_enter(&emul64_stats_mutex);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_io_ops++;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_io_blocks += nblks;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_exit(&emul64_stats_mutex);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_enter(&tgt->emul64_tgt_blk_lock);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Keep the ioctls from changing the nowrite list for the duration
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * of this I/O by grabbing emul64_tgt_nw_lock. This will keep the
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * results from our call to bsd_tgt_overlap from changing while we
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * do the I/O.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth rw_enter(&tgt->emul64_tgt_nw_lock, RW_READER);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth overlap = bsd_tgt_overlap(tgt, blkno, nblks);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth switch (overlap) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case O_SAME:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case O_SUBSET:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64_collect_stats) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_enter(&emul64_stats_mutex);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_skipped_io++;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_skipped_blk += nblks;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_exit(&emul64_stats_mutex);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth rw_exit(&tgt->emul64_tgt_nw_lock);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_exit(&tgt->emul64_tgt_blk_lock);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case O_OVERLAP:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case O_NONE:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth for (i = 0; i < nblks; i++) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if ((overlap == O_NONE) ||
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (bsd_tgt_overlap(tgt, blkno, 1) == O_NONE)) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * If there was no overlap for the entire I/O range
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * or if there is no overlap for this particular
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * block, then we need to do the write.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64_debug_blklist)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_writeblks: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "%d of %d: blkno %lld\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, i+1, nblks, blkno);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (blkno > tgt->emul64_tgt_sectors) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_WARN, "%s: bsd_writeblks: "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "blkno %lld, tgt_sectors %lld\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, blkno,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth tgt->emul64_tgt_sectors);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth blk = bsd_findblk(tgt, blkno, &where);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (bcmp(bufaddr, emul64_zeros, DEV_BSIZE) == 0) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (blk) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth bsd_freeblk(tgt, blk);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth } else {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (blk) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bcopy(bufaddr, blk->bl_data,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne DEV_BSIZE);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth } else {
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne bsd_allocblk(tgt, blkno,
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne (caddr_t)bufaddr, where);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth blkno++;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth bufaddr += DEV_BSIZE;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Now that we're done with our I/O, allow the ioctls to change the
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * nowrite list.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth rw_exit(&tgt->emul64_tgt_nw_lock);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bctherrout:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_exit(&tgt->emul64_tgt_blk_lock);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthunlocked_out:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return ((nblks - i) * DEV_BSIZE);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthemul64_tgt_t *
cd210bb4840e6add5921c775aa07cebd6891f738Chris Hornefind_tgt(struct emul64 *emul64, ushort_t target, ushort_t lun)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_tgt_t *tgt;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth tgt = emul64->emul64_tgt;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth while (tgt) {
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne if (tgt->emul64_tgt_saddr.a_target == target &&
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne tgt->emul64_tgt_saddr.a_lun == lun) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth tgt = tgt->emul64_tgt_next;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (tgt);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Free all blocks that are part of the specified range.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_freeblkrange(emul64_tgt_t *tgt, emul64_range_t *range)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth blklist_t *blk;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth blklist_t *nextblk;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth ASSERT(mutex_owned(&tgt->emul64_tgt_blk_lock));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth for (blk = (blklist_t *)avl_first(&tgt->emul64_tgt_data);
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne blk != NULL;
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne blk = nextblk) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * We need to get the next block pointer now, because blk
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * will be freed inside the if statement.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth nextblk = AVL_NEXT(&tgt->emul64_tgt_data, blk);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64_overlap(range, blk->bl_blkno, (size_t)1) != O_NONE) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth bsd_freeblk(tgt, blk);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic blklist_t *
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_findblk(emul64_tgt_t *tgt, diskaddr_t blkno, avl_index_t *where)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth blklist_t *blk;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth blklist_t search;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth ASSERT(mutex_owned(&tgt->emul64_tgt_blk_lock));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth search.bl_blkno = blkno;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth blk = (blklist_t *)avl_find(&tgt->emul64_tgt_data, &search, where);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (blk);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic void
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_allocblk(emul64_tgt_t *tgt,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth diskaddr_t blkno,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth caddr_t data,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth avl_index_t where)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth blklist_t *blk;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64_debug_blklist)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_allocblk: %llu\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, blkno);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth ASSERT(mutex_owned(&tgt->emul64_tgt_blk_lock));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth blk = (blklist_t *)kmem_zalloc(sizeof (blklist_t), KM_SLEEP);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth blk->bl_data = (uchar_t *)kmem_zalloc(DEV_BSIZE, KM_SLEEP);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth blk->bl_blkno = blkno;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) bcopy(data, blk->bl_data, DEV_BSIZE);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth avl_insert(&tgt->emul64_tgt_data, (void *) blk, where);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64_collect_stats) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_enter(&emul64_stats_mutex);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_nonzero++;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth tgt->emul64_list_length++;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (tgt->emul64_list_length > emul64_max_list_length) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_max_list_length = tgt->emul64_list_length;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_exit(&emul64_stats_mutex);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic void
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_freeblk(emul64_tgt_t *tgt, blklist_t *blk)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64_debug_blklist)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmn_err(CE_CONT, "%s: bsd_freeblk: <%d,%d> blk=%lld\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_name, tgt->emul64_tgt_saddr.a_target,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth tgt->emul64_tgt_saddr.a_lun, blk->bl_blkno);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth ASSERT(mutex_owned(&tgt->emul64_tgt_blk_lock));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth avl_remove(&tgt->emul64_tgt_data, (void *) blk);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64_collect_stats) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_enter(&emul64_stats_mutex);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_nonzero--;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth tgt->emul64_list_length--;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_exit(&emul64_stats_mutex);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth kmem_free(blk->bl_data, DEV_BSIZE);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth kmem_free(blk, sizeof (blklist_t));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Look for overlap between a nowrite range and a block range.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth *
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * NOTE: Callers of this function must hold the tgt->emul64_tgt_nw_lock
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * lock. For the purposes of this function, a reader lock is
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * sufficient.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic emul64_rng_overlap_t
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthbsd_tgt_overlap(emul64_tgt_t *tgt, diskaddr_t blkno, int count)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_nowrite_t *nw;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_rng_overlap_t rv = O_NONE;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth for (nw = tgt->emul64_tgt_nowrite;
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne (nw != NULL) && (rv == O_NONE);
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne nw = nw->emul64_nwnext) {
cd210bb4840e6add5921c775aa07cebd6891f738Chris Horne rv = emul64_overlap(&nw->emul64_blocked, blkno, (size_t)count);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (rv);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Operations that do a lot of I/O, such as RAID 5 initializations, result
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * in a CPU bound kernel when the device is an emul64 device. This makes
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * the machine look hung. To avoid this problem, give up the CPU from time
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * to time.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic void
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthemul64_yield_check()
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth static uint_t emul64_io_count = 0; /* # I/Os since last wait */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth static uint_t emul64_waiting = FALSE; /* TRUE -> a thread is in */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /* cv_timed wait. */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth clock_t ticks;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64_yield_enable == 0)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_enter(&emul64_yield_mutex);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (emul64_waiting == TRUE) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Another thread has already started the timer. We'll
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * just wait here until their time expires, and they
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * broadcast to us. When they do that, we'll return and
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * let our caller do more I/O.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cv_wait(&emul64_yield_cv, &emul64_yield_mutex);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth } else if (emul64_io_count++ > emul64_yield_period) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Set emul64_waiting to let other threads know that we
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * have started the timer.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_waiting = TRUE;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_num_delay_called++;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth ticks = drv_usectohz(emul64_yield_length);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (ticks == 0)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth ticks = 1;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (void) cv_reltimedwait(&emul64_yield_cv, &emul64_yield_mutex,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni ticks, TR_CLOCK_TICK);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_io_count = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_waiting = FALSE;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /* Broadcast in case others are waiting. */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cv_broadcast(&emul64_yield_cv);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth mutex_exit(&emul64_yield_mutex);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}