summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2014-10-20 08:07:29 +0000
committermav <mav@FreeBSD.org>2014-10-20 08:07:29 +0000
commit7cb7c8f15323a01f3c360bbbb6d9114dd030fb90 (patch)
tree2c5111cb98dbc2984b426498c491d4d59603511a
parent9281ac48318a43e261b255c83184e9f87a0aa0e6 (diff)
downloadFreeBSD-src-7cb7c8f15323a01f3c360bbbb6d9114dd030fb90.zip
FreeBSD-src-7cb7c8f15323a01f3c360bbbb6d9114dd030fb90.tar.gz
MFC r273038: Add support for READ DEFECT DATA (10/12) commands.
SPC-4 r2 allows to return empty defect list if the list is not supported. We don't reallu support defect data lists, but this suppresses some errors.
-rw-r--r--sys/cam/ctl/ctl.c83
-rw-r--r--sys/cam/ctl/ctl_cmd_table.c12
-rw-r--r--sys/cam/ctl/ctl_private.h1
-rw-r--r--sys/cam/scsi/scsi_da.h45
4 files changed, 107 insertions, 34 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 6ebf426..6c4eba6 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -7391,6 +7391,89 @@ ctl_read_capacity_16(struct ctl_scsiio *ctsio)
}
int
+ctl_read_defect(struct ctl_scsiio *ctsio)
+{
+ struct scsi_read_defect_data_10 *ccb10;
+ struct scsi_read_defect_data_12 *ccb12;
+ struct scsi_read_defect_data_hdr_10 *data10;
+ struct scsi_read_defect_data_hdr_12 *data12;
+ struct ctl_lun *lun;
+ uint32_t alloc_len, data_len;
+ uint8_t format;
+
+ CTL_DEBUG_PRINT(("ctl_read_defect\n"));
+
+ lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
+ if (lun->flags & CTL_LUN_PR_RESERVED) {
+ uint32_t residx;
+
+ /*
+ * XXX KDM need a lock here.
+ */
+ residx = ctl_get_resindex(&ctsio->io_hdr.nexus);
+ if ((lun->res_type == SPR_TYPE_EX_AC
+ && residx != lun->pr_res_idx)
+ || ((lun->res_type == SPR_TYPE_EX_AC_RO
+ || lun->res_type == SPR_TYPE_EX_AC_AR)
+ && lun->pr_keys[residx] == 0)) {
+ ctl_set_reservation_conflict(ctsio);
+ ctl_done((union ctl_io *)ctsio);
+ return (CTL_RETVAL_COMPLETE);
+ }
+ }
+
+ if (ctsio->cdb[0] == READ_DEFECT_DATA_10) {
+ ccb10 = (struct scsi_read_defect_data_10 *)&ctsio->cdb;
+ format = ccb10->format;
+ alloc_len = scsi_2btoul(ccb10->alloc_length);
+ data_len = sizeof(*data10);
+ } else {
+ ccb12 = (struct scsi_read_defect_data_12 *)&ctsio->cdb;
+ format = ccb12->format;
+ alloc_len = scsi_4btoul(ccb12->alloc_length);
+ data_len = sizeof(*data12);
+ }
+ if (alloc_len == 0) {
+ ctl_set_success(ctsio);
+ ctl_done((union ctl_io *)ctsio);
+ return (CTL_RETVAL_COMPLETE);
+ }
+
+ ctsio->kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
+ if (data_len < alloc_len) {
+ ctsio->residual = alloc_len - data_len;
+ ctsio->kern_data_len = data_len;
+ ctsio->kern_total_len = data_len;
+ } else {
+ ctsio->residual = 0;
+ ctsio->kern_data_len = alloc_len;
+ ctsio->kern_total_len = alloc_len;
+ }
+ ctsio->kern_data_resid = 0;
+ ctsio->kern_rel_offset = 0;
+ ctsio->kern_sg_entries = 0;
+
+ if (ctsio->cdb[0] == READ_DEFECT_DATA_10) {
+ data10 = (struct scsi_read_defect_data_hdr_10 *)
+ ctsio->kern_data_ptr;
+ data10->format = format;
+ scsi_ulto2b(0, data10->length);
+ } else {
+ data12 = (struct scsi_read_defect_data_hdr_12 *)
+ ctsio->kern_data_ptr;
+ data12->format = format;
+ scsi_ulto2b(0, data12->generation);
+ scsi_ulto4b(0, data12->length);
+ }
+
+ ctsio->scsi_status = SCSI_STATUS_OK;
+ ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
+ ctsio->be_move_done = ctl_config_move_done;
+ ctl_datamove((union ctl_io *)ctsio);
+ return (CTL_RETVAL_COMPLETE);
+}
+
+int
ctl_report_tagret_port_groups(struct ctl_scsiio *ctsio)
{
struct scsi_maintenance_in *cdb;
diff --git a/sys/cam/ctl/ctl_cmd_table.c b/sys/cam/ctl/ctl_cmd_table.c
index f109300..c1c1673 100644
--- a/sys/cam/ctl/ctl_cmd_table.c
+++ b/sys/cam/ctl/ctl_cmd_table.c
@@ -768,7 +768,11 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
/* 37 READ DEFECT DATA(10) */
-{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
+{ctl_read_defect, CTL_SERIDX_MD_SNS, CTL_CMD_FLAG_OK_ON_SLUN |
+ CTL_FLAG_DATA_IN |
+ CTL_CMD_FLAG_ALLOW_ON_PR_RESV,
+ CTL_LUN_PAT_NONE,
+ 10, {0, 0x1f, 0, 0, 0, 0, 0xff, 0xff, 0x07}},
/* 38 MEDIUM SCAN */
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
@@ -1247,7 +1251,11 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
/* B7 READ DEFECT DATA(12) */
-{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
+{ctl_read_defect, CTL_SERIDX_MD_SNS, CTL_CMD_FLAG_OK_ON_SLUN |
+ CTL_FLAG_DATA_IN |
+ CTL_CMD_FLAG_ALLOW_ON_PR_RESV,
+ CTL_LUN_PAT_NONE,
+ 12, {0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}},
/* B8 READ ELEMENT STATUS */
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
diff --git a/sys/cam/ctl/ctl_private.h b/sys/cam/ctl/ctl_private.h
index aeea63d..30418df 100644
--- a/sys/cam/ctl/ctl_private.h
+++ b/sys/cam/ctl/ctl_private.h
@@ -486,6 +486,7 @@ int ctl_mode_select(struct ctl_scsiio *ctsio);
int ctl_mode_sense(struct ctl_scsiio *ctsio);
int ctl_read_capacity(struct ctl_scsiio *ctsio);
int ctl_read_capacity_16(struct ctl_scsiio *ctsio);
+int ctl_read_defect(struct ctl_scsiio *ctsio);
int ctl_read_write(struct ctl_scsiio *ctsio);
int ctl_cnw(struct ctl_scsiio *ctsio);
int ctl_report_luns(struct ctl_scsiio *ctsio);
diff --git a/sys/cam/scsi/scsi_da.h b/sys/cam/scsi/scsi_da.h
index a27b173..f48d327 100644
--- a/sys/cam/scsi/scsi_da.h
+++ b/sys/cam/scsi/scsi_da.h
@@ -92,28 +92,19 @@ struct scsi_reassign_blocks
struct scsi_read_defect_data_10
{
- u_int8_t opcode;
-
- /*
- * The most significant 3 bits are the LUN, the other 5 are
- * reserved.
- */
-#define SRDD10_LUN_MASK 0xE0
- u_int8_t byte2;
+ uint8_t opcode;
+ uint8_t byte2;
#define SRDD10_GLIST 0x08
#define SRDD10_PLIST 0x10
#define SRDD10_DLIST_FORMAT_MASK 0x07
#define SRDD10_BLOCK_FORMAT 0x00
#define SRDD10_BYTES_FROM_INDEX_FORMAT 0x04
#define SRDD10_PHYSICAL_SECTOR_FORMAT 0x05
- u_int8_t format;
-
- u_int8_t reserved[4];
-
- u_int8_t alloc_length[2];
+ uint8_t format;
+ uint8_t reserved[4];
+ uint8_t alloc_length[2];
#define SRDD10_MAX_LENGTH 0xffff
-
- u_int8_t control;
+ uint8_t control;
};
struct scsi_sanitize
@@ -143,29 +134,18 @@ struct scsi_sanitize_parameter_list
struct scsi_read_defect_data_12
{
- u_int8_t opcode;
-
- /*
- * The most significant 3 bits are the LUN, the other 5 are
- * reserved.
- */
-#define SRDD12_LUN_MASK 0xE0
- u_int8_t byte2;
-
+ uint8_t opcode;
#define SRDD12_GLIST 0x08
#define SRDD12_PLIST 0x10
#define SRDD12_DLIST_FORMAT_MASK 0x07
#define SRDD12_BLOCK_FORMAT 0x00
#define SRDD12_BYTES_FROM_INDEX_FORMAT 0x04
#define SRDD12_PHYSICAL_SECTOR_FORMAT 0x05
- u_int8_t format;
-
- u_int8_t reserved[4];
-
- u_int8_t alloc_length[4];
-
- u_int8_t control;
-
+ uint8_t format;
+ uint8_t address_descriptor_index[4];
+ uint8_t alloc_length[4];
+ uint8_t reserved;
+ uint8_t control;
};
@@ -376,6 +356,7 @@ struct scsi_read_defect_data_hdr_12
#define SRDDH12_BYTES_FROM_INDEX_FORMAT 0x04
#define SRDDH12_PHYSICAL_SECTOR_FORMAT 0x05
u_int8_t format;
+ u_int8_t generation[2];
u_int8_t length[4];
};
OpenPOWER on IntegriCloud