summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-10-05 10:55:08 +0000
committermav <mav@FreeBSD.org>2015-10-05 10:55:08 +0000
commit06e368a3c3eab54e7f8d54e297390dd312e437a0 (patch)
tree50ea6913a7b6b9176f3a234dfaf9102235c67183
parent8aeebc57372626ad7a03875fc1d314039d6e759f (diff)
downloadFreeBSD-src-06e368a3c3eab54e7f8d54e297390dd312e437a0.zip
FreeBSD-src-06e368a3c3eab54e7f8d54e297390dd312e437a0.tar.gz
MFC r288165: Add support for READ BUFFER(16) command.
-rw-r--r--sys/cam/ctl/ctl.c47
-rw-r--r--sys/cam/ctl/ctl_cmd_table.c12
-rw-r--r--sys/cam/scsi/scsi_all.h11
3 files changed, 55 insertions, 15 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 6e0ff8e3..de8eeb2 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -5612,20 +5612,43 @@ bailout:
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,
@@ -5636,10 +5659,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,
@@ -5650,12 +5671,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 {
diff --git a/sys/cam/ctl/ctl_cmd_table.c b/sys/cam/ctl/ctl_cmd_table.c
index 7711b31..0753f28 100644
--- a/sys/cam/ctl/ctl_cmd_table.c
+++ b/sys/cam/ctl/ctl_cmd_table.c
@@ -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,
diff --git a/sys/cam/scsi/scsi_all.h b/sys/cam/scsi/scsi_all.h
index 4f1b5b3..e8fd5fe 100644
--- a/sys/cam/scsi/scsi_all.h
+++ b/sys/cam/scsi/scsi_all.h
@@ -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
OpenPOWER on IntegriCloud