提交 3a3c5e4a 编写于 作者: R Roland Dreier 提交者: Nicholas Bellinger

target: Add emulation for MODE SELECT

This is another thing that compliance tests try, and it's easy to
implement on top of the MODE SENSE refactoring; since we don't claim
to support any changeable values, all we need to do is check that
the page contents sent by the initiator match what we would return.
Signed-off-by: NRoland Dreier <roland@purestorage.com>
Signed-off-by: NNicholas Bellinger <nab@linux-iscsi.org>
上级 0f6d64ce
...@@ -975,6 +975,57 @@ static int spc_emulate_modesense(struct se_cmd *cmd) ...@@ -975,6 +975,57 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
return 0; return 0;
} }
static int spc_emulate_modeselect(struct se_cmd *cmd)
{
struct se_device *dev = cmd->se_dev;
char *cdb = cmd->t_task_cdb;
bool ten = cdb[0] == MODE_SELECT_10;
int off = ten ? 8 : 4;
bool pf = !!(cdb[1] & 0x10);
u8 page, subpage;
unsigned char *buf;
unsigned char tbuf[SE_MODE_PAGE_BUF];
int length;
int ret = 0;
int i;
buf = transport_kmap_data_sg(cmd);
if (!pf) {
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
ret = -EINVAL;
goto out;
}
page = buf[off] & 0x3f;
subpage = buf[off] & 0x40 ? buf[off + 1] : 0;
for (i = 0; i < ARRAY_SIZE(modesense_handlers); ++i)
if (modesense_handlers[i].page == page &&
modesense_handlers[i].subpage == subpage) {
memset(tbuf, 0, SE_MODE_PAGE_BUF);
length = modesense_handlers[i].emulate(dev, 0, tbuf);
goto check_contents;
}
cmd->scsi_sense_reason = TCM_UNKNOWN_MODE_PAGE;
ret = -EINVAL;
goto out;
check_contents:
if (memcmp(buf + off, tbuf, length)) {
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL;
}
out:
transport_kunmap_data_sg(cmd);
if (!ret)
target_complete_cmd(cmd, GOOD);
return ret;
}
static int spc_emulate_request_sense(struct se_cmd *cmd) static int spc_emulate_request_sense(struct se_cmd *cmd)
{ {
unsigned char *cdb = cmd->t_task_cdb; unsigned char *cdb = cmd->t_task_cdb;
...@@ -1113,9 +1164,11 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) ...@@ -1113,9 +1164,11 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
switch (cdb[0]) { switch (cdb[0]) {
case MODE_SELECT: case MODE_SELECT:
*size = cdb[4]; *size = cdb[4];
cmd->execute_cmd = spc_emulate_modeselect;
break; break;
case MODE_SELECT_10: case MODE_SELECT_10:
*size = (cdb[7] << 8) + cdb[8]; *size = (cdb[7] << 8) + cdb[8];
cmd->execute_cmd = spc_emulate_modeselect;
break; break;
case MODE_SENSE: case MODE_SENSE:
*size = cdb[4]; *size = cdb[4];
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册