Add reporting of SCSI Feature Sets VPD page from SPC-5.

CTL implements all defined feature sets except Drive Maintenance 2016,
which is not very applicable to such a virtual device, and implemented
only partially now.  But may be it could be fixed later at least for
completeness.

MFC after:	2 weeks
This commit is contained in:
Alexander Motin 2019-07-26 01:49:28 +00:00
parent 0dbac71f19
commit 0ea67e7019
2 changed files with 81 additions and 5 deletions

View file

@ -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;
@ -9698,6 +9702,58 @@ ctl_inquiry_evpd_scsi_ports(struct ctl_scsiio *ctsio, int alloc_len)
return (CTL_RETVAL_COMPLETE);
}
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)
{
@ -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;

View file

@ -2762,6 +2762,19 @@ struct scsi_vpd_tpc
struct scsi_vpd_tpc_descriptor descr[];
};
/*
* 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) \