Add support for READ BUFFER(16) command.

This commit is contained in:
Alexander Motin 2015-09-24 07:16:34 +00:00
parent 64d6acd5e7
commit de988746be
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=288165
3 changed files with 55 additions and 15 deletions

View File

@ -5610,20 +5610,43 @@ ctl_format(struct ctl_scsiio *ctsio)
int
ctl_read_buffer(struct ctl_scsiio *ctsio)
{
struct scsi_read_buffer *cdb;
struct ctl_lun *lun;
int buffer_offset, len;
uint64_t buffer_offset;
uint32_t len;
uint8_t byte2;
static uint8_t descr[4];
static uint8_t echo_descr[4] = { 0 };
CTL_DEBUG_PRINT(("ctl_read_buffer\n"));
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
cdb = (struct scsi_read_buffer *)ctsio->cdb;
switch (ctsio->cdb[0]) {
case READ_BUFFER: {
struct scsi_read_buffer *cdb;
if ((cdb->byte2 & RWB_MODE) != RWB_MODE_DATA &&
(cdb->byte2 & RWB_MODE) != RWB_MODE_ECHO_DESCR &&
(cdb->byte2 & RWB_MODE) != RWB_MODE_DESCR) {
cdb = (struct scsi_read_buffer *)ctsio->cdb;
buffer_offset = scsi_3btoul(cdb->offset);
len = scsi_3btoul(cdb->length);
byte2 = cdb->byte2;
break;
}
case READ_BUFFER_16: {
struct scsi_read_buffer_16 *cdb;
cdb = (struct scsi_read_buffer_16 *)ctsio->cdb;
buffer_offset = scsi_8btou64(cdb->offset);
len = scsi_4btoul(cdb->length);
byte2 = cdb->byte2;
break;
}
default: /* This shouldn't happen. */
ctl_set_invalid_opcode(ctsio);
ctl_done((union ctl_io *)ctsio);
return (CTL_RETVAL_COMPLETE);
}
if ((byte2 & RWB_MODE) != RWB_MODE_DATA &&
(byte2 & RWB_MODE) != RWB_MODE_ECHO_DESCR &&
(byte2 & RWB_MODE) != RWB_MODE_DESCR) {
ctl_set_invalid_field(ctsio,
/*sks_valid*/ 1,
/*command*/ 1,
@ -5634,10 +5657,8 @@ ctl_read_buffer(struct ctl_scsiio *ctsio)
return (CTL_RETVAL_COMPLETE);
}
len = scsi_3btoul(cdb->length);
buffer_offset = scsi_3btoul(cdb->offset);
if (buffer_offset + len > CTL_WRITE_BUFFER_SIZE) {
if (buffer_offset > CTL_WRITE_BUFFER_SIZE ||
buffer_offset + len > CTL_WRITE_BUFFER_SIZE) {
ctl_set_invalid_field(ctsio,
/*sks_valid*/ 1,
/*command*/ 1,
@ -5648,12 +5669,12 @@ ctl_read_buffer(struct ctl_scsiio *ctsio)
return (CTL_RETVAL_COMPLETE);
}
if ((cdb->byte2 & RWB_MODE) == RWB_MODE_DESCR) {
if ((byte2 & RWB_MODE) == RWB_MODE_DESCR) {
descr[0] = 0;
scsi_ulto3b(CTL_WRITE_BUFFER_SIZE, &descr[1]);
ctsio->kern_data_ptr = descr;
len = min(len, sizeof(descr));
} else if ((cdb->byte2 & RWB_MODE) == RWB_MODE_ECHO_DESCR) {
} else if ((byte2 & RWB_MODE) == RWB_MODE_ECHO_DESCR) {
ctsio->kern_data_ptr = echo_descr;
len = min(len, sizeof(echo_descr));
} else {

View File

@ -1155,8 +1155,16 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
/* 9A */
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
/* 9B */
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
/* 9B READ BUFFER(16) */
{ctl_read_buffer, CTL_SERIDX_MD_SNS, CTL_CMD_FLAG_OK_ON_BOTH |
CTL_CMD_FLAG_OK_ON_STOPPED |
CTL_CMD_FLAG_OK_ON_INOPERABLE |
CTL_CMD_FLAG_OK_ON_STANDBY |
CTL_FLAG_DATA_IN |
CTL_CMD_FLAG_ALLOW_ON_PR_WRESV,
CTL_LUN_PAT_NONE,
10, {0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}},
/* 9C WRITE ATOMIC (16) */
{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN| CTL_FLAG_DATA_OUT,

View File

@ -1002,6 +1002,16 @@ struct scsi_read_buffer
u_int8_t control;
};
struct scsi_read_buffer_16
{
uint8_t opcode;
uint8_t byte2;
uint8_t offset[8];
uint8_t length[4];
uint8_t buffer_id;
uint8_t control;
};
struct scsi_write_buffer
{
u_int8_t opcode;
@ -1988,6 +1998,7 @@ struct ata_pass_16 {
#define VERIFY_16 0x8F
#define SYNCHRONIZE_CACHE_16 0x91
#define WRITE_SAME_16 0x93
#define READ_BUFFER_16 0x9B
#define WRITE_ATOMIC_16 0x9C
#define SERVICE_ACTION_IN 0x9E
#define REPORT_LUNS 0xA0