From: ccardenas Date: Tue, 16 Jan 2018 06:10:45 +0000 (+0000) Subject: VMD: vioscsi - add support for REPORT_LUNS opcode X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=845b44568bcf608339f7db6e46caec2f4462b8f5;p=openbsd VMD: vioscsi - add support for REPORT_LUNS opcode ok mlarkin@ --- diff --git a/usr.sbin/vmd/vioscsi.c b/usr.sbin/vmd/vioscsi.c index fec4d46c14b..e1ea48782b0 100644 --- a/usr.sbin/vmd/vioscsi.c +++ b/usr.sbin/vmd/vioscsi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vioscsi.c,v 1.2 2018/01/15 04:26:58 ccardenas Exp $ */ +/* $OpenBSD: vioscsi.c,v 1.3 2018/01/16 06:10:45 ccardenas Exp $ */ /* * Copyright (c) 2017 Carlos Cardenas @@ -771,6 +771,105 @@ read_capacity_16_out: return (ret); } +static int +vioscsi_handle_report_luns(struct vioscsi_dev *dev, + struct virtio_scsi_req_hdr *req, struct virtio_vq_acct *acct) +{ + int ret = 0; + struct virtio_scsi_res_hdr resp; + uint32_t rpl_length; + struct scsi_report_luns *rpl; + struct vioscsi_report_luns_data *reply_rpl; + + memset(&resp, 0, sizeof(resp)); + rpl = (struct scsi_report_luns *)(req->cdb); + rpl_length = _4btol(rpl->length); + + log_debug("%s: REPORT_LUNS Report 0x%x Length %d", __func__, + rpl->selectreport, rpl_length); + + if (rpl_length < RPL_MIN_SIZE) { + log_debug("%s: RPL_Length %d < %d (RPL_MIN_SIZE)", __func__, + rpl_length, RPL_MIN_SIZE); + + vioscsi_prepare_resp(&resp, + VIRTIO_SCSI_S_OK, SCSI_CHECK, SKEY_ILLEGAL_REQUEST, + SENSE_ILLEGAL_CDB_FIELD, SENSE_DEFAULT_ASCQ); + + /* Move index for response */ + acct->resp_desc = vioscsi_next_ring_desc(acct->desc, + acct->req_desc, &(acct->resp_idx)); + + if (write_mem(acct->resp_desc->addr, &resp, + acct->resp_desc->len)) { + log_warnx("%s: unable to set ERR " + "status data @ 0x%llx", __func__, + acct->resp_desc->addr); + } else { + ret = 1; + dev->cfg.isr_status = 1; + /* Move ring indexes */ + vioscsi_next_ring_item(dev, acct->avail, acct->used, + acct->req_desc, acct->req_idx); + } + goto rpl_out; + + } + + reply_rpl = calloc(1, sizeof(*reply_rpl)); + + if (reply_rpl == NULL) { + log_warnx("%s: cannot alloc reply_rpl", __func__); + goto rpl_out; + } + + _lto4b(RPL_SINGLE_LUN, reply_rpl->length); + memcpy(reply_rpl->lun, req->lun, RPL_SINGLE_LUN); + + vioscsi_prepare_resp(&resp, + VIRTIO_SCSI_S_OK, SCSI_OK, 0, 0, 0); + + /* Move index for response */ + acct->resp_desc = vioscsi_next_ring_desc(acct->desc, acct->req_desc, + &(acct->resp_idx)); + + dprintf("%s: writing resp to 0x%llx size %d at local " + "idx %d req_idx %d global_idx %d", __func__, acct->resp_desc->addr, + acct->resp_desc->len, acct->resp_idx, acct->req_idx, acct->idx); + + if (write_mem(acct->resp_desc->addr, &resp, acct->resp_desc->len)) { + log_warnx("%s: unable to write OK resp status data @ 0x%llx", + __func__, acct->resp_desc->addr); + goto free_rpl; + } + + /* Move index for reply_rpl */ + acct->resp_desc = vioscsi_next_ring_desc(acct->desc, acct->resp_desc, + &(acct->resp_idx)); + + dprintf("%s: writing reply_rpl to 0x%llx size %d at " + "local idx %d req_idx %d global_idx %d", + __func__, acct->resp_desc->addr, acct->resp_desc->len, + acct->resp_idx, acct->req_idx, acct->idx); + + if (write_mem(acct->resp_desc->addr, reply_rpl, acct->resp_desc->len)) { + log_warnx("%s: unable to write reply_rpl" + " response to gpa @ 0x%llx", + __func__, acct->resp_desc->addr); + } else { + ret = 1; + dev->cfg.isr_status = 1; + /* Move ring indexes */ + vioscsi_next_ring_item(dev, acct->avail, acct->used, + acct->req_desc, acct->req_idx); + } + +free_rpl: + free(reply_rpl); +rpl_out: + return (ret); +} + static int vioscsi_handle_read_6(struct vioscsi_dev *dev, struct virtio_scsi_req_hdr *req, struct virtio_vq_acct *acct) @@ -2220,6 +2319,15 @@ vioscsi_notifyq(struct vioscsi_dev *dev) } } break; + case REPORT_LUNS: + ret = vioscsi_handle_report_luns(dev, &req, &acct); + if (ret) { + if (write_mem(q_gpa, vr, vr_sz)) { + log_warnx("%s: error writing vioring", + __func__); + } + } + break; default: log_warnx("%s: unsupported opcode 0x%02x,%s", __func__, req.cdb[0], vioscsi_op_names(req.cdb[0])); diff --git a/usr.sbin/vmd/vioscsi.h b/usr.sbin/vmd/vioscsi.h index ffaa21f7a0a..16aed6f5e01 100644 --- a/usr.sbin/vmd/vioscsi.h +++ b/usr.sbin/vmd/vioscsi.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vioscsi.h,v 1.1 2018/01/03 05:39:56 ccardenas Exp $ */ +/* $OpenBSD: vioscsi.h,v 1.2 2018/01/16 06:10:45 ccardenas Exp $ */ /* * Copyright (c) 2017 Carlos Cardenas @@ -59,6 +59,8 @@ #define G_CONFIG_REPLY_SIZE 56 #define G_CONFIG_REPLY_SIZE_HEX 0x0034 +#define RPL_MIN_SIZE 16 + /* Opcodes not defined in scsi */ #define GET_EVENT_STATUS_NOTIFICATION 0x4a #define GET_CONFIGURATION 0x46 @@ -229,3 +231,14 @@ struct scsi_config_random_read_descriptor { #define CONFIG_RANDOM_READ_BLOCKING_TYPE 0x0010 u_int8_t unused[2]; }; + +/* + * Variant of scsi_report_luns_data in scsi_all.h + * but with only one lun in the lun list + */ +struct vioscsi_report_luns_data { + u_int8_t length[4]; + u_int8_t reserved[4]; +#define RPL_SINGLE_LUN 8 + u_int8_t lun[RPL_SINGLE_LUN]; +};