VMD: vioscsi - add support for REPORT_LUNS opcode
authorccardenas <ccardenas@openbsd.org>
Tue, 16 Jan 2018 06:10:45 +0000 (06:10 +0000)
committerccardenas <ccardenas@openbsd.org>
Tue, 16 Jan 2018 06:10:45 +0000 (06:10 +0000)
ok mlarkin@

usr.sbin/vmd/vioscsi.c
usr.sbin/vmd/vioscsi.h

index fec4d46..e1ea487 100644 (file)
@@ -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 <ccardenas@openbsd.org>
@@ -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]));
index ffaa21f..16aed6f 100644 (file)
@@ -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 <ccardenas@openbsd.org>
@@ -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];
+};