Howdy.

Attached is a patch that includes handling the REPORT_LUNS opcode which
is used by SeaBIOS 1.11.x .

Comments? Ok?

+--+
Carlos
Index: vioscsi.c
===================================================================
RCS file: /home/los/cvs/src/usr.sbin/vmd/vioscsi.c,v
retrieving revision 1.2
diff -u -p -a -u -r1.2 vioscsi.c
--- vioscsi.c   15 Jan 2018 04:26:58 -0000      1.2
+++ vioscsi.c   16 Jan 2018 04:48:03 -0000
@@ -772,6 +772,105 @@ read_capacity_16_out:
 }
 
 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)
 {
@@ -2213,6 +2312,15 @@ vioscsi_notifyq(struct vioscsi_dev *dev)
                        break;
                case MECHANISM_STATUS:
                        ret = vioscsi_handle_mechanism_status(dev, &req, &acct);
+                       if (ret) {
+                               if (write_mem(q_gpa, vr, vr_sz)) {
+                                       log_warnx("%s: error writing vioring",
+                                           __func__);
+                               }
+                       }
+                       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",
Index: vioscsi.h
===================================================================
RCS file: /home/los/cvs/src/usr.sbin/vmd/vioscsi.h,v
retrieving revision 1.1
diff -u -p -a -u -r1.1 vioscsi.h
--- vioscsi.h   3 Jan 2018 05:39:56 -0000       1.1
+++ vioscsi.h   16 Jan 2018 04:23:26 -0000
@@ -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
@@ -228,4 +230,15 @@ struct scsi_config_random_read_descripto
        u_int8_t blocking_type[2];
 #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];
 };

Reply via email to