mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-17 10:41:26 +00:00
REPORT SUPPORTED OPERATION CODES added
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@5418 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -661,6 +661,7 @@ struct scst_acg;
|
||||
struct scst_acg_dev;
|
||||
struct scst_acn;
|
||||
struct scst_aen;
|
||||
struct scst_opcode_descriptor;
|
||||
|
||||
/*
|
||||
* SCST uses 64-bit numbers to represent LUN's internally. The value
|
||||
@@ -1374,6 +1375,29 @@ struct scst_dev_type {
|
||||
*/
|
||||
bool (*on_sg_tablesize_low) (struct scst_cmd *cmd);
|
||||
|
||||
/*
|
||||
* Called to return array of supported opcodes in out_supp_opcodes
|
||||
* argument with out_supp_opcodes_cnt elements count or execute
|
||||
* REPORT SUPPORTED OPERATION CODES command in place. Must return
|
||||
* 0 on success or any other code otherwise. In the latter case,
|
||||
* cmd supposed to have correct sense set.
|
||||
*
|
||||
* OPTIONAL
|
||||
*/
|
||||
int (*get_supported_opcodes) (struct scst_cmd *cmd,
|
||||
const struct scst_opcode_descriptor ***out_supp_opcodes,
|
||||
int *out_supp_opcodes_cnt);
|
||||
|
||||
/*
|
||||
* Called to put (release) array of supported opcodes returned
|
||||
* by get_supported_opcodes() callback.
|
||||
*
|
||||
* OPTIONAL
|
||||
*/
|
||||
void (*put_supported_opcodes) (struct scst_cmd *cmd,
|
||||
const struct scst_opcode_descriptor **supp_opcodes,
|
||||
int supp_opcodes_cnt);
|
||||
|
||||
/*
|
||||
* Called when new device is attaching to the dev handler
|
||||
* Returns 0 on success, error code otherwise.
|
||||
@@ -2896,6 +2920,58 @@ struct scst_aen {
|
||||
int delivery_status;
|
||||
};
|
||||
|
||||
#define SCST_OD_DEFAULT_CONTROL_BYTE 0
|
||||
|
||||
struct scst_opcode_descriptor {
|
||||
uint16_t od_serv_action;
|
||||
uint8_t od_opcode;
|
||||
uint8_t od_serv_action_valid:1;
|
||||
uint8_t od_support:3; /* SUPPORT bits */
|
||||
uint16_t od_cdb_size;
|
||||
uint8_t od_comm_specific_timeout;
|
||||
uint32_t od_nominal_timeout;
|
||||
uint32_t od_recommended_timeout;
|
||||
uint8_t od_cdb_usage_bits[];
|
||||
} __packed;
|
||||
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_log_select;
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_log_sense;
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_mode_select6;
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_mode_sense6;
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_mode_select10;
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_mode_sense10;
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_rtpg;
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_stpg;
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_send_diagnostic;
|
||||
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_inquiry;
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_tur;
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_reserve6;
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_release6;
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_reserve10;
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_release10;
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_pr_in;
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_pr_out;
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_report_luns;
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_request_sense;
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_report_supp_tm_fns;
|
||||
extern const struct scst_opcode_descriptor scst_op_descr_report_supp_opcodes;
|
||||
|
||||
#define SCST_OPCODE_DESCRIPTORS \
|
||||
&scst_op_descr_inquiry, \
|
||||
&scst_op_descr_tur, \
|
||||
&scst_op_descr_reserve6, \
|
||||
&scst_op_descr_release6, \
|
||||
&scst_op_descr_reserve10, \
|
||||
&scst_op_descr_release10, \
|
||||
&scst_op_descr_pr_in, \
|
||||
&scst_op_descr_pr_out, \
|
||||
&scst_op_descr_report_luns, \
|
||||
&scst_op_descr_request_sense, \
|
||||
&scst_op_descr_report_supp_opcodes, \
|
||||
&scst_op_descr_report_supp_tm_fns,
|
||||
|
||||
|
||||
#ifndef smp_mb__after_set_bit
|
||||
/* There is no smp_mb__after_set_bit() in the kernel */
|
||||
#define smp_mb__after_set_bit() smp_mb()
|
||||
|
||||
@@ -571,6 +571,7 @@ enum scst_tg_sup {
|
||||
** Various timeouts
|
||||
*************************************************************/
|
||||
#define SCST_DEFAULT_TIMEOUT (30 * HZ)
|
||||
#define SCST_DEFAULT_NOMINAL_TIMEOUT_SEC 1
|
||||
|
||||
#define SCST_GENERIC_CHANGER_TIMEOUT (3 * HZ)
|
||||
#define SCST_GENERIC_CHANGER_LONG_TIMEOUT (14000 * HZ)
|
||||
@@ -586,8 +587,8 @@ enum scst_tg_sup {
|
||||
#define SCST_GENERIC_MODISK_REG_TIMEOUT (900 * HZ)
|
||||
#define SCST_GENERIC_MODISK_LONG_TIMEOUT (14000 * HZ)
|
||||
|
||||
#define SCST_GENERIC_DISK_SMALL_TIMEOUT (3 * HZ)
|
||||
#define SCST_GENERIC_DISK_REG_TIMEOUT (30 * HZ)
|
||||
#define SCST_GENERIC_DISK_SMALL_TIMEOUT (10 * HZ)
|
||||
#define SCST_GENERIC_DISK_REG_TIMEOUT (60 * HZ)
|
||||
#define SCST_GENERIC_DISK_LONG_TIMEOUT (3600 * HZ)
|
||||
|
||||
#define SCST_GENERIC_RAID_TIMEOUT (3 * HZ)
|
||||
|
||||
@@ -244,6 +244,12 @@ static int vdisk_attach(struct scst_device *dev);
|
||||
static void vdisk_detach(struct scst_device *dev);
|
||||
static int vdisk_attach_tgt(struct scst_tgt_dev *tgt_dev);
|
||||
static void vdisk_detach_tgt(struct scst_tgt_dev *tgt_dev);
|
||||
static int vdisk_get_supported_opcodes(struct scst_cmd *cmd,
|
||||
const struct scst_opcode_descriptor ***out_supp_opcodes,
|
||||
int *out_supp_opcodes_cnt);
|
||||
static int vcdrom_get_supported_opcodes(struct scst_cmd *cmd,
|
||||
const struct scst_opcode_descriptor ***out_supp_opcodes,
|
||||
int *out_supp_opcodes_cnt);
|
||||
static int fileio_alloc_data_buf(struct scst_cmd *cmd);
|
||||
static int vdisk_parse(struct scst_cmd *);
|
||||
static int vcdrom_parse(struct scst_cmd *);
|
||||
@@ -565,6 +571,7 @@ static struct scst_dev_type vdisk_file_devtype = {
|
||||
.exec = vdisk_exec,
|
||||
.on_free_cmd = fileio_on_free_cmd,
|
||||
.task_mgmt_fn_done = vdisk_task_mgmt_fn_done,
|
||||
.get_supported_opcodes = vdisk_get_supported_opcodes,
|
||||
.devt_priv = (void *)fileio_ops,
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
.read_proc = vdisk_read_proc,
|
||||
@@ -613,6 +620,7 @@ static struct scst_dev_type vdisk_blk_devtype = {
|
||||
.parse = non_fileio_parse,
|
||||
.exec = non_fileio_exec,
|
||||
.task_mgmt_fn_done = vdisk_task_mgmt_fn_done,
|
||||
.get_supported_opcodes = vdisk_get_supported_opcodes,
|
||||
.devt_priv = (void *)blockio_ops,
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
.add_device = vdisk_add_blockio_device,
|
||||
@@ -655,6 +663,7 @@ static struct scst_dev_type vdisk_null_devtype = {
|
||||
.exec = non_fileio_exec,
|
||||
.task_mgmt_fn_done = vdisk_task_mgmt_fn_done,
|
||||
.devt_priv = (void *)nullio_ops,
|
||||
.get_supported_opcodes = vdisk_get_supported_opcodes,
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
.add_device = vdisk_add_nullio_device,
|
||||
.del_device = vdisk_del_device,
|
||||
@@ -694,6 +703,7 @@ static struct scst_dev_type vcdrom_devtype = {
|
||||
.exec = vcdrom_exec,
|
||||
.on_free_cmd = fileio_on_free_cmd,
|
||||
.task_mgmt_fn_done = vdisk_task_mgmt_fn_done,
|
||||
.get_supported_opcodes = vcdrom_get_supported_opcodes,
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
.read_proc = vcdrom_read_proc,
|
||||
.write_proc = vcdrom_write_proc,
|
||||
@@ -1398,6 +1408,311 @@ static enum compl_status_e vdisk_invalid_opcode(struct vdisk_cmd_params *p)
|
||||
return INVALID_OPCODE;
|
||||
}
|
||||
|
||||
#define VDEV_DEF_RDPROTECT 0
|
||||
#define VDEV_DEF_WRPROTECT 0
|
||||
#define VDEV_DEF_VRPROTECT 0
|
||||
|
||||
#define VDEF_DEF_GROUP_NUM 0
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_cwr = {
|
||||
.od_opcode = COMPARE_AND_WRITE,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 16,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { COMPARE_AND_WRITE, VDEV_DEF_WRPROTECT | 0x18, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
|
||||
0, 0, 0, 0xFF, VDEF_DEF_GROUP_NUM, \
|
||||
SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_format_unit = {
|
||||
.od_opcode = FORMAT_UNIT,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 6,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_LONG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { FORMAT_UNIT, 0xF0, 0, 0, 0, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_get_lba_status = {
|
||||
.od_opcode = SERVICE_ACTION_IN,
|
||||
.od_serv_action = SAI_GET_LBA_STATUS,
|
||||
.od_serv_action_valid = 1,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 16,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { SERVICE_ACTION_IN, SAI_GET_LBA_STATUS, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0, \
|
||||
SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_allow_medium_removal = {
|
||||
.od_opcode = ALLOW_MEDIUM_REMOVAL,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 6,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { ALLOW_MEDIUM_REMOVAL, 0, 0, 0, 3, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_read6 = {
|
||||
.od_opcode = READ_6,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 6,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { READ_6, 0x1F, \
|
||||
0xFF, 0xFF, 0xFF, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_read10 = {
|
||||
.od_opcode = READ_10,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 10,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { READ_10, VDEV_DEF_RDPROTECT | 0x18, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, VDEF_DEF_GROUP_NUM, \
|
||||
0xFF, 0xFF, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_read12 = {
|
||||
.od_opcode = READ_12,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 12,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { READ_12, VDEV_DEF_RDPROTECT | 0x18, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
|
||||
VDEF_DEF_GROUP_NUM, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_read16 = {
|
||||
.od_opcode = READ_16,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 16,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { READ_16, VDEV_DEF_RDPROTECT | 0x18, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, VDEF_DEF_GROUP_NUM, \
|
||||
SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_read_capacity = {
|
||||
.od_opcode = READ_CAPACITY,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 10,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_read_capacity16 = {
|
||||
.od_opcode = SERVICE_ACTION_IN,
|
||||
.od_serv_action = SAI_READ_CAPACITY_16,
|
||||
.od_serv_action_valid = 1,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 16,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { SERVICE_ACTION_IN, SAI_READ_CAPACITY_16, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0, \
|
||||
SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_start_stop_unit = {
|
||||
.od_opcode = START_STOP,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 6,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { START_STOP, 1, 0, 0xF, 0xF7, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_sync_cache10 = {
|
||||
.od_opcode = SYNCHRONIZE_CACHE,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 10,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { SYNCHRONIZE_CACHE, 2, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, VDEF_DEF_GROUP_NUM, \
|
||||
0xFF, 0xFF, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_sync_cache16 = {
|
||||
.od_opcode = SYNCHRONIZE_CACHE_16,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 16,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { SYNCHRONIZE_CACHE_16, 2, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, VDEF_DEF_GROUP_NUM, \
|
||||
SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_unmap = {
|
||||
.od_opcode = UNMAP,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 10,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { UNMAP, 0, 0, 0, 0, 0, VDEF_DEF_GROUP_NUM, \
|
||||
0xFF, 0xFF, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_verify10 = {
|
||||
.od_opcode = VERIFY,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 10,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { VERIFY, VDEV_DEF_VRPROTECT | 0x16, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, VDEF_DEF_GROUP_NUM, \
|
||||
0xFF, 0xFF, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_verify12 = {
|
||||
.od_opcode = VERIFY_12,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 12,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { VERIFY_12, VDEV_DEF_VRPROTECT | 0x16, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
|
||||
VDEF_DEF_GROUP_NUM, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_verify16 = {
|
||||
.od_opcode = VERIFY_16,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 16,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { VERIFY_16, VDEV_DEF_VRPROTECT | 0x16, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, VDEF_DEF_GROUP_NUM, \
|
||||
SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_write6 = {
|
||||
.od_opcode = WRITE_6,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 6,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { WRITE_6, 0x1F, \
|
||||
0xFF, 0xFF, 0xFF, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_write10 = {
|
||||
.od_opcode = WRITE_10,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 10,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { WRITE_10, VDEV_DEF_WRPROTECT | 0x1A, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, VDEF_DEF_GROUP_NUM, \
|
||||
0xFF, 0xFF, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_write12 = {
|
||||
.od_opcode = WRITE_12,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 12,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { WRITE_12, VDEV_DEF_WRPROTECT | 0x1A, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
|
||||
VDEF_DEF_GROUP_NUM, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_write16 = {
|
||||
.od_opcode = WRITE_16,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 16,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { WRITE_16, VDEV_DEF_WRPROTECT | 0x1A, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, VDEF_DEF_GROUP_NUM, \
|
||||
SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_write_verify10 = {
|
||||
.od_opcode = WRITE_VERIFY,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 10,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { WRITE_VERIFY, VDEV_DEF_WRPROTECT | 0x16, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, VDEF_DEF_GROUP_NUM, \
|
||||
0xFF, 0xFF, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_write_verify12 = {
|
||||
.od_opcode = WRITE_VERIFY_12,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 12,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { WRITE_VERIFY_12, VDEV_DEF_WRPROTECT | 0x16, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
|
||||
VDEF_DEF_GROUP_NUM, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_write_verify16 = {
|
||||
.od_opcode = WRITE_VERIFY_16,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 16,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { WRITE_VERIFY_16, VDEV_DEF_WRPROTECT | 0x16, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, VDEF_DEF_GROUP_NUM, \
|
||||
SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_write_same10 = {
|
||||
.od_opcode = WRITE_SAME,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 10,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { WRITE_SAME, VDEV_DEF_WRPROTECT | 0x8, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, VDEF_DEF_GROUP_NUM, \
|
||||
0xFF, 0xFF, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_write_same16 = {
|
||||
.od_opcode = WRITE_SAME_16,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 16,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { WRITE_SAME_16, VDEV_DEF_WRPROTECT | 0x8, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, VDEF_DEF_GROUP_NUM, \
|
||||
SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor scst_op_descr_read_toc = {
|
||||
.od_opcode = READ_TOC,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 10,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_REG_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { READ_TOC, 0, 0xF, 0, 0, 0, 0xFF, \
|
||||
0xFF, 0xFF, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
|
||||
#define SHARED_OPS \
|
||||
[SYNCHRONIZE_CACHE] = vdisk_synchronize_cache, \
|
||||
[SYNCHRONIZE_CACHE_16] = vdisk_synchronize_cache, \
|
||||
@@ -1427,6 +1742,34 @@ static enum compl_status_e vdisk_invalid_opcode(struct vdisk_cmd_params *p)
|
||||
[SEND_DIAGNOSTIC] = vdisk_exec_send_diagnostic, \
|
||||
[FORMAT_UNIT] = vdisk_exec_format_unit,
|
||||
|
||||
#define SHARED_OPCODE_DESCRIPTORS \
|
||||
&scst_op_descr_sync_cache10, \
|
||||
&scst_op_descr_sync_cache16, \
|
||||
&scst_op_descr_mode_sense6, \
|
||||
&scst_op_descr_mode_sense10, \
|
||||
&scst_op_descr_mode_select6, \
|
||||
&scst_op_descr_mode_select10, \
|
||||
&scst_op_descr_log_select, \
|
||||
&scst_op_descr_log_sense, \
|
||||
&scst_op_descr_start_stop_unit, \
|
||||
&scst_op_descr_read_capacity, \
|
||||
&scst_op_descr_send_diagnostic, \
|
||||
&scst_op_descr_rtpg, \
|
||||
&scst_op_descr_read6, \
|
||||
&scst_op_descr_read10, \
|
||||
&scst_op_descr_read12, \
|
||||
&scst_op_descr_read16, \
|
||||
&scst_op_descr_write6, \
|
||||
&scst_op_descr_write10, \
|
||||
&scst_op_descr_write12, \
|
||||
&scst_op_descr_write16, \
|
||||
&scst_op_descr_write_verify10, \
|
||||
&scst_op_descr_write_verify12, \
|
||||
&scst_op_descr_write_verify16, \
|
||||
&scst_op_descr_verify10, \
|
||||
&scst_op_descr_verify12, \
|
||||
&scst_op_descr_verify16,
|
||||
|
||||
static vdisk_op_fn blockio_ops[256] = {
|
||||
[READ_6] = blockio_exec_read,
|
||||
[READ_10] = blockio_exec_read,
|
||||
@@ -1481,6 +1824,45 @@ static vdisk_op_fn nullio_ops[256] = {
|
||||
SHARED_OPS
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor *vdisk_opcode_descriptors[] = {
|
||||
SHARED_OPCODE_DESCRIPTORS
|
||||
#if 0 /* it's INVALID OPCODE currently */
|
||||
&scst_op_descr_get_lba_status,
|
||||
#endif
|
||||
&scst_op_descr_read_capacity16,
|
||||
&scst_op_descr_write_same10,
|
||||
&scst_op_descr_write_same16,
|
||||
&scst_op_descr_unmap,
|
||||
&scst_op_descr_format_unit,
|
||||
&scst_op_descr_cwr,
|
||||
SCST_OPCODE_DESCRIPTORS
|
||||
};
|
||||
|
||||
static const struct scst_opcode_descriptor *vcdrom_opcode_descriptors[] = {
|
||||
SHARED_OPCODE_DESCRIPTORS
|
||||
&scst_op_descr_allow_medium_removal,
|
||||
&scst_op_descr_read_toc,
|
||||
SCST_OPCODE_DESCRIPTORS
|
||||
};
|
||||
|
||||
static int vdisk_get_supported_opcodes(struct scst_cmd *cmd,
|
||||
const struct scst_opcode_descriptor ***out_supp_opcodes,
|
||||
int *out_supp_opcodes_cnt)
|
||||
{
|
||||
*out_supp_opcodes = vdisk_opcode_descriptors;
|
||||
*out_supp_opcodes_cnt = ARRAY_SIZE(vdisk_opcode_descriptors);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vcdrom_get_supported_opcodes(struct scst_cmd *cmd,
|
||||
const struct scst_opcode_descriptor ***out_supp_opcodes,
|
||||
int *out_supp_opcodes_cnt)
|
||||
{
|
||||
*out_supp_opcodes = vcdrom_opcode_descriptors;
|
||||
*out_supp_opcodes_cnt = ARRAY_SIZE(vcdrom_opcode_descriptors);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute p->loff and p->fua.
|
||||
* Returns true for success or false otherwise and set error in the commeand.
|
||||
@@ -3535,6 +3917,7 @@ out:
|
||||
|
||||
static enum compl_status_e vdisk_exec_get_lba_status(struct vdisk_cmd_params *p)
|
||||
{
|
||||
/* Changing it don't forget to add it to vdisk_opcode_descriptors! */
|
||||
return INVALID_OPCODE;
|
||||
}
|
||||
|
||||
|
||||
@@ -88,6 +88,240 @@ static int sg_copy(struct scatterlist *dst_sg, struct scatterlist *src_sg,
|
||||
|
||||
static void scst_free_descriptors(struct scst_cmd *cmd);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_inquiry = {
|
||||
.od_opcode = INQUIRY,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 6,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { INQUIRY, 1, 0xFF, 0xFF, 0xFF, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_inquiry);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_tur = {
|
||||
.od_opcode = TEST_UNIT_READY,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 6,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { TEST_UNIT_READY, 0, 0, 0, 0, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_tur);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_log_select = {
|
||||
.od_opcode = LOG_SELECT,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 10,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { LOG_SELECT, 3, 0xFF, 0xFF, 0, 0, 0, 0xFF, 0xFF, \
|
||||
SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_log_select);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_log_sense = {
|
||||
.od_opcode = LOG_SENSE,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 10,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { LOG_SENSE, 1, 0xFF, 0xFF, 0, 0xFF, 0xFF, 0xFF, 0xFF, \
|
||||
SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_log_sense);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_mode_select6 = {
|
||||
.od_opcode = MODE_SELECT,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 6,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { MODE_SELECT, 0x11, 0, 0, 0xFF, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_mode_select6);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_mode_sense6 = {
|
||||
.od_opcode = MODE_SENSE,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 6,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { MODE_SENSE, 8, 0xFF, 0xFF, 0xFF, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_mode_sense6);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_mode_select10 = {
|
||||
.od_opcode = MODE_SELECT_10,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 10,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { MODE_SELECT_10, 0x11, 0, 0, 0, 0, 0, 0xFF, 0xFF, \
|
||||
SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_mode_select10);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_mode_sense10 = {
|
||||
.od_opcode = MODE_SENSE_10,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 10,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { MODE_SENSE_10, 0x18, 0xFF, 0xFF, 0, 0, 0, 0xFF, 0xFF, \
|
||||
SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_mode_sense10);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_rtpg = {
|
||||
.od_opcode = MAINTENANCE_IN,
|
||||
.od_serv_action = MI_REPORT_TARGET_PGS,
|
||||
.od_serv_action_valid = 1,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 12,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { MAINTENANCE_IN, 0xE0|MI_REPORT_TARGET_PGS, 0, 0, \
|
||||
0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_rtpg);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_stpg = {
|
||||
.od_opcode = MAINTENANCE_OUT,
|
||||
.od_serv_action = MO_SET_TARGET_PGS,
|
||||
.od_serv_action_valid = 1,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 12,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { MAINTENANCE_IN, MO_SET_TARGET_PGS, 0, 0, 0, 0, \
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_stpg);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_send_diagnostic = {
|
||||
.od_opcode = SEND_DIAGNOSTIC,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 6,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { SEND_DIAGNOSTIC, 0xF7, 0, 0xFF, 0xFF, \
|
||||
SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_send_diagnostic);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_reserve6 = {
|
||||
.od_opcode = RESERVE,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 6,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { RESERVE, 0, 0, 0, 0, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_reserve6);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_release6 = {
|
||||
.od_opcode = RELEASE,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 6,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { RELEASE, 0, 0, 0, 0, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_release6);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_reserve10 = {
|
||||
.od_opcode = RESERVE_10,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 10,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { RESERVE_10, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_reserve10);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_release10 = {
|
||||
.od_opcode = RELEASE_10,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 10,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { RELEASE_10, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_release10);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_pr_in = {
|
||||
.od_opcode = PERSISTENT_RESERVE_IN,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 10,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { PERSISTENT_RESERVE_IN, 0x1F, 0, 0, 0, 0, 0, 0xFF, 0xFF, \
|
||||
SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_pr_in);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_pr_out = {
|
||||
.od_opcode = PERSISTENT_RESERVE_OUT,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 10,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { PERSISTENT_RESERVE_OUT, 0x1F, 0xFF, 0, 0, 0xFF, \
|
||||
0xFF, 0xFF, 0xFF, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_pr_out);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_report_luns = {
|
||||
.od_opcode = REPORT_LUNS,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 12,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { REPORT_LUNS, 0, 0xFF, 0, 0, 0, 0xFF, 0xFF, \
|
||||
0xFF, 0xFF, 0, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_report_luns);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_request_sense = {
|
||||
.od_opcode = REQUEST_SENSE,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 6,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { REQUEST_SENSE, 1, 0, 0, 0xFF, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_request_sense);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_report_supp_tm_fns = {
|
||||
.od_opcode = MAINTENANCE_IN,
|
||||
.od_serv_action = MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS,
|
||||
.od_serv_action_valid = 1,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 12,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { MAINTENANCE_IN, MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS, \
|
||||
0x80, 0, 0, 0, 0xFF, 0xFF, 0xFF, \
|
||||
0xFF, 0, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_report_supp_tm_fns);
|
||||
|
||||
const struct scst_opcode_descriptor scst_op_descr_report_supp_opcodes = {
|
||||
.od_opcode = MAINTENANCE_IN,
|
||||
.od_serv_action = MI_REPORT_SUPPORTED_OPERATION_CODES,
|
||||
.od_serv_action_valid = 1,
|
||||
.od_support = 3, /* supported as in the standard */
|
||||
.od_cdb_size = 12,
|
||||
.od_nominal_timeout = SCST_DEFAULT_NOMINAL_TIMEOUT_SEC,
|
||||
.od_recommended_timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT/HZ,
|
||||
.od_cdb_usage_bits = { MAINTENANCE_IN, MI_REPORT_SUPPORTED_OPERATION_CODES, \
|
||||
0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
|
||||
0xFF, 0, SCST_OD_DEFAULT_CONTROL_BYTE },
|
||||
};
|
||||
EXPORT_SYMBOL(scst_op_descr_report_supp_opcodes);
|
||||
|
||||
struct scst_sdbops;
|
||||
|
||||
static int get_cdb_info_len_10(struct scst_cmd *cmd,
|
||||
@@ -6901,7 +7135,8 @@ static int get_cdb_info_min(struct scst_cmd *cmd,
|
||||
break;
|
||||
case MI_REPORT_SUPPORTED_OPERATION_CODES:
|
||||
cmd->op_name = "REPORT SUPPORTED OPERATION CODES";
|
||||
cmd->op_flags |= SCST_WRITE_EXCL_ALLOWED;
|
||||
cmd->op_flags |= SCST_WRITE_EXCL_ALLOWED |
|
||||
SCST_LOCAL_CMD | SCST_FULLY_LOCAL_CMD;
|
||||
break;
|
||||
case MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS:
|
||||
cmd->op_name = "REPORT SUPPORTED TASK MANAGEMENT FUNCTIONS";
|
||||
|
||||
@@ -2111,6 +2111,208 @@ out_compl:
|
||||
return res;
|
||||
}
|
||||
|
||||
static int scst_report_supported_opcodes(struct scst_cmd *cmd)
|
||||
{
|
||||
int res = SCST_EXEC_COMPLETED;
|
||||
int length, buf_len, i, offs;
|
||||
uint8_t *address;
|
||||
uint8_t *buf;
|
||||
bool inline_buf;
|
||||
bool rctd = cmd->cdb[2] >> 7;
|
||||
int options = cmd->cdb[2] & 7;
|
||||
int req_opcode = cmd->cdb[3];
|
||||
int req_sa = get_unaligned_be16(&cmd->cdb[4]);
|
||||
const struct scst_opcode_descriptor *op = NULL;
|
||||
const struct scst_opcode_descriptor **supp_opcodes = NULL;
|
||||
int supp_opcodes_cnt;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (cmd->devt->get_supported_opcodes == NULL) {
|
||||
TRACE(TRACE_MINOR, "Unknown opcode 0x%02x", cmd->cdb[0]);
|
||||
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_invalid_opcode));
|
||||
goto out_compl;
|
||||
} else {
|
||||
int rc = cmd->devt->get_supported_opcodes(cmd, &supp_opcodes,
|
||||
&supp_opcodes_cnt);
|
||||
if (rc != 0)
|
||||
goto out_compl;
|
||||
}
|
||||
|
||||
TRACE_DBG("cmd %p, options %d, req_opcode %x, req_sa %x, rctd %d",
|
||||
cmd, options, req_opcode, req_sa, rctd);
|
||||
|
||||
switch (options) {
|
||||
case 0: /* all */
|
||||
buf_len = 4;
|
||||
for (i = 0; i < supp_opcodes_cnt; i++) {
|
||||
buf_len += 8;
|
||||
if (rctd)
|
||||
buf_len += 12;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
buf_len = 0;
|
||||
for (i = 0; i < supp_opcodes_cnt; i++) {
|
||||
if (req_opcode == supp_opcodes[i]->od_opcode) {
|
||||
op = supp_opcodes[i];
|
||||
if (op->od_serv_action_valid) {
|
||||
TRACE(TRACE_MINOR, "Requested opcode %x "
|
||||
"with unexpected service action "
|
||||
"(dev %s, initiator %s)",
|
||||
req_opcode, cmd->dev->virt_name,
|
||||
cmd->sess->initiator_name);
|
||||
scst_set_invalid_field_in_cdb(cmd, 2,
|
||||
SCST_INVAL_FIELD_BIT_OFFS_VALID | 0);
|
||||
goto out_compl;
|
||||
}
|
||||
buf_len = 4 + op->od_cdb_size;
|
||||
if (rctd)
|
||||
buf_len += 12;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (op == NULL) {
|
||||
TRACE(TRACE_MINOR, "Requested opcode %x not found "
|
||||
"(dev %s, initiator %s)", req_opcode,
|
||||
cmd->dev->virt_name, cmd->sess->initiator_name);
|
||||
buf_len = 4;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
buf_len = 0;
|
||||
for (i = 0; i < supp_opcodes_cnt; i++) {
|
||||
if (req_opcode == supp_opcodes[i]->od_opcode) {
|
||||
op = supp_opcodes[i];
|
||||
if (!op->od_serv_action_valid) {
|
||||
TRACE(TRACE_MINOR, "Requested opcode %x "
|
||||
"without expected service action "
|
||||
"(dev %s, initiator %s)",
|
||||
req_opcode, cmd->dev->virt_name,
|
||||
cmd->sess->initiator_name);
|
||||
scst_set_invalid_field_in_cdb(cmd, 2,
|
||||
SCST_INVAL_FIELD_BIT_OFFS_VALID | 0);
|
||||
goto out_compl;
|
||||
}
|
||||
if (req_sa != op->od_serv_action) {
|
||||
op = NULL; /* reset it */
|
||||
continue;
|
||||
}
|
||||
buf_len = 4 + op->od_cdb_size;
|
||||
if (rctd)
|
||||
buf_len += 12;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (op == NULL) {
|
||||
TRACE(TRACE_MINOR, "Requested opcode %x/%x not found "
|
||||
"(dev %s, initiator %s)", req_opcode, req_sa,
|
||||
cmd->dev->virt_name, cmd->sess->initiator_name);
|
||||
buf_len = 4;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
PRINT_ERROR("REPORT SUPPORTED OPERATION CODES: REPORTING OPTIONS "
|
||||
"%x not supported (dev %s, initiator %s)", options,
|
||||
cmd->dev->virt_name, cmd->sess->initiator_name);
|
||||
scst_set_invalid_field_in_cdb(cmd, 2,
|
||||
SCST_INVAL_FIELD_BIT_OFFS_VALID | 0);
|
||||
goto out_compl;
|
||||
}
|
||||
|
||||
length = scst_get_buf_full_sense(cmd, &address);
|
||||
TRACE_DBG("length %d, buf_len %d, op %p", length, buf_len, op);
|
||||
if (unlikely(length <= 0))
|
||||
goto out_compl;
|
||||
|
||||
if (length >= buf_len) {
|
||||
buf = address;
|
||||
inline_buf = true;
|
||||
} else {
|
||||
buf = vzalloc(buf_len); /* it can be big */
|
||||
if (buf == NULL) {
|
||||
PRINT_ERROR("Unable to allocate REPORT SUPPORTED "
|
||||
"OPERATION CODES buffer with size %d", buf_len);
|
||||
scst_set_busy(cmd);
|
||||
goto out_err_put;
|
||||
}
|
||||
inline_buf = false;
|
||||
}
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
switch(options) {
|
||||
case 0: /* all */
|
||||
put_unaligned_be32(buf_len - 3, &buf[0]);
|
||||
offs = 4;
|
||||
for (i = 0; i < supp_opcodes_cnt; i++) {
|
||||
op = supp_opcodes[i];
|
||||
buf[offs] = op->od_opcode;
|
||||
if (op->od_serv_action_valid) {
|
||||
put_unaligned_be16(op->od_serv_action, &buf[offs + 2]);
|
||||
buf[offs + 5] |= 1;
|
||||
}
|
||||
put_unaligned_be16(op->od_cdb_size, &buf[offs + 6]);
|
||||
offs += 8;
|
||||
if (rctd) {
|
||||
buf[(offs - 8) + 5] |= 2;
|
||||
buf[offs + 1] = 0xA;
|
||||
buf[offs + 3] = op->od_comm_specific_timeout;
|
||||
put_unaligned_be32(op->od_nominal_timeout, &buf[offs + 4]);
|
||||
put_unaligned_be32(op->od_recommended_timeout, &buf[offs + 8]);
|
||||
offs += 12;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
if (op != NULL) {
|
||||
buf[1] |= op->od_support;
|
||||
put_unaligned_be16(op->od_cdb_size, &buf[2]);
|
||||
memcpy(&buf[4], op->od_cdb_usage_bits, op->od_cdb_size);
|
||||
if (rctd) {
|
||||
buf[1] |= 0x80;
|
||||
offs = 4 + op->od_cdb_size;
|
||||
buf[offs + 1] = 0xA;
|
||||
buf[offs + 3] = op->od_comm_specific_timeout;
|
||||
put_unaligned_be32(op->od_nominal_timeout, &buf[offs + 4]);
|
||||
put_unaligned_be32(op->od_recommended_timeout, &buf[offs + 8]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sBUG_ON(1);
|
||||
goto out_compl;
|
||||
}
|
||||
|
||||
if (length > buf_len)
|
||||
length = buf_len;
|
||||
if (!inline_buf) {
|
||||
memcpy(address, buf, length);
|
||||
vfree(buf);
|
||||
}
|
||||
|
||||
scst_put_buf_full(cmd, address);
|
||||
if (length < cmd->resp_data_len)
|
||||
scst_set_resp_data_len(cmd, length);
|
||||
|
||||
out_compl:
|
||||
if ((supp_opcodes != NULL) && (cmd->devt->put_supported_opcodes != NULL))
|
||||
cmd->devt->put_supported_opcodes(cmd, supp_opcodes, supp_opcodes_cnt);
|
||||
|
||||
cmd->completed = 1;
|
||||
|
||||
/* Report the result */
|
||||
cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
|
||||
out_err_put:
|
||||
scst_put_buf_full(cmd, address);
|
||||
goto out_compl;
|
||||
}
|
||||
|
||||
static int scst_maintenance_in(struct scst_cmd *cmd)
|
||||
{
|
||||
int res;
|
||||
@@ -2121,6 +2323,9 @@ static int scst_maintenance_in(struct scst_cmd *cmd)
|
||||
case MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS:
|
||||
res = scst_report_supported_tm_fns(cmd);
|
||||
break;
|
||||
case MI_REPORT_SUPPORTED_OPERATION_CODES:
|
||||
res = scst_report_supported_opcodes(cmd);
|
||||
break;
|
||||
default:
|
||||
res = SCST_EXEC_NOT_COMPLETED;
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user