- Cleanups and improvements in handling various special commands properties

- REQUEST SENSE handling improved
 - READ CAPACITY(16) handling improved
 - New write_medium member added to scst_user's scst_user_scsi_cmd_reply_parse
 - scst_user docs updated
 - Other minot cleanups



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@816 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2009-05-01 19:26:10 +00:00
parent 19ab352393
commit 9f2f2e7bd1
19 changed files with 313 additions and 123 deletions

View File

@@ -785,6 +785,7 @@ struct scst_user_scsi_cmd_reply_parse
{
uint8_t queue_type;
uint8_t data_direction;
uint8_t write_medium;
int32_t data_len;
int32_t bufflen;
},
@@ -795,6 +796,9 @@ where:
- data_direction - command's data flow direction, one of SCST_DATA_* constants
- write_medium - true, if command writes data to medium, so should be
forbidden for read-only devices, false otherwise
- data_len - command's data length
- bufflen - command's buffer length

View File

@@ -477,12 +477,17 @@ typedef enum dma_data_direction scst_data_direction;
enum scst_cdb_flags {
/* SCST_TRANSFER_LEN_TYPE_FIXED must be equiv 1 (FIXED_BIT in cdb) */
SCST_TRANSFER_LEN_TYPE_FIXED = 0x01,
SCST_SMALL_TIMEOUT = 0x02,
SCST_LONG_TIMEOUT = 0x04,
SCST_UNKNOWN_LENGTH = 0x08,
SCST_INFO_INVALID = 0x10,
SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED = 0x20,
SCST_TRANSFER_LEN_TYPE_FIXED = 0x001,
SCST_SMALL_TIMEOUT = 0x002,
SCST_LONG_TIMEOUT = 0x004,
SCST_UNKNOWN_LENGTH = 0x008,
SCST_INFO_NOT_FOUND = 0x010, /* must be single bit */
SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED = 0x020,
SCST_IMPLICIT_HQ = 0x040,
SCST_SKIP_UA = 0x080,
SCST_WRITE_MEDIUM = 0x100,
SCST_LOCAL_CMD = 0x200,
SCST_LOCAL_EXEC_NEEDED = 0x400,
};
/*
@@ -1605,6 +1610,13 @@ struct scst_tgt_dev {
/* internal tmp list entry */
struct list_head extra_tgt_dev_list_entry;
/*
* Stored Unit Attention sense and its length for possible
* subsequent RQUEST SENSE. Both protected by tgt_dev_lock.
*/
unsigned short tgt_dev_valid_sense_len;
uint8_t tgt_dev_sense[SCST_SENSE_BUFFERSIZE];
};
/*
@@ -2051,14 +2063,9 @@ enum dma_data_direction scst_to_tgt_dma_dir(int scst_dir);
* Returns 1, if cmd's CDB is locally handled by SCST and 0 otherwise.
* Dev handlers parse() and dev_done() not called for such commands.
*/
static inline int scst_is_cmd_local(struct scst_cmd *cmd)
static inline bool scst_is_cmd_local(struct scst_cmd *cmd)
{
int res = 0;
switch (cmd->cdb[0]) {
case REPORT_LUNS:
res = 1;
}
return res;
return (cmd->op_flags & SCST_LOCAL_CMD) != 0;
}
/*

View File

@@ -295,7 +295,7 @@ static inline int scst_is_ua_sense(const uint8_t *sense)
*************************************************************/
#define SCST_SENSE_ASC_UA_RESET 0x29
#define READ_CAP_LEN 8
#define READ_CAP16_LEN 12
#define READ_CAP16_LEN 32
#define BYTCHK 0x02
#define POSITION_LEN_SHORT 20
#define POSITION_LEN_LONG 32

View File

@@ -206,6 +206,7 @@ struct scst_user_get_cmd {
struct scst_user_scsi_cmd_reply_parse {
uint8_t queue_type;
uint8_t data_direction;
uint8_t write_medium;
int32_t data_len;
int32_t bufflen;
};

View File

@@ -75,7 +75,7 @@ static int cdrom_attach(struct scst_device *dev)
TRACE_ENTRY();
if (dev->scsi_dev == NULL ||
dev->scsi_dev->type != dev->handler->type) {
dev->scsi_dev->type != dev->type) {
PRINT_ERROR("%s", "SCSI device not define or illegal type");
res = -ENODEV;
goto out;

View File

@@ -65,7 +65,7 @@ static int changer_attach(struct scst_device *dev)
TRACE_ENTRY();
if (dev->scsi_dev == NULL ||
dev->scsi_dev->type != dev->handler->type) {
dev->scsi_dev->type != dev->type) {
PRINT_ERROR("%s", "SCSI device not define or illegal type");
res = -ENODEV;
goto out;

View File

@@ -151,7 +151,7 @@ static int disk_attach(struct scst_device *dev)
TRACE_ENTRY();
if (dev->scsi_dev == NULL ||
dev->scsi_dev->type != dev->handler->type) {
dev->scsi_dev->type != dev->type) {
PRINT_ERROR("%s", "SCSI device not define or illegal type");
res = -ENODEV;
goto out;

View File

@@ -151,7 +151,7 @@ static int modisk_attach(struct scst_device *dev)
TRACE_ENTRY();
if (dev->scsi_dev == NULL ||
dev->scsi_dev->type != dev->handler->type) {
dev->scsi_dev->type != dev->type) {
PRINT_ERROR("%s", "SCSI device not define or illegal type");
res = -ENODEV;
goto out;

View File

@@ -65,7 +65,7 @@ static int processor_attach(struct scst_device *dev)
TRACE_ENTRY();
if (dev->scsi_dev == NULL ||
dev->scsi_dev->type != dev->handler->type) {
dev->scsi_dev->type != dev->type) {
PRINT_ERROR("%s", "SCSI device not define or illegal type");
res = -ENODEV;
goto out;

View File

@@ -65,7 +65,7 @@ static int raid_attach(struct scst_device *dev)
TRACE_ENTRY();
if (dev->scsi_dev == NULL ||
dev->scsi_dev->type != dev->handler->type) {
dev->scsi_dev->type != dev->type) {
PRINT_ERROR("%s", "SCSI device not define or illegal type");
res = -ENODEV;
goto out;

View File

@@ -154,7 +154,7 @@ static int tape_attach(struct scst_device *dev)
TRACE_ENTRY();
if (dev->scsi_dev == NULL ||
dev->scsi_dev->type != dev->handler->type) {
dev->scsi_dev->type != dev->type) {
PRINT_ERROR("%s", "SCSI device not define or illegal type");
res = -ENODEV;
goto out;

View File

@@ -760,14 +760,14 @@ static int dev_user_parse(struct scst_cmd *cmd)
case SCST_USER_PARSE_STANDARD:
TRACE_DBG("PARSE STANDARD: ucmd %p", ucmd);
rc = dev->generic_parse(cmd, dev_user_get_block);
if ((rc != 0) || (cmd->op_flags & SCST_INFO_INVALID))
if ((rc != 0) || (cmd->op_flags & SCST_INFO_NOT_FOUND))
goto out_invalid;
break;
case SCST_USER_PARSE_EXCEPTION:
TRACE_DBG("PARSE EXCEPTION: ucmd %p", ucmd);
rc = dev->generic_parse(cmd, dev_user_get_block);
if ((rc == 0) && (!(cmd->op_flags & SCST_INFO_INVALID)))
if ((rc == 0) && (!(cmd->op_flags & SCST_INFO_NOT_FOUND)))
break;
else if (rc == SCST_CMD_STATE_NEED_THREAD_CTX) {
TRACE_MEM("Restarting PARSE to thread context "
@@ -828,8 +828,7 @@ out:
return res;
out_invalid:
PRINT_ERROR("PARSE failed (ucmd %p, rc %d, invalid %d)", ucmd, rc,
cmd->op_flags & SCST_INFO_INVALID);
PRINT_ERROR("PARSE failed (ucmd %p, rc %d)", ucmd, rc);
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_invalid_opcode));
out_error:
@@ -1249,6 +1248,8 @@ static int dev_user_process_reply_parse(struct scst_user_cmd *ucmd,
cmd->data_direction = preply->data_direction;
cmd->bufflen = preply->bufflen;
cmd->data_len = preply->data_len;
if (preply->write_medium)
cmd->op_flags |= SCST_WRITE_MEDIUM;
out_process:
scst_process_active_cmd(cmd, false);

View File

@@ -507,7 +507,7 @@ static int vdisk_attach(struct scst_device *dev)
goto out;
}
vd = (dev->handler->type == TYPE_DISK) ?
vd = (dev->type == TYPE_DISK) ?
&vdisk_dev_list :
&vcdrom_dev_list;
@@ -530,7 +530,7 @@ static int vdisk_attach(struct scst_device *dev)
virt_dev->dev = dev;
if (dev->handler->type == TYPE_ROM)
if (dev->type == TYPE_ROM)
virt_dev->rd_only_flag = 1;
if (!virt_dev->cdrom_empty) {
@@ -547,7 +547,7 @@ static int vdisk_attach(struct scst_device *dev)
} else
virt_dev->file_size = 0;
if (dev->handler->type == TYPE_DISK) {
if (dev->type == TYPE_DISK) {
virt_dev->nblocks =
virt_dev->file_size >> virt_dev->block_shift;
} else {
@@ -561,7 +561,7 @@ static int vdisk_attach(struct scst_device *dev)
PRINT_INFO("Attached SCSI target virtual %s %s "
"(file=\"%s\", fs=%lldMB, bs=%d, nblocks=%lld,"
" cyln=%lld%s)",
(dev->handler->type == TYPE_DISK) ? "disk" : "cdrom",
(dev->type == TYPE_DISK) ? "disk" : "cdrom",
virt_dev->name, virt_dev->file_name,
virt_dev->file_size >> 20, virt_dev->block_size,
(long long unsigned int)virt_dev->nblocks,
@@ -1209,7 +1209,7 @@ static void vdisk_exec_inquiry(struct scst_cmd *cmd)
goto out_put;
}
buf[0] = cmd->dev->handler->type; /* type dev */
buf[0] = cmd->dev->type; /* type dev */
if ((buf[0] == TYPE_ROM) || virt_dev->removable)
buf[1] = 0x80; /* removable */
/* Vital Product */
@@ -1548,7 +1548,7 @@ static void vdisk_exec_mode_sense(struct scst_cmd *cmd)
blocksize = virt_dev->block_size;
nblocks = virt_dev->nblocks;
type = cmd->dev->handler->type; /* type dev */
type = cmd->dev->type; /* type dev */
dbd = cmd->cdb[1] & DBD;
pcontrol = (cmd->cdb[2] & 0xc0) >> 6;
pcode = cmd->cdb[2] & 0x3f;
@@ -1904,6 +1904,7 @@ static void vdisk_exec_read_capacity16(struct scst_cmd *cmd)
nblocks = virt_dev->nblocks - 1;
memset(buffer, 0, sizeof(buffer));
buffer[0] = nblocks >> 56;
buffer[1] = (nblocks >> 48) & 0xFF;
buffer[2] = (nblocks >> 40) & 0xFF;
@@ -1918,6 +1919,25 @@ static void vdisk_exec_read_capacity16(struct scst_cmd *cmd)
buffer[10] = (blocksize >> (BYTE * 1)) & 0xFF;
buffer[11] = (blocksize >> (BYTE * 0)) & 0xFF;
switch (blocksize) {
case 512:
buffer[13] = 3;
break;
case 1024:
buffer[13] = 2;
break;
case 2048:
buffer[13] = 1;
break;
default:
PRINT_ERROR("%s: Unexpected block size %d",
cmd->op_name, blocksize);
/* go through */
case 4096:
buffer[13] = 0;
break;
}
length = scst_get_buf_first(cmd, &address);
if (unlikely(length <= 0)) {
if (length < 0) {
@@ -1953,7 +1973,7 @@ static void vdisk_exec_read_toc(struct scst_cmd *cmd)
TRACE_ENTRY();
if (cmd->dev->handler->type != TYPE_ROM) {
if (cmd->dev->type != TYPE_ROM) {
PRINT_ERROR("%s", "READ TOC for non-CDROM device");
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_opcode));
@@ -2040,7 +2060,7 @@ static void vdisk_exec_prevent_allow_medium_removal(struct scst_cmd *cmd)
TRACE_DBG("PERSIST/PREVENT 0x%02x", cmd->cdb[4]);
if (cmd->dev->handler->type == TYPE_ROM) {
if (cmd->dev->type == TYPE_ROM) {
spin_lock(&virt_dev->flags_lock);
virt_dev->prevent_allow_medium_removal =
cmd->cdb[4] & 0x01 ? 1 : 0;

View File

@@ -31,6 +31,7 @@ static int get_trans_len_4(struct scst_cmd *cmd, uint8_t off);
/* for special commands */
static int get_trans_len_block_limit(struct scst_cmd *cmd, uint8_t off);
static int get_trans_len_read_capacity(struct scst_cmd *cmd, uint8_t off);
static int get_trans_len_serv_act_in(struct scst_cmd *cmd, uint8_t off);
static int get_trans_len_single(struct scst_cmd *cmd, uint8_t off);
static int get_trans_len_none(struct scst_cmd *cmd, uint8_t off);
static int get_trans_len_read_pos(struct scst_cmd *cmd, uint8_t off);
@@ -80,7 +81,7 @@ struct scst_sdbops {
uint8_t direction; /* init --> target: SCST_DATA_WRITE
* target --> init: SCST_DATA_READ
*/
uint8_t flags; /* opcode -- various flags */
uint16_t flags; /* opcode -- various flags */
uint8_t off; /* length offset in cdb */
int (*get_trans_len)(struct scst_cmd *cmd, uint8_t off)
__attribute__ ((aligned));
@@ -111,7 +112,8 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
/* 6-bytes length CDB */
{0x00, "MMMMMMMMMMMMMMMM", "TEST UNIT READY",
SCST_DATA_NONE, SCST_SMALL_TIMEOUT, 0, get_trans_len_none},
/* let's be HQ to don't look dead under high load */
SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_IMPLICIT_HQ, 0, get_trans_len_none},
{0x01, " M ", "REWIND",
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
{0x01, "O V OO OO ", "REZERO UNIT",
@@ -119,12 +121,13 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
{0x02, "VVVVVV V ", "REQUEST BLOCK ADDR",
SCST_DATA_NONE, SCST_SMALL_TIMEOUT, 0, get_trans_len_none},
{0x03, "MMMMMMMMMMMMMMMM", "REQUEST SENSE",
SCST_DATA_READ, SCST_SMALL_TIMEOUT, 4, get_trans_len_1},
SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_SKIP_UA|SCST_LOCAL_EXEC_NEEDED,
4, get_trans_len_1},
{0x04, "M O O ", "FORMAT UNIT",
SCST_DATA_WRITE, SCST_LONG_TIMEOUT|SCST_UNKNOWN_LENGTH,
SCST_DATA_WRITE, SCST_LONG_TIMEOUT|SCST_UNKNOWN_LENGTH|SCST_WRITE_MEDIUM,
0, get_trans_len_none},
{0x04, " O ", "FORMAT",
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
{0x05, "VMVVVV V ", "READ BLOCK LIMITS",
SCST_DATA_READ, SCST_SMALL_TIMEOUT, 0, get_trans_len_block_limit},
{0x06, "VVVVVV V ", "",
@@ -132,7 +135,7 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
{0x07, " O ", "INITIALIZE ELEMENT STATUS",
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
{0x07, "OVV O OV ", "REASSIGN BLOCKS",
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
{0x08, "O ", "READ(6)",
SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 4, get_trans_len_1_256},
{0x08, " MV OO OV ", "READ(6)",
@@ -144,9 +147,11 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
{0x09, "VVVVVV V ", "",
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
{0x0A, "O ", "WRITE(6)",
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 4, get_trans_len_1_256},
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
4, get_trans_len_1_256},
{0x0A, " M O OV ", "WRITE(6)",
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 2, get_trans_len_3},
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
2, get_trans_len_3},
{0x0A, " M ", "PRINT",
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
{0x0A, " M ", "SEND MESSAGE(6)",
@@ -162,19 +167,21 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
{0x0C, "VVVVVV V ", "SEEK BLOCK",
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
{0x0D, "VVVVVV V ", "PARTITION",
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
SCST_DATA_NONE, SCST_LONG_TIMEOUT|SCST_WRITE_MEDIUM,
0, get_trans_len_none},
{0x0E, "VVVVVV V ", "",
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
{0x0F, "VOVVVV V ", "READ REVERSE",
SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 2, get_trans_len_3},
{0x10, "VM V V ", "WRITE FILEMARKS",
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
{0x10, " O O ", "SYNCHRONIZE BUFFER",
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
{0x11, "VMVVVV ", "SPACE",
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
{0x12, "MMMMMMMMMMMMMMMM", "INQUIRY",
SCST_DATA_READ, SCST_SMALL_TIMEOUT, 4, get_trans_len_1},
SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_IMPLICIT_HQ|SCST_SKIP_UA,
4, get_trans_len_1},
{0x13, "VOVVVV ", "VERIFY(6)",
SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED|
SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED,
@@ -182,15 +189,18 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
{0x14, "VOOVVV ", "RECOVER BUFFERED DATA",
SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 2, get_trans_len_3},
{0x15, "OMOOOOOOOOOOOOOO", "MODE SELECT(6)",
SCST_DATA_WRITE, FLAG_NONE, 4, get_trans_len_1},
SCST_DATA_WRITE, SCST_LOCAL_EXEC_NEEDED, 4, get_trans_len_1},
{0x16, "MMMMMMMMMMMMMMMM", "RESERVE",
SCST_DATA_NONE, SCST_SMALL_TIMEOUT, 0, get_trans_len_none},
SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_EXEC_NEEDED,
0, get_trans_len_none},
{0x17, "MMMMMMMMMMMMMMMM", "RELEASE",
SCST_DATA_NONE, SCST_SMALL_TIMEOUT, 0, get_trans_len_none},
SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_EXEC_NEEDED,
0, get_trans_len_none},
{0x18, "OOOOOOOO ", "COPY",
SCST_DATA_WRITE, SCST_LONG_TIMEOUT, 2, get_trans_len_3},
{0x19, "VMVVVV ", "ERASE",
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
SCST_DATA_NONE, SCST_LONG_TIMEOUT|SCST_WRITE_MEDIUM,
0, get_trans_len_none},
{0x1A, "OMOOOOOOOOOOOOOO", "MODE SENSE(6)",
SCST_DATA_READ, SCST_SMALL_TIMEOUT, 4, get_trans_len_1},
{0x1B, " O ", "SCAN",
@@ -222,7 +232,7 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
{0x24, "V VVM ", "SET WINDOW",
SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_3},
{0x25, "M MM M ", "READ CAPACITY",
SCST_DATA_READ, FLAG_NONE, 0, get_trans_len_read_capacity},
SCST_DATA_READ, SCST_IMPLICIT_HQ, 0, get_trans_len_read_capacity},
{0x25, " O ", "GET WINDOW",
SCST_DATA_READ, FLAG_NONE, 6, get_trans_len_3},
{0x26, "V VV ", "",
@@ -236,7 +246,8 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
{0x29, "V VV O ", "READ GENERATION",
SCST_DATA_READ, FLAG_NONE, 8, get_trans_len_1},
{0x2A, "O MO M ", "WRITE(10)",
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 7, get_trans_len_2},
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
7, get_trans_len_2},
{0x2A, " O ", "SEND MESSAGE(10)",
SCST_DATA_WRITE, FLAG_NONE, 7, get_trans_len_2},
{0x2A, " O ", "SEND(10)",
@@ -248,11 +259,13 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
{0x2B, "O OO O ", "SEEK(10)",
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
{0x2C, "V O O ", "ERASE(10)",
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
SCST_DATA_NONE, SCST_LONG_TIMEOUT|SCST_WRITE_MEDIUM,
0, get_trans_len_none},
{0x2D, "V O O ", "READ UPDATED BLOCK",
SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 0, get_trans_len_single},
{0x2E, "O OO O ", "WRITE AND VERIFY(10)",
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 7, get_trans_len_2},
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
7, get_trans_len_2},
{0x2F, "O OO O ", "VERIFY(10)",
SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED|
SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED,
@@ -287,11 +300,11 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
{0x3E, "O OO O ", "READ LONG",
SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
{0x3F, "O O O ", "WRITE LONG",
SCST_DATA_WRITE, FLAG_NONE, 7, get_trans_len_2},
SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 7, get_trans_len_2},
{0x40, "OOOOOOOOOO ", "CHANGE DEFINITION",
SCST_DATA_WRITE, SCST_SMALL_TIMEOUT, 8, get_trans_len_1},
{0x41, "O O ", "WRITE SAME",
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED,
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
0, get_trans_len_single},
{0x42, " O ", "READ SUB-CHANNEL",
SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
@@ -324,11 +337,11 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
{0x4F, " ", "",
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
{0x50, " ", "XDWRITE",
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
{0x51, " O ", "READ DISC INFORMATION",
SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
{0x51, " ", "XPWRITE",
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
{0x52, " O ", "READ TRACK INFORMATION",
SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
{0x53, " O ", "RESERVE TRACK",
@@ -336,13 +349,15 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
{0x54, " O ", "SEND OPC INFORMATION",
SCST_DATA_WRITE, FLAG_NONE, 7, get_trans_len_2},
{0x55, "OOOOOOOOOOOOOOOO", "MODE SELECT(10)",
SCST_DATA_WRITE, FLAG_NONE, 7, get_trans_len_2},
SCST_DATA_WRITE, SCST_LOCAL_EXEC_NEEDED, 7, get_trans_len_2},
{0x56, "OOOOOOOOOOOOOOOO", "RESERVE(10)",
SCST_DATA_NONE, SCST_SMALL_TIMEOUT, 0, get_trans_len_none},
SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_EXEC_NEEDED,
0, get_trans_len_none},
{0x57, "OOOOOOOOOOOOOOOO", "RELEASE(10)",
SCST_DATA_NONE, SCST_SMALL_TIMEOUT, 0, get_trans_len_none},
SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_EXEC_NEEDED,
0, get_trans_len_none},
{0x58, " O ", "REPAIR TRACK",
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
{0x59, " ", "",
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
{0x5A, "OOOOOOOOOOOOOOOO", "MODE SENSE(10)",
@@ -353,22 +368,22 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
{0x5D, " O ", "SEND CUE SHEET",
SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_3},
{0x5E, "OOOOO OOOO ", "PERSISTENT_RESERV_IN",
{0x5E, "OOOOO OOOO ", "PERSISTENT RESERV IN",
SCST_DATA_READ, FLAG_NONE, 5, get_trans_len_4},
{0x5F, "OOOOO OOOO ", "PERSISTENT_RESERV_OUT",
{0x5F, "OOOOO OOOO ", "PERSISTENT RESERV OUT",
SCST_DATA_WRITE, FLAG_NONE, 5, get_trans_len_4},
/* 16-bytes length CDB */
{0x80, "O OO O ", "XDWRITE EXTENDED",
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
{0x80, " M ", "WRITE FILEMARKS",
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
{0x81, "O OO O ", "REBUILD",
SCST_DATA_WRITE, FLAG_NONE, 10, get_trans_len_4},
SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 10, get_trans_len_4},
{0x82, "O OO O ", "REGENERATE",
SCST_DATA_WRITE, FLAG_NONE, 10, get_trans_len_4},
SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 10, get_trans_len_4},
{0x83, "OOOOOOOOOOOOOOOO", "EXTENDED COPY",
SCST_DATA_WRITE, FLAG_NONE, 10, get_trans_len_4},
SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 10, get_trans_len_4},
{0x84, "OOOOOOOOOOOOOOOO", "RECEIVE COPY RESULT",
SCST_DATA_WRITE, FLAG_NONE, 10, get_trans_len_4},
{0x86, "OOOOOOOOOO ", "ACCESS CONTROL IN",
@@ -378,13 +393,15 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
{0x88, "M MMMM ", "READ(16)",
SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 10, get_trans_len_4},
{0x8A, "O OO O ", "WRITE(16)",
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 10, get_trans_len_4},
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
10, get_trans_len_4},
{0x8C, "OOOOOOOOOO ", "READ ATTRIBUTE",
SCST_DATA_READ, FLAG_NONE, 10, get_trans_len_4},
{0x8D, "OOOOOOOOOO ", "WRITE ATTRIBUTE",
SCST_DATA_WRITE, FLAG_NONE, 10, get_trans_len_4},
SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 10, get_trans_len_4},
{0x8E, "O OO O ", "WRITE AND VERIFY(16)",
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 10, get_trans_len_4},
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
10, get_trans_len_4},
{0x8F, "O OO O ", "VERIFY(16)",
SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED|
SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED,
@@ -400,15 +417,19 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
{0x92, " O ", "LOCATE(16)",
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
{0x93, "O O ", "WRITE SAME(16)",
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 10, get_trans_len_4},
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
10, get_trans_len_4},
{0x93, " M ", "ERASE(16)",
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
SCST_DATA_NONE, SCST_LONG_TIMEOUT|SCST_WRITE_MEDIUM,
0, get_trans_len_none},
{0x9E, "O ", "SERVICE ACTION IN",
SCST_DATA_READ, SCST_UNKNOWN_LENGTH, 0, get_trans_len_none},
SCST_DATA_READ, FLAG_NONE, 0, get_trans_len_serv_act_in},
/* 12-bytes length CDB */
{0xA0, "VVVVVVVVVV M ", "REPORT LUN",
SCST_DATA_READ, SCST_SMALL_TIMEOUT, 6, get_trans_len_4},
{0xA0, "VVVVVVVVVV M ", "REPORT LUNS",
SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_IMPLICIT_HQ|SCST_SKIP_UA|
SCST_LOCAL_CMD|SCST_LOCAL_EXEC_NEEDED,
6, get_trans_len_4},
{0xA1, " O ", "BLANK",
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
{0xA2, " ", "",
@@ -438,19 +459,21 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
{0xA9, " O ", "PLAY TRACK RELATIVE(12)",
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
{0xAA, "O OO O ", "WRITE(12)",
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 6, get_trans_len_4},
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
6, get_trans_len_4},
{0xAA, " O ", "SEND MESSAGE(12)",
SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_4},
{0xAB, " ", "",
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
{0xAC, " O ", "ERASE(12)",
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
{0xAC, " M ", "GET PERFORMANCE",
SCST_DATA_READ, SCST_UNKNOWN_LENGTH, 0, get_trans_len_none},
{0xAD, " O ", "READ DVD STRUCTURE",
SCST_DATA_READ, FLAG_NONE, 8, get_trans_len_2},
{0xAE, "O OO O ", "WRITE AND VERIFY(12)",
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 6, get_trans_len_4},
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
6, get_trans_len_4},
{0xAF, "O OO O ", "VERIFY(12)",
SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED|
SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED,
@@ -505,14 +528,6 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none}
};
/* Notes:
Unknown op's:
#define SCSIOP_XDWRITE_EXTENDED 0x80
#define SCSIOP_REBUILD 0x81
#define SCSIOP_EA 0xea
#define WRITE_LONG_2 0xea
*/
#define SCST_CDB_TBL_SIZE \
((int)(sizeof(scst_scsi_op_table)/sizeof(struct scst_sdbops)))

View File

@@ -2487,6 +2487,23 @@ static int get_trans_len_read_capacity(struct scst_cmd *cmd, uint8_t off)
return 0;
}
static int get_trans_len_serv_act_in(struct scst_cmd *cmd, uint8_t off)
{
int res = 0;
TRACE_ENTRY();
if ((cmd->cdb[1] & 0x1f) == SAI_READ_CAPACITY_16) {
cmd->op_name = "READ CAPACITY(16)";
cmd->bufflen = READ_CAP16_LEN;
cmd->op_flags |= SCST_IMPLICIT_HQ;
} else
cmd->op_flags |= SCST_UNKNOWN_LENGTH;
TRACE_EXIT_RES(res);
return res;
}
static int get_trans_len_single(struct scst_cmd *cmd, uint8_t off)
{
cmd->bufflen = 1;
@@ -2600,7 +2617,7 @@ static int get_trans_len_none(struct scst_cmd *cmd, uint8_t off)
int scst_get_cdb_info(struct scst_cmd *cmd)
{
int dev_type = cmd->dev->handler->type;
int dev_type = cmd->dev->type;
int i, res = 0;
uint8_t op;
const struct scst_sdbops *ptr = NULL;
@@ -2638,12 +2655,12 @@ int scst_get_cdb_info(struct scst_cmd *cmd)
i++;
}
if (ptr == NULL) {
if (unlikely(ptr == NULL)) {
/* opcode not found or now not used !!! */
TRACE(TRACE_SCSI, "Unknown opcode 0x%x for type %d", op,
dev_type);
res = -1;
cmd->op_flags = SCST_INFO_INVALID;
cmd->op_flags = SCST_INFO_NOT_FOUND;
goto out;
}
@@ -2654,7 +2671,7 @@ int scst_get_cdb_info(struct scst_cmd *cmd)
res = (*ptr->get_trans_len)(cmd, ptr->off);
out:
TRACE_EXIT();
TRACE_EXIT_RES(res);
return res;
}
EXPORT_SYMBOL(scst_get_cdb_info);
@@ -2811,12 +2828,6 @@ int scst_sbc_generic_parse(struct scst_cmd *cmd,
cmd->op_name, cmd->data_direction, cmd->op_flags, cmd->bufflen);
switch (cmd->cdb[0]) {
case SERVICE_ACTION_IN:
if ((cmd->cdb[1] & 0x1f) == SAI_READ_CAPACITY_16) {
cmd->bufflen = READ_CAP16_LEN;
cmd->data_direction = SCST_DATA_READ;
}
break;
case VERIFY_6:
case VERIFY:
case VERIFY_12:

View File

@@ -413,23 +413,14 @@ void scst_process_reset(struct scst_device *dev,
struct scst_session *originator, struct scst_cmd *exclude_cmd,
struct scst_mgmt_cmd *mcmd, bool setUA);
static inline int scst_is_ua_command(struct scst_cmd *cmd)
static inline bool scst_is_ua_command(struct scst_cmd *cmd)
{
return (cmd->cdb[0] != INQUIRY) &&
(cmd->cdb[0] != REQUEST_SENSE) &&
(cmd->cdb[0] != REPORT_LUNS);
return (cmd->op_flags & SCST_SKIP_UA) == 0;
}
static inline int scst_is_implicit_hq(struct scst_cmd *cmd)
static inline bool scst_is_implicit_hq(struct scst_cmd *cmd)
{
return (cmd->cdb[0] == INQUIRY) ||
(cmd->cdb[0] == REPORT_LUNS) ||
((cmd->dev->type == TYPE_DISK) &&
((cmd->cdb[0] == READ_CAPACITY) ||
((cmd->cdb[0] == SERVICE_ACTION_IN) &&
((cmd->cdb[1] & 0x1f) == SAI_READ_CAPACITY_16)))) ||
/* Let's don't look dead under high load */
(cmd->cdb[0] == TEST_UNIT_READY);
return (cmd->op_flags & SCST_IMPLICIT_HQ) != 0;
}
/*

View File

@@ -1460,7 +1460,7 @@ static int scst_proc_assign_handler(char *buf)
if (dev->scsi_dev->type != handler->type) {
PRINT_ERROR("Type %d of device %s differs from type "
"%d of dev handler %s", dev->handler->type,
"%d of dev handler %s", dev->type,
dev->handler->name, handler->type, handler->name);
res = -EINVAL;
goto out;

View File

@@ -1440,7 +1440,7 @@ static int scst_report_luns_local(struct scst_cmd *cmd)
if (unlikely(buffer_size == 0))
goto out_compl;
else if (unlikely(buffer_size < 0))
goto out_err;
goto out_hw_err;
if (buffer_size < 16)
goto out_put_err;
@@ -1491,7 +1491,7 @@ inc_dev_cnt:
if (unlikely(buffer_size == 0))
goto out_compl;
else if (unlikely(buffer_size < 0))
goto out_err;
goto out_hw_err;
dev_cnt *= 8;
buffer[0] = (dev_cnt >> 24) & 0xff;
@@ -1557,10 +1557,108 @@ out_err:
out_put_hw_err:
scst_put_buf(cmd, buffer);
out_hw_err:
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
goto out_compl;
}
static int scst_request_sense_local(struct scst_cmd *cmd)
{
int res = SCST_EXEC_COMPLETED, rc;
struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
uint8_t *buffer;
int buffer_size = 0;
TRACE_ENTRY();
rc = scst_check_local_events(cmd);
if (unlikely(rc != 0))
goto out_done;
cmd->status = 0;
cmd->msg_status = 0;
cmd->host_status = DID_OK;
cmd->driver_status = 0;
spin_lock_bh(&tgt_dev->tgt_dev_lock);
if (tgt_dev->tgt_dev_valid_sense_len == 0)
goto out_not_completed;
TRACE(TRACE_SCSI, "%s: Returning stored sense", cmd->op_name);
buffer_size = scst_get_buf_first(cmd, &buffer);
if (unlikely(buffer_size == 0))
goto out_compl;
else if (unlikely(buffer_size < 0))
goto out_hw_err;
memset(buffer, 0, buffer_size);
if (((tgt_dev->tgt_dev_sense[0] == 0x70) ||
(tgt_dev->tgt_dev_sense[0] == 0x71)) && (cmd->cdb[1] & 1)) {
PRINT_WARNING("%s: Fixed format of the saved sense, but "
"descriptor format requested. Convertion will "
"truncated data", cmd->op_name);
PRINT_BUFFER("Original sense", tgt_dev->tgt_dev_sense,
tgt_dev->tgt_dev_valid_sense_len);
buffer_size = min(SCST_STANDARD_SENSE_LEN, buffer_size);
scst_set_sense(buffer, buffer_size, true,
tgt_dev->tgt_dev_sense[2], tgt_dev->tgt_dev_sense[12],
tgt_dev->tgt_dev_sense[13]);
} else if (((tgt_dev->tgt_dev_sense[0] == 0x72) ||
(tgt_dev->tgt_dev_sense[0] == 0x73)) && !(cmd->cdb[1] & 1)) {
PRINT_WARNING("%s: Descriptor format of the "
"saved sense, but fixed format requested. Convertion "
"will truncated data", cmd->op_name);
PRINT_BUFFER("Original sense", tgt_dev->tgt_dev_sense,
tgt_dev->tgt_dev_valid_sense_len);
buffer_size = min(SCST_STANDARD_SENSE_LEN, buffer_size);
scst_set_sense(buffer, buffer_size, false,
tgt_dev->tgt_dev_sense[1], tgt_dev->tgt_dev_sense[2],
tgt_dev->tgt_dev_sense[3]);
} else {
if (buffer_size >= tgt_dev->tgt_dev_valid_sense_len)
buffer_size = tgt_dev->tgt_dev_valid_sense_len;
else {
PRINT_WARNING("%s: Being returned sense truncated to "
"size %d (needed %d)", cmd->op_name,
buffer_size, tgt_dev->tgt_dev_valid_sense_len);
}
memcpy(buffer, tgt_dev->tgt_dev_sense, buffer_size);
}
scst_put_buf(cmd, buffer);
out_compl:
tgt_dev->tgt_dev_valid_sense_len = 0;
scst_set_resp_data_len(cmd, buffer_size);
spin_unlock_bh(&tgt_dev->tgt_dev_lock);
cmd->completed = 1;
out_done:
/* Report the result */
cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
out:
TRACE_EXIT_RES(res);
return res;
out_hw_err:
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
goto out_compl;
out_not_completed:
spin_unlock_bh(&tgt_dev->tgt_dev_lock);
res = SCST_EXEC_NOT_COMPLETED;
goto out;
}
static int scst_pre_select(struct scst_cmd *cmd)
{
int res = SCST_EXEC_NOT_COMPLETED;
@@ -2044,16 +2142,8 @@ static int scst_do_local_exec(struct scst_cmd *cmd)
TRACE_ENTRY();
/* Check READ_ONLY device status */
if (((tgt_dev->acg_dev->rd_only_flag) || cmd->dev->swp) &&
(cmd->cdb[0] == WRITE_6 || /* ToDo: full list of the modify cmds */
cmd->cdb[0] == WRITE_10 ||
cmd->cdb[0] == WRITE_12 ||
cmd->cdb[0] == WRITE_16 ||
cmd->cdb[0] == WRITE_VERIFY ||
cmd->cdb[0] == WRITE_VERIFY_12 ||
cmd->cdb[0] == WRITE_VERIFY_16 ||
(cmd->dev->handler->type == TYPE_TAPE &&
(cmd->cdb[0] == ERASE || cmd->cdb[0] == WRITE_FILEMARKS)))) {
if ((cmd->op_flags & SCST_WRITE_MEDIUM) &&
((tgt_dev->acg_dev->rd_only_flag) || cmd->dev->swp)) {
PRINT_WARNING("Attempt of write access to read-only device: "
"initiator %s, LUN %lld, op %x",
cmd->sess->initiator_name, cmd->lun, cmd->cdb[0]);
@@ -2067,6 +2157,11 @@ static int scst_do_local_exec(struct scst_cmd *cmd)
* scst_is_cmd_local() in scst.h, if necessary
*/
if (!(cmd->op_flags & SCST_LOCAL_EXEC_NEEDED)) {
res = SCST_EXEC_NOT_COMPLETED;
goto out;
}
switch (cmd->cdb[0]) {
case MODE_SELECT:
case MODE_SELECT_10:
@@ -2084,6 +2179,9 @@ static int scst_do_local_exec(struct scst_cmd *cmd)
case REPORT_LUNS:
res = scst_report_luns_local(cmd);
break;
case REQUEST_SENSE:
res = scst_request_sense_local(cmd);
break;
default:
res = SCST_EXEC_NOT_COMPLETED;
break;
@@ -2453,7 +2551,7 @@ static int scst_pre_dev_done(struct scst_cmd *cmd)
goto out;
if (likely(scsi_status_is_good(cmd->status))) {
unsigned char type = cmd->dev->handler->type;
unsigned char type = cmd->dev->type;
if (unlikely((cmd->cdb[0] == MODE_SENSE ||
cmd->cdb[0] == MODE_SENSE_10)) &&
cmd->tgt_dev->acg_dev->rd_only_flag &&
@@ -2824,6 +2922,28 @@ static int scst_pre_xmit_response(struct scst_cmd *cmd)
if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)))
scst_xmit_process_aborted_cmd(cmd);
else if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION) &&
SCST_SENSE_VALID(cmd->sense) &&
!test_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags)) {
struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
TRACE_DBG("Storing sense (cmd %p)", cmd);
spin_lock_bh(&tgt_dev->tgt_dev_lock);
if (cmd->sense_bufflen <= sizeof(tgt_dev->tgt_dev_sense))
tgt_dev->tgt_dev_valid_sense_len = cmd->sense_bufflen;
else {
tgt_dev->tgt_dev_valid_sense_len = sizeof(tgt_dev->tgt_dev_sense);
PRINT_ERROR("Stored sense truncated to size %d "
"(needed %d)", tgt_dev->tgt_dev_valid_sense_len,
cmd->sense_bufflen);
}
memcpy(tgt_dev->tgt_dev_sense, cmd->sense,
tgt_dev->tgt_dev_valid_sense_len);
spin_unlock_bh(&tgt_dev->tgt_dev_lock);
}
if (unlikely(test_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags))) {
TRACE_MGMT_DBG("Flag NO_RESP set for cmd %p (tag %llu),"

View File

@@ -1469,6 +1469,7 @@ static void exec_read_capacity16(struct vdisk_cmd *vcmd)
nblocks = dev->nblocks - 1;
memset(buffer, 0, sizeof(buffer));
buffer[0] = nblocks >> 56;
buffer[1] = (nblocks >> 48) & 0xFF;
buffer[2] = (nblocks >> 40) & 0xFF;
@@ -1483,6 +1484,25 @@ static void exec_read_capacity16(struct vdisk_cmd *vcmd)
buffer[10] = (blocksize >> (BYTE * 1)) & 0xFF;
buffer[11] = (blocksize >> (BYTE * 0)) & 0xFF;
switch (blocksize) {
case 512:
buffer[13] = 3;
break;
case 1024:
buffer[13] = 2;
break;
case 2048:
buffer[13] = 1;
break;
default:
PRINT_ERROR("READ CAPACITY(16): Unexpected block size %d6",
blocksize);
/* go through */
case 4096:
buffer[13] = 0;
break;
}
if (length > READ_CAP16_LEN)
length = READ_CAP16_LEN;
memcpy(address, buffer, length);