aboutsummaryrefslogtreecommitdiff
path: root/sys/cam
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/ctl/ctl.c67
-rw-r--r--sys/cam/scsi/scsi_all.h19
2 files changed, 81 insertions, 5 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 482e12d0dba8..ab66bd94f8e6 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -448,10 +448,11 @@ SYSCTL_INT(_kern_cam_ctl, OID_AUTO, max_ports, CTLFLAG_RDTUN,
/*
* Supported pages (0x00), Serial number (0x80), Device ID (0x83),
* Extended INQUIRY Data (0x86), Mode Page Policy (0x87),
- * SCSI Ports (0x88), Third-party Copy (0x8F), Block limits (0xB0),
- * Block Device Characteristics (0xB1) and Logical Block Provisioning (0xB2)
+ * SCSI Ports (0x88), Third-party Copy (0x8F), SCSI Feature Sets (0x92),
+ * Block limits (0xB0), Block Device Characteristics (0xB1) and
+ * Logical Block Provisioning (0xB2)
*/
-#define SCSI_EVPD_NUM_SUPPORTED_PAGES 10
+#define SCSI_EVPD_NUM_SUPPORTED_PAGES 11
static void ctl_isc_event_handler(ctl_ha_channel chanel, ctl_ha_event event,
int param);
@@ -489,6 +490,7 @@ static int ctl_inquiry_evpd_eid(struct ctl_scsiio *ctsio, int alloc_len);
static int ctl_inquiry_evpd_mpp(struct ctl_scsiio *ctsio, int alloc_len);
static int ctl_inquiry_evpd_scsi_ports(struct ctl_scsiio *ctsio,
int alloc_len);
+static int ctl_inquiry_evpd_sfs(struct ctl_scsiio *ctsio, int alloc_len);
static int ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio,
int alloc_len);
static int ctl_inquiry_evpd_bdc(struct ctl_scsiio *ctsio, int alloc_len);
@@ -9318,6 +9320,8 @@ ctl_inquiry_evpd_supported(struct ctl_scsiio *ctsio, int alloc_len)
pages->page_list[p++] = SVPD_SCSI_PORTS;
/* Third-party Copy */
pages->page_list[p++] = SVPD_SCSI_TPC;
+ /* SCSI Feature Sets */
+ pages->page_list[p++] = SVPD_SCSI_SFS;
if (lun != NULL && lun->be_lun->lun_type == T_DIRECT) {
/* Block limits */
pages->page_list[p++] = SVPD_BLOCK_LIMITS;
@@ -9699,6 +9703,58 @@ ctl_inquiry_evpd_scsi_ports(struct ctl_scsiio *ctsio, int alloc_len)
}
static int
+ctl_inquiry_evpd_sfs(struct ctl_scsiio *ctsio, int alloc_len)
+{
+ struct ctl_lun *lun = CTL_LUN(ctsio);
+ struct scsi_vpd_sfs *sfs_ptr;
+ int sfs_page_size, n;
+
+ sfs_page_size = sizeof(*sfs_ptr) + 5 * 2;
+ ctsio->kern_data_ptr = malloc(sfs_page_size, M_CTL, M_WAITOK | M_ZERO);
+ sfs_ptr = (struct scsi_vpd_sfs *)ctsio->kern_data_ptr;
+ ctsio->kern_sg_entries = 0;
+ ctsio->kern_rel_offset = 0;
+ ctsio->kern_sg_entries = 0;
+ ctsio->kern_data_len = min(sfs_page_size, alloc_len);
+ ctsio->kern_total_len = ctsio->kern_data_len;
+
+ /*
+ * The control device is always connected. The disk device, on the
+ * other hand, may not be online all the time. Need to change this
+ * to figure out whether the disk device is actually online or not.
+ */
+ if (lun != NULL)
+ sfs_ptr->device = (SID_QUAL_LU_CONNECTED << 5) |
+ lun->be_lun->lun_type;
+ else
+ sfs_ptr->device = (SID_QUAL_LU_OFFLINE << 5) | T_DIRECT;
+
+ sfs_ptr->page_code = SVPD_SCSI_SFS;
+ n = 0;
+ /* Discovery 2016 */
+ scsi_ulto2b(0x0001, &sfs_ptr->codes[2 * n++]);
+ if (lun != NULL && lun->be_lun->lun_type == T_DIRECT) {
+ /* SBC Base 2016 */
+ scsi_ulto2b(0x0101, &sfs_ptr->codes[2 * n++]);
+ /* SBC Base 2010 */
+ scsi_ulto2b(0x0102, &sfs_ptr->codes[2 * n++]);
+ if (lun->be_lun->flags & CTL_LUN_FLAG_UNMAP) {
+ /* Basic Provisioning 2016 */
+ scsi_ulto2b(0x0103, &sfs_ptr->codes[2 * n++]);
+ }
+ /* Drive Maintenance 2016 */
+ //scsi_ulto2b(0x0104, &sfs_ptr->codes[2 * n++]);
+ }
+ scsi_ulto2b(4 + 2 * n, sfs_ptr->page_length);
+
+ ctl_set_success(ctsio);
+ 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);
+}
+
+static int
ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio, int alloc_len)
{
struct ctl_lun *lun = CTL_LUN(ctsio);
@@ -9811,7 +9867,7 @@ ctl_inquiry_evpd_bdc(struct ctl_scsiio *ctsio, int alloc_len)
else
i = 0;
bdc_ptr->wab_wac_ff = (i & 0x0f);
- bdc_ptr->flags = SVPD_FUAB | SVPD_VBULS;
+ bdc_ptr->flags = SVPD_RBWZ | SVPD_FUAB | SVPD_VBULS;
ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
@@ -9904,6 +9960,9 @@ ctl_inquiry_evpd(struct ctl_scsiio *ctsio)
case SVPD_SCSI_TPC:
retval = ctl_inquiry_evpd_tpc(ctsio, alloc_len);
break;
+ case SVPD_SCSI_SFS:
+ retval = ctl_inquiry_evpd_sfs(ctsio, alloc_len);
+ break;
case SVPD_BLOCK_LIMITS:
if (lun == NULL || lun->be_lun->lun_type != T_DIRECT)
goto err;
diff --git a/sys/cam/scsi/scsi_all.h b/sys/cam/scsi/scsi_all.h
index 4434ef2fa647..ae9c691986f4 100644
--- a/sys/cam/scsi/scsi_all.h
+++ b/sys/cam/scsi/scsi_all.h
@@ -2763,6 +2763,19 @@ struct scsi_vpd_tpc
};
/*
+ * SCSI Feature Sets VPD Page
+ */
+struct scsi_vpd_sfs
+{
+ uint8_t device;
+ uint8_t page_code;
+#define SVPD_SCSI_SFS 0x92
+ uint8_t page_length[2];
+ uint8_t reserved[4];
+ uint8_t codes[];
+};
+
+/*
* Block Device Characteristics VPD Page based on
* T10/1799-D Revision 31
*/
@@ -2803,11 +2816,15 @@ struct scsi_vpd_block_device_characteristics
uint8_t flags;
#define SVPD_VBULS 0x01
#define SVPD_FUAB 0x02
+#define SVPD_BOCS 0x04
+#define SVPD_RBWZ 0x08
#define SVPD_ZBC_NR 0x00 /* Not Reported */
#define SVPD_HAW_ZBC 0x10 /* Host Aware */
#define SVPD_DM_ZBC 0x20 /* Drive Managed */
#define SVPD_ZBC_MASK 0x30 /* Zoned mask */
- uint8_t reserved[55];
+ uint8_t reserved[3];
+ uint8_t depopulation_time[4];
+ uint8_t reserved2[48];
};
#define SBDC_IS_PRESENT(bdc, length, field) \