Skip to content

Commit

Permalink
target: Add emulation for MODE SELECT
Browse files Browse the repository at this point in the history
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: Roland Dreier <roland@purestorage.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
  • Loading branch information
Roland Dreier authored and Nicholas Bellinger committed Nov 7, 2012
1 parent 0f6d64c commit 3a3c5e4
Showing 1 changed file with 53 additions and 0 deletions.
53 changes: 53 additions & 0 deletions drivers/target/target_core_spc.c
Original file line number Diff line number Diff line change
Expand Up @@ -975,6 +975,57 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
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)
{
unsigned char *cdb = cmd->t_task_cdb;
Expand Down Expand Up @@ -1113,9 +1164,11 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
switch (cdb[0]) {
case MODE_SELECT:
*size = cdb[4];
cmd->execute_cmd = spc_emulate_modeselect;
break;
case MODE_SELECT_10:
*size = (cdb[7] << 8) + cdb[8];
cmd->execute_cmd = spc_emulate_modeselect;
break;
case MODE_SENSE:
*size = cdb[4];
Expand Down

0 comments on commit 3a3c5e4

Please sign in to comment.