/* * vvvvvvvvvvvvvvvvvvvvvvv Original vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv * Copyright (C) 1992 Eric Youngdale * Simulate a host adapter with 2 disks attached. Do a lot of checking * to make sure that we are not getting blocks mixed up, and PANIC if * anything out of the ordinary is seen. * ^^^^^^^^^^^^^^^^^^^^^^^ Original ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * * This version is more generic, simulating a variable number of disk * (or disk like devices) sharing a common amount of RAM. To be more * realistic, the simulated devices have the transport attributes of * SAS disks. * * * For documentation see http://sg.danny.cz/sg/sdebug26.html * * D. Gilbert (dpg) work for Magneto-Optical device test [20010421] * dpg: work for devfs large number of disks [20010809] * forked for lk 2.5 series [20011216, 20020101] * use vmalloc() more inquiry+mode_sense [20020302] * add timers for delayed responses [20020721] * Patrick Mansfield <patmans@us.ibm.com> max_luns+scsi_level [20021031] * Mike Anderson <andmike@us.ibm.com> sysfs work [20021118] * dpg: change style of boot options to "scsi_debug.num_tgts=2" and * module options to "modprobe scsi_debug num_tgts=2" [20021221] */ #include <linux/module.h> #include <linux/kernel.h>#include <linux/errno.h>#include <linux/timer.h>#include <linux/slab.h>#include <linux/types.h>#include <linux/string.h>#include <linux/genhd.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/proc_fs.h>#include <linux/vmalloc.h>#include <linux/moduleparam.h>#include <linux/scatterlist.h>#include <linux/blkdev.h>#include <linux/crc-t10dif.h> #include <net/checksum.h> #include <asm/unaligned.h> #include <scsi/scsi.h>#include <scsi/scsi_cmnd.h>#include <scsi/scsi_device.h>#include <scsi/scsi_host.h>#include <scsi/scsicam.h>#include <scsi/scsi_eh.h>#include <scsi/scsi_dbg.h> #include "sd.h"#include "scsi_logging.h" #define SCSI_DEBUG_VERSION "1.82"static const char * scsi_debug_version_date = "20100324"; /* Additional Sense Code (ASC) */#define NO_ADDITIONAL_SENSE 0x0#define LOGICAL_UNIT_NOT_READY 0x4#define UNRECOVERED_READ_ERR 0x11#define PARAMETER_LIST_LENGTH_ERR 0x1a#define INVALID_OPCODE 0x20#define ADDR_OUT_OF_RANGE 0x21#define INVALID_COMMAND_OPCODE 0x20#define INVALID_FIELD_IN_CDB 0x24#define INVALID_FIELD_IN_PARAM_LIST 0x26#define POWERON_RESET 0x29#define SAVING_PARAMS_UNSUP 0x39#define TRANSPORT_PROBLEM 0x4b#define THRESHOLD_EXCEEDED 0x5d#define LOW_POWER_COND_ON 0x5e /* Additional Sense Code Qualifier (ASCQ) */#define ACK_NAK_TO 0x3 #define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */ /* Default values for driver parameters */#define DEF_NUM_HOST 1#define DEF_NUM_TGTS 1#define DEF_MAX_LUNS 1/* With these defaults, this driver will make 1 host with 1 target * (id 0) containing 1 logical unit (lun 0). That is 1 device. */#define DEF_ATO 1#define DEF_DELAY 1#define DEF_DEV_SIZE_MB 8#define DEF_DIF 0#define DEF_DIX 0#define DEF_D_SENSE 0#define DEF_EVERY_NTH 0#define DEF_FAKE_RW 0#define DEF_GUARD 0#define DEF_LBPU 0#define DEF_LBPWS 0#define DEF_LBPWS10 0#define DEF_LBPRZ 1#define DEF_LOWEST_ALIGNED 0#define DEF_NO_LUN_0 0#define DEF_NUM_PARTS 0#define DEF_OPTS 0#define DEF_OPT_BLKS 64#define DEF_PHYSBLK_EXP 0#define DEF_PTYPE 0#define DEF_SCSI_LEVEL 5 /* INQUIRY, byte2 [5->SPC-3] */#define DEF_SECTOR_SIZE 512#define DEF_UNMAP_ALIGNMENT 0#define DEF_UNMAP_GRANULARITY 1#define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF#define DEF_UNMAP_MAX_DESC 256#define DEF_VIRTUAL_GB 0#define DEF_VPD_USE_HOSTNO 1#define DEF_WRITESAME_LENGTH 0xFFFF /* bit mask values for scsi_debug_opts */#define SCSI_DEBUG_OPT_NOISE 1#define SCSI_DEBUG_OPT_MEDIUM_ERR 2#define SCSI_DEBUG_OPT_TIMEOUT 4#define SCSI_DEBUG_OPT_RECOVERED_ERR 8#define SCSI_DEBUG_OPT_TRANSPORT_ERR 16#define SCSI_DEBUG_OPT_DIF_ERR 32#define SCSI_DEBUG_OPT_DIX_ERR 64#define SCSI_DEBUG_OPT_MAC_TIMEOUT 128/* When "every_nth" > 0 then modulo "every_nth" commands: * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set * - a RECOVERED_ERROR is simulated on successful read and write * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set. * - a TRANSPORT_ERROR is simulated on successful read and write * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set. * * When "every_nth" < 0 then after "- every_nth" commands: * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set * - a RECOVERED_ERROR is simulated on successful read and write * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set. * - a TRANSPORT_ERROR is simulated on successful read and write * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set. * This will continue until some other action occurs (e.g. the user * writing a new value (other than -1 or 1) to every_nth via sysfs). */ /* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this * sector on read commands: */#define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */#define OPT_MEDIUM_ERR_NUM 10 /* number of consecutive medium errs */ /* If REPORT LUNS has luns >= 256 it can choose "flat space" (value 1) * or "peripheral device" addressing (value 0) */#define SAM2_LUN_ADDRESS_METHOD 0#define SAM2_WLUN_REPORT_LUNS 0xc101 /* Can queue up to this number of commands. Typically commands that * that have a non-zero delay are queued. */#define SCSI_DEBUG_CANQUEUE 255 static int scsi_debug_add_host = DEF_NUM_HOST;static int scsi_debug_ato = DEF_ATO;static int scsi_debug_delay = DEF_DELAY;static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB;static int scsi_debug_dif = DEF_DIF;static int scsi_debug_dix = DEF_DIX;static int scsi_debug_dsense = DEF_D_SENSE;static int scsi_debug_every_nth = DEF_EVERY_NTH;static int scsi_debug_fake_rw = DEF_FAKE_RW;static int scsi_debug_guard = DEF_GUARD;static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED;static int scsi_debug_max_luns = DEF_MAX_LUNS;static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE;static int scsi_debug_no_lun_0 = DEF_NO_LUN_0;static int scsi_debug_no_uld = 0;static int scsi_debug_num_parts = DEF_NUM_PARTS;static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */static int scsi_debug_opt_blks = DEF_OPT_BLKS;static int scsi_debug_opts = DEF_OPTS;static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP;static int scsi_debug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */static int scsi_debug_scsi_level = DEF_SCSI_LEVEL;static int scsi_debug_sector_size = DEF_SECTOR_SIZE;static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB;static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO;static unsigned int scsi_debug_lbpu = DEF_LBPU;static unsigned int scsi_debug_lbpws = DEF_LBPWS;static unsigned int scsi_debug_lbpws10 = DEF_LBPWS10;static unsigned int scsi_debug_lbprz = DEF_LBPRZ;static unsigned int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT;static unsigned int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;static unsigned int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH; static int scsi_debug_cmnd_count = 0; #define DEV_READONLY(TGT) (0)#define DEV_REMOVEABLE(TGT) (0) static unsigned int sdebug_store_sectors;static sector_t sdebug_capacity; /* in sectors */ /* old BIOS stuff, kernel may get rid of them but some mode sense pages may still need them */static int sdebug_heads; /* heads per disk */static int sdebug_cylinders_per; /* cylinders per surface */static int sdebug_sectors_per; /* sectors per cylinder */ #define SDEBUG_MAX_PARTS 4 #define SDEBUG_SENSE_LEN 32 #define SCSI_DEBUG_MAX_CMD_LEN 32 static unsigned int scsi_debug_lbp(void){ return scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10;} struct sdebug_dev_info { struct list_head dev_list; unsigned char sense_buff[SDEBUG_SENSE_LEN]; /* weak nexus */ unsigned int channel; unsigned int target; unsigned int lun; struct sdebug_host_info *sdbg_host; unsigned int wlun; char reset; char stopped; char used;}; struct sdebug_host_info { struct list_head host_list; struct Scsi_Host *shost; struct device dev; struct list_head dev_info_list;}; #define to_sdebug_host(d) \ container_of(d, struct sdebug_host_info, dev) static LIST_HEAD(sdebug_host_list);static DEFINE_SPINLOCK(sdebug_host_list_lock); typedef void (* done_funct_t) (struct scsi_cmnd *); struct sdebug_queued_cmd { int in_use; struct timer_list cmnd_timer; done_funct_t done_funct; struct scsi_cmnd * a_cmnd; int scsi_result;};static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE]; static unsigned char * fake_storep; /* ramdisk storage */static unsigned char *dif_storep; /* protection info */static void *map_storep; /* provisioning map */ static unsigned long map_size;static int num_aborts = 0;static int num_dev_resets = 0;static int num_bus_resets = 0;static int num_host_resets = 0;static int dix_writes;static int dix_reads;static int dif_errors; static DEFINE_SPINLOCK(queued_arr_lock);static DEFINE_RWLOCK(atomic_rw); static char sdebug_proc_name[] = "scsi_debug"; static struct bus_type pseudo_lld_bus; static inline sector_t dif_offset(sector_t sector){ return sector << 3;} static struct device_driver sdebug_driverfs_driver = { .name = sdebug_proc_name, .bus = &pseudo_lld_bus,}; static const int check_condition_result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; static const int illegal_condition_result = (DRIVER_SENSE << 24) | (DID_ABORT << 16) | SAM_STAT_CHECK_CONDITION; static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0x2, 0x4b};static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, 0, 0, 0x0, 0x0}; static int sdebug_add_adapter(void);static void sdebug_remove_adapter(void); static void sdebug_max_tgts_luns(void){ struct sdebug_host_info *sdbg_host; struct Scsi_Host *hpnt; spin_lock(&sdebug_host_list_lock); list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { hpnt = sdbg_host->shost; if ((hpnt->this_id >= 0) && (scsi_debug_num_tgts > hpnt->this_id)) hpnt->max_id = scsi_debug_num_tgts + 1; else hpnt->max_id = scsi_debug_num_tgts; /* scsi_debug_max_luns; */ hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; } spin_unlock(&sdebug_host_list_lock);} static void mk_sense_buffer(struct sdebug_dev_info *devip, int key, int asc, int asq){ unsigned char *sbuff; sbuff = devip->sense_buff; memset(sbuff, 0, SDEBUG_SENSE_LEN); scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq); if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) printk(KERN_INFO "scsi_debug: [sense_key,asc,ascq]: " "[0x%x,0x%x,0x%x]\n", key, asc, asq);} static void get_data_transfer_info(unsigned char *cmd, unsigned long long *lba, unsigned int *num, u32 *ei_lba){ *ei_lba = 0; switch (*cmd) { case VARIABLE_LENGTH_CMD: *lba = (u64)cmd[19] | (u64)cmd[18] << 8 | (u64)cmd[17] << 16 | (u64)cmd[16] << 24 | (u64)cmd[15] << 32 | (u64)cmd[14] << 40 | (u64)cmd[13] << 48 | (u64)cmd[12] << 56; *ei_lba = (u32)cmd[23] | (u32)cmd[22] << 8 | (u32)cmd[21] << 16 | (u32)cmd[20] << 24; *num = (u32)cmd[31] | (u32)cmd[30] << 8 | (u32)cmd[29] << 16 | (u32)cmd[28] << 24; break; case WRITE_SAME_16: case WRITE_16: case READ_16: *lba = (u64)cmd[9] | (u64)cmd[8] << 8 | (u64)cmd[7] << 16 | (u64)cmd[6] << 24 | (u64)cmd[5] << 32 | (u64)cmd[4] << 40 | (u64)cmd[3] << 48 | (u64)cmd[2] << 56; *num = (u32)cmd[13] | (u32)cmd[12] << 8 | (u32)cmd[11] << 16 | (u32)cmd[10] << 24; break; case WRITE_12: case READ_12: *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 | (u32)cmd[2] << 24; *num = (u32)cmd[9] | (u32)cmd[8] << 8 | (u32)cmd[7] << 16 | (u32)cmd[6] << 24; break; case WRITE_SAME: case WRITE_10: case READ_10: case XDWRITEREAD_10: *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 | (u32)cmd[2] << 24; *num = (u32)cmd[8] | (u32)cmd[7] << 8; break; case WRITE_6: case READ_6: *lba = (u32)cmd[3] | (u32)cmd[2] << 8 | (u32)(cmd[1] & 0x1f) << 16; *num = (0 == cmd[4]) ? 256 : cmd[4]; break; default: break; }} static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg){ if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) { printk(KERN_INFO "scsi_debug: ioctl: cmd=0x%x\n", cmd); } return -EINVAL; /* return -ENOTTY; // correct return but upsets fdisk */} static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only, struct sdebug_dev_info * devip){ if (devip->reset) { if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) printk(KERN_INFO "scsi_debug: Reporting Unit " "attention: power on reset\n"); devip->reset = 0; mk_sense_buffer(devip, UNIT_ATTENTION, POWERON_RESET, 0); return check_condition_result; } if ((0 == reset_only) && devip->stopped) { if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) printk(KERN_INFO "scsi_debug: Reporting Not " "ready: initializing command required\n"); mk_sense_buffer(devip, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2); return check_condition_result; } return 0;} /* Returns 0 if ok else (DID_ERROR << 16). Sets scp->resid . */static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr, int arr_len){ int act_len; struct scsi_data_buffer *sdb = scsi_in(scp); if (!sdb->length) return 0; if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE)) return (DID_ERROR << 16); act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents, arr, arr_len); if (sdb->resid) sdb->resid -= act_len; else sdb->resid = scsi_bufflen(scp) - act_len; return 0;} /* Returns number of bytes fetched into 'arr' or -1 if error. */static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr, int arr_len){ if (!scsi_bufflen(scp)) return 0; if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_TO_DEVICE)) return -1; return scsi_sg_copy_to_buffer(scp, arr, arr_len);} static const char * inq_vendor_id = "Linux ";static const char * inq_product_id = "scsi_debug ";static const char * inq_product_rev = "0004"; static int inquiry_evpd_83(unsigned char * arr, int port_group_id, int target_dev_id, int dev_id_num, const char * dev_id_str, int dev_id_str_len){ int num, port_a; char b[32]; port_a = target_dev_id + 1; /* T10 vendor identifier field format (faked) */ arr[0] = 0x2; /* ASCII */ arr[1] = 0x1; arr[2] = 0x0; memcpy(&arr[4], inq_vendor_id, 8); memcpy(&arr[12], inq_product_id, 16); memcpy(&arr[28], dev_id_str, dev_id_str_len); num = 8 + 16 + dev_id_str_len; arr[3] = num; num += 4; if (dev_id_num >= 0) { /* NAA-5, Logical unit identifier (binary) */ arr[num++] = 0x1; /* binary (not necessarily sas) */ arr[num++] = 0x3; /* PIV=0, lu, naa */ arr[num++] = 0x0; arr[num++] = 0x8; arr[num++] = 0x53; /* naa-5 ieee company id=0x333333 (fake) */ arr[num++] = 0x33; arr[num++] = 0x33; arr[num++] = 0x30; arr[num++] = (dev_id_num >> 24); arr[num++] = (dev_id_num >> 16) & 0xff; arr[num++] = (dev_id_num >> 8) & 0xff; arr[num++] = dev_id_num & 0xff; /* Target relative port number */ arr[num++] = 0x61; /* proto=sas, binary */Lines 1–500 of 4076. Load more
/* * vvvvvvvvvvvvvvvvvvvvvvv Original vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv * Copyright (C) 1992 Eric Youngdale * Simulate a host adapter with 2 disks attached. Do a lot of checking * to make sure that we are not getting blocks mixed up, and PANIC if * anything out of the ordinary is seen. * ^^^^^^^^^^^^^^^^^^^^^^^ Original ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * * This version is more generic, simulating a variable number of disk * (or disk like devices) sharing a common amount of RAM. To be more * realistic, the simulated devices have the transport attributes of * SAS disks. * * * For documentation see http://sg.danny.cz/sg/sdebug26.html * * D. Gilbert (dpg) work for Magneto-Optical device test [20010421] * dpg: work for devfs large number of disks [20010809] * forked for lk 2.5 series [20011216, 20020101] * use vmalloc() more inquiry+mode_sense [20020302] * add timers for delayed responses [20020721] * Patrick Mansfield <patmans@us.ibm.com> max_luns+scsi_level [20021031] * Mike Anderson <andmike@us.ibm.com> sysfs work [20021118] * dpg: change style of boot options to "scsi_debug.num_tgts=2" and * module options to "modprobe scsi_debug num_tgts=2" [20021221] */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/timer.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/string.h> #include <linux/genhd.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/proc_fs.h> #include <linux/vmalloc.h> #include <linux/moduleparam.h> #include <linux/scatterlist.h> #include <linux/blkdev.h> #include <linux/crc-t10dif.h> #include <net/checksum.h> #include <asm/unaligned.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_device.h> #include <scsi/scsi_host.h> #include <scsi/scsicam.h> #include <scsi/scsi_eh.h> #include <scsi/scsi_dbg.h> #include "sd.h" #include "scsi_logging.h" #define SCSI_DEBUG_VERSION "1.82" static const char * scsi_debug_version_date = "20100324"; /* Additional Sense Code (ASC) */ #define NO_ADDITIONAL_SENSE 0x0 #define LOGICAL_UNIT_NOT_READY 0x4 #define UNRECOVERED_READ_ERR 0x11 #define PARAMETER_LIST_LENGTH_ERR 0x1a #define INVALID_OPCODE 0x20 #define ADDR_OUT_OF_RANGE 0x21 #define INVALID_COMMAND_OPCODE 0x20 #define INVALID_FIELD_IN_CDB 0x24 #define INVALID_FIELD_IN_PARAM_LIST 0x26 #define POWERON_RESET 0x29 #define SAVING_PARAMS_UNSUP 0x39 #define TRANSPORT_PROBLEM 0x4b #define THRESHOLD_EXCEEDED 0x5d #define LOW_POWER_COND_ON 0x5e /* Additional Sense Code Qualifier (ASCQ) */ #define ACK_NAK_TO 0x3 #define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */ /* Default values for driver parameters */ #define DEF_NUM_HOST 1 #define DEF_NUM_TGTS 1 #define DEF_MAX_LUNS 1 /* With these defaults, this driver will make 1 host with 1 target * (id 0) containing 1 logical unit (lun 0). That is 1 device. */ #define DEF_ATO 1 #define DEF_DELAY 1 #define DEF_DEV_SIZE_MB 8 #define DEF_DIF 0 #define DEF_DIX 0 #define DEF_D_SENSE 0 #define DEF_EVERY_NTH 0 #define DEF_FAKE_RW 0 #define DEF_GUARD 0 #define DEF_LBPU 0 #define DEF_LBPWS 0 #define DEF_LBPWS10 0 #define DEF_LBPRZ 1 #define DEF_LOWEST_ALIGNED 0 #define DEF_NO_LUN_0 0 #define DEF_NUM_PARTS 0 #define DEF_OPTS 0 #define DEF_OPT_BLKS 64 #define DEF_PHYSBLK_EXP 0 #define DEF_PTYPE 0 #define DEF_SCSI_LEVEL 5 /* INQUIRY, byte2 [5->SPC-3] */ #define DEF_SECTOR_SIZE 512 #define DEF_UNMAP_ALIGNMENT 0 #define DEF_UNMAP_GRANULARITY 1 #define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF #define DEF_UNMAP_MAX_DESC 256 #define DEF_VIRTUAL_GB 0 #define DEF_VPD_USE_HOSTNO 1 #define DEF_WRITESAME_LENGTH 0xFFFF /* bit mask values for scsi_debug_opts */ #define SCSI_DEBUG_OPT_NOISE 1 #define SCSI_DEBUG_OPT_MEDIUM_ERR 2 #define SCSI_DEBUG_OPT_TIMEOUT 4 #define SCSI_DEBUG_OPT_RECOVERED_ERR 8 #define SCSI_DEBUG_OPT_TRANSPORT_ERR 16 #define SCSI_DEBUG_OPT_DIF_ERR 32 #define SCSI_DEBUG_OPT_DIX_ERR 64 #define SCSI_DEBUG_OPT_MAC_TIMEOUT 128 /* When "every_nth" > 0 then modulo "every_nth" commands: * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set * - a RECOVERED_ERROR is simulated on successful read and write * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set. * - a TRANSPORT_ERROR is simulated on successful read and write * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set. * * When "every_nth" < 0 then after "- every_nth" commands: * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set * - a RECOVERED_ERROR is simulated on successful read and write * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set. * - a TRANSPORT_ERROR is simulated on successful read and write * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set. * This will continue until some other action occurs (e.g. the user * writing a new value (other than -1 or 1) to every_nth via sysfs). */ /* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this * sector on read commands: */ #define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */ #define OPT_MEDIUM_ERR_NUM 10 /* number of consecutive medium errs */ /* If REPORT LUNS has luns >= 256 it can choose "flat space" (value 1) * or "peripheral device" addressing (value 0) */ #define SAM2_LUN_ADDRESS_METHOD 0 #define SAM2_WLUN_REPORT_LUNS 0xc101 /* Can queue up to this number of commands. Typically commands that * that have a non-zero delay are queued. */ #define SCSI_DEBUG_CANQUEUE 255 static int scsi_debug_add_host = DEF_NUM_HOST; static int scsi_debug_ato = DEF_ATO; static int scsi_debug_delay = DEF_DELAY; static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB; static int scsi_debug_dif = DEF_DIF; static int scsi_debug_dix = DEF_DIX; static int scsi_debug_dsense = DEF_D_SENSE; static int scsi_debug_every_nth = DEF_EVERY_NTH; static int scsi_debug_fake_rw = DEF_FAKE_RW; static int scsi_debug_guard = DEF_GUARD; static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED; static int scsi_debug_max_luns = DEF_MAX_LUNS; static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE; static int scsi_debug_no_lun_0 = DEF_NO_LUN_0; static int scsi_debug_no_uld = 0; static int scsi_debug_num_parts = DEF_NUM_PARTS; static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */ static int scsi_debug_opt_blks = DEF_OPT_BLKS; static int scsi_debug_opts = DEF_OPTS; static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP; static int scsi_debug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */ static int scsi_debug_scsi_level = DEF_SCSI_LEVEL; static int scsi_debug_sector_size = DEF_SECTOR_SIZE; static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB; static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO; static unsigned int scsi_debug_lbpu = DEF_LBPU; static unsigned int scsi_debug_lbpws = DEF_LBPWS; static unsigned int scsi_debug_lbpws10 = DEF_LBPWS10; static unsigned int scsi_debug_lbprz = DEF_LBPRZ; static unsigned int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT; static unsigned int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY; static unsigned int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS; static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC; static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH; static int scsi_debug_cmnd_count = 0; #define DEV_READONLY(TGT) (0) #define DEV_REMOVEABLE(TGT) (0) static unsigned int sdebug_store_sectors; static sector_t sdebug_capacity; /* in sectors */ /* old BIOS stuff, kernel may get rid of them but some mode sense pages may still need them */ static int sdebug_heads; /* heads per disk */ static int sdebug_cylinders_per; /* cylinders per surface */ static int sdebug_sectors_per; /* sectors per cylinder */ #define SDEBUG_MAX_PARTS 4 #define SDEBUG_SENSE_LEN 32 #define SCSI_DEBUG_MAX_CMD_LEN 32 static unsigned int scsi_debug_lbp(void) { return scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10; } struct sdebug_dev_info { struct list_head dev_list; unsigned char sense_buff[SDEBUG_SENSE_LEN]; /* weak nexus */ unsigned int channel; unsigned int target; unsigned int lun; struct sdebug_host_info *sdbg_host; unsigned int wlun; char reset; char stopped; char used; }; struct sdebug_host_info { struct list_head host_list; struct Scsi_Host *shost; struct device dev; struct list_head dev_info_list; }; #define to_sdebug_host(d) \ container_of(d, struct sdebug_host_info, dev) static LIST_HEAD(sdebug_host_list); static DEFINE_SPINLOCK(sdebug_host_list_lock); typedef void (* done_funct_t) (struct scsi_cmnd *); struct sdebug_queued_cmd { int in_use; struct timer_list cmnd_timer; done_funct_t done_funct; struct scsi_cmnd * a_cmnd; int scsi_result; }; static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE]; static unsigned char * fake_storep; /* ramdisk storage */ static unsigned char *dif_storep; /* protection info */ static void *map_storep; /* provisioning map */ static unsigned long map_size; static int num_aborts = 0; static int num_dev_resets = 0; static int num_bus_resets = 0; static int num_host_resets = 0; static int dix_writes; static int dix_reads; static int dif_errors; static DEFINE_SPINLOCK(queued_arr_lock); static DEFINE_RWLOCK(atomic_rw); static char sdebug_proc_name[] = "scsi_debug"; static struct bus_type pseudo_lld_bus; static inline sector_t dif_offset(sector_t sector) { return sector << 3; } static struct device_driver sdebug_driverfs_driver = { .name = sdebug_proc_name, .bus = &pseudo_lld_bus, }; static const int check_condition_result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; static const int illegal_condition_result = (DRIVER_SENSE << 24) | (DID_ABORT << 16) | SAM_STAT_CHECK_CONDITION; static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0x2, 0x4b}; static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, 0, 0, 0x0, 0x0}; static int sdebug_add_adapter(void); static void sdebug_remove_adapter(void); static void sdebug_max_tgts_luns(void) { struct sdebug_host_info *sdbg_host; struct Scsi_Host *hpnt; spin_lock(&sdebug_host_list_lock); list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { hpnt = sdbg_host->shost; if ((hpnt->this_id >= 0) && (scsi_debug_num_tgts > hpnt->this_id)) hpnt->max_id = scsi_debug_num_tgts + 1; else hpnt->max_id = scsi_debug_num_tgts; /* scsi_debug_max_luns; */ hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; } spin_unlock(&sdebug_host_list_lock); } static void mk_sense_buffer(struct sdebug_dev_info *devip, int key, int asc, int asq) { unsigned char *sbuff; sbuff = devip->sense_buff; memset(sbuff, 0, SDEBUG_SENSE_LEN); scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq); if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) printk(KERN_INFO "scsi_debug: [sense_key,asc,ascq]: " "[0x%x,0x%x,0x%x]\n", key, asc, asq); } static void get_data_transfer_info(unsigned char *cmd, unsigned long long *lba, unsigned int *num, u32 *ei_lba) { *ei_lba = 0; switch (*cmd) { case VARIABLE_LENGTH_CMD: *lba = (u64)cmd[19] | (u64)cmd[18] << 8 | (u64)cmd[17] << 16 | (u64)cmd[16] << 24 | (u64)cmd[15] << 32 | (u64)cmd[14] << 40 | (u64)cmd[13] << 48 | (u64)cmd[12] << 56; *ei_lba = (u32)cmd[23] | (u32)cmd[22] << 8 | (u32)cmd[21] << 16 | (u32)cmd[20] << 24; *num = (u32)cmd[31] | (u32)cmd[30] << 8 | (u32)cmd[29] << 16 | (u32)cmd[28] << 24; break; case WRITE_SAME_16: case WRITE_16: case READ_16: *lba = (u64)cmd[9] | (u64)cmd[8] << 8 | (u64)cmd[7] << 16 | (u64)cmd[6] << 24 | (u64)cmd[5] << 32 | (u64)cmd[4] << 40 | (u64)cmd[3] << 48 | (u64)cmd[2] << 56; *num = (u32)cmd[13] | (u32)cmd[12] << 8 | (u32)cmd[11] << 16 | (u32)cmd[10] << 24; break; case WRITE_12: case READ_12: *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 | (u32)cmd[2] << 24; *num = (u32)cmd[9] | (u32)cmd[8] << 8 | (u32)cmd[7] << 16 | (u32)cmd[6] << 24; break; case WRITE_SAME: case WRITE_10: case READ_10: case XDWRITEREAD_10: *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 | (u32)cmd[2] << 24; *num = (u32)cmd[8] | (u32)cmd[7] << 8; break; case WRITE_6: case READ_6: *lba = (u32)cmd[3] | (u32)cmd[2] << 8 | (u32)(cmd[1] & 0x1f) << 16; *num = (0 == cmd[4]) ? 256 : cmd[4]; break; default: break; } } static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg) { if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) { printk(KERN_INFO "scsi_debug: ioctl: cmd=0x%x\n", cmd); } return -EINVAL; /* return -ENOTTY; // correct return but upsets fdisk */ } static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only, struct sdebug_dev_info * devip) { if (devip->reset) { if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) printk(KERN_INFO "scsi_debug: Reporting Unit " "attention: power on reset\n"); devip->reset = 0; mk_sense_buffer(devip, UNIT_ATTENTION, POWERON_RESET, 0); return check_condition_result; } if ((0 == reset_only) && devip->stopped) { if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) printk(KERN_INFO "scsi_debug: Reporting Not " "ready: initializing command required\n"); mk_sense_buffer(devip, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2); return check_condition_result; } return 0; } /* Returns 0 if ok else (DID_ERROR << 16). Sets scp->resid . */ static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr, int arr_len) { int act_len; struct scsi_data_buffer *sdb = scsi_in(scp); if (!sdb->length) return 0; if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE)) return (DID_ERROR << 16); act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents, arr, arr_len); if (sdb->resid) sdb->resid -= act_len; else sdb->resid = scsi_bufflen(scp) - act_len; return 0; } /* Returns number of bytes fetched into 'arr' or -1 if error. */ static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr, int arr_len) { if (!scsi_bufflen(scp)) return 0; if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_TO_DEVICE)) return -1; return scsi_sg_copy_to_buffer(scp, arr, arr_len); } static const char * inq_vendor_id = "Linux "; static const char * inq_product_id = "scsi_debug "; static const char * inq_product_rev = "0004"; static int inquiry_evpd_83(unsigned char * arr, int port_group_id, int target_dev_id, int dev_id_num, const char * dev_id_str, int dev_id_str_len) { int num, port_a; char b[32]; port_a = target_dev_id + 1; /* T10 vendor identifier field format (faked) */ arr[0] = 0x2; /* ASCII */ arr[1] = 0x1; arr[2] = 0x0; memcpy(&arr[4], inq_vendor_id, 8); memcpy(&arr[12], inq_product_id, 16); memcpy(&arr[28], dev_id_str, dev_id_str_len); num = 8 + 16 + dev_id_str_len; arr[3] = num; num += 4; if (dev_id_num >= 0) { /* NAA-5, Logical unit identifier (binary) */ arr[num++] = 0x1; /* binary (not necessarily sas) */ arr[num++] = 0x3; /* PIV=0, lu, naa */ arr[num++] = 0x0; arr[num++] = 0x8; arr[num++] = 0x53; /* naa-5 ieee company id=0x333333 (fake) */ arr[num++] = 0x33; arr[num++] = 0x33; arr[num++] = 0x30; arr[num++] = (dev_id_num >> 24); arr[num++] = (dev_id_num >> 16) & 0xff; arr[num++] = (dev_id_num >> 8) & 0xff; arr[num++] = dev_id_num & 0xff; /* Target relative port number */ arr[num++] = 0x61; /* proto=sas, binary */