[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 1/4] virtio-scsi: Add virtio-scsi stub device
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PATCH 1/4] virtio-scsi: Add virtio-scsi stub device |
Date: |
Tue, 15 Nov 2011 18:00:02 +0100 |
From: Stefan Hajnoczi <address@hidden>
Add a useless virtio SCSI HBA device:
qemu -device virtio-scsi-pci
Signed-off-by: Stefan Hajnoczi <address@hidden>
Signed-off-by: Paolo Bonzini <address@hidden>
---
Makefile.target | 1 +
default-configs/pci.mak | 1 +
hw/pci.h | 1 +
hw/virtio-pci.c | 42 ++++++++++
hw/virtio-pci.h | 2 +
hw/virtio-scsi.c | 194 +++++++++++++++++++++++++++++++++++++++++++++++
hw/virtio-scsi.h | 28 +++++++
hw/virtio.h | 3 +
8 files changed, 272 insertions(+), 0 deletions(-)
create mode 100644 hw/virtio-scsi.c
create mode 100644 hw/virtio-scsi.h
diff --git a/Makefile.target b/Makefile.target
index a111521..f3bc562 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -199,6 +199,7 @@ obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o
balloon.o ioport.o
# need to fix this properly
obj-$(CONFIG_NO_PCI) += pci-stub.o
obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o
virtio-serial-bus.o
+obj-$(CONFIG_VIRTIO_SCSI) += virtio-scsi.o
obj-y += vhost_net.o
obj-$(CONFIG_VHOST_NET) += vhost.o
obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
diff --git a/default-configs/pci.mak b/default-configs/pci.mak
index 22bd350..9c8edd4 100644
--- a/default-configs/pci.mak
+++ b/default-configs/pci.mak
@@ -1,5 +1,6 @@
CONFIG_PCI=y
CONFIG_VIRTIO_PCI=y
+CONFIG_VIRTIO_SCSI=y
CONFIG_VIRTIO=y
CONFIG_USB_UHCI=y
CONFIG_USB_OHCI=y
diff --git a/hw/pci.h b/hw/pci.h
index 4b2e785..e21ffd2 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -75,6 +75,7 @@
#define PCI_DEVICE_ID_VIRTIO_BLOCK 0x1001
#define PCI_DEVICE_ID_VIRTIO_BALLOON 0x1002
#define PCI_DEVICE_ID_VIRTIO_CONSOLE 0x1003
+#define PCI_DEVICE_ID_VIRTIO_SCSI 0x1004
#define FMT_PCIBUS PRIx64
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index ca5923c..72be056 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -19,6 +19,7 @@
#include "virtio-blk.h"
#include "virtio-net.h"
#include "virtio-serial.h"
+#include "virtio-scsi.h"
#include "pci.h"
#include "qemu-error.h"
#include "msix.h"
@@ -784,6 +785,32 @@ static int virtio_balloon_exit_pci(PCIDevice *pci_dev)
return virtio_exit_pci(pci_dev);
}
+static int virtio_scsi_init_pci(PCIDevice *pci_dev)
+{
+ VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+ VirtIODevice *vdev;
+
+ vdev = virtio_scsi_init(&pci_dev->qdev, &proxy->scsi);
+ if (!vdev) {
+ return -EINVAL;
+ }
+
+ vdev->nvectors = proxy->nvectors;
+ virtio_init_pci(proxy, vdev);
+
+ /* make the actual value visible */
+ proxy->nvectors = vdev->nvectors;
+ return 0;
+}
+
+static int virtio_scsi_exit_pci(PCIDevice *pci_dev)
+{
+ VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+
+ virtio_scsi_exit(proxy->vdev);
+ return virtio_exit_pci(pci_dev);
+}
+
static PCIDeviceInfo virtio_info[] = {
{
.qdev.name = "virtio-blk-pci",
@@ -869,6 +896,21 @@ static PCIDeviceInfo virtio_info[] = {
},
.qdev.reset = virtio_pci_reset,
},{
+ .qdev.name = "virtio-scsi-pci",
+ .qdev.size = sizeof(VirtIOPCIProxy),
+ .init = virtio_scsi_init_pci,
+ .exit = virtio_scsi_exit_pci,
+ .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
+ .device_id = PCI_DEVICE_ID_VIRTIO_SCSI,
+ .class_id = PCI_CLASS_STORAGE_SCSI,
+ .revision = 0x00,
+ .qdev.props = (Property[]) {
+ DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
+ DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+ DEFINE_PROP_UINT32("num_queues", VirtIOPCIProxy, scsi.num_queues,
1),
+ DEFINE_PROP_END_OF_LIST(),
+ },
+ }, {
/* end of list */
}
};
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index f8404de..20523af 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -17,6 +17,7 @@
#include "virtio-net.h"
#include "virtio-serial.h"
+#include "virtio-scsi.h"
/* Performance improves when virtqueue kick processing is decoupled from the
* vcpu thread using ioeventfd for some devices. */
@@ -40,6 +41,7 @@ typedef struct {
#endif
virtio_serial_conf serial;
virtio_net_conf net;
+ VirtIOSCSIConf scsi;
bool ioeventfd_disabled;
bool ioeventfd_started;
} VirtIOPCIProxy;
diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
new file mode 100644
index 0000000..ff86376
--- /dev/null
+++ b/hw/virtio-scsi.c
@@ -0,0 +1,194 @@
+/*
+ * Virtio SCSI HBA
+ *
+ * Copyright IBM, Corp. 2010
+ * Copyright Red Hat, Inc. 2011
+ *
+ * Authors:
+ * Stefan Hajnoczi <address@hidden>
+ * Paolo Bonzini <address@hidden>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "virtio-scsi.h"
+#include <hw/scsi.h>
+#include <hw/scsi-defs.h>
+
+#define VIRTIO_SCSI_VQ_SIZE 128
+#define VIRTIO_SCSI_CDB_SIZE 32
+#define VIRTIO_SCSI_SENSE_SIZE 96
+
+/* Response codes */
+#define VIRTIO_SCSI_S_OK 0
+#define VIRTIO_SCSI_S_UNDERRUN 1
+#define VIRTIO_SCSI_S_ABORTED 2
+#define VIRTIO_SCSI_S_BAD_TARGET 3
+#define VIRTIO_SCSI_S_RESET 4
+#define VIRTIO_SCSI_S_TRANSPORT_FAILURE 5
+#define VIRTIO_SCSI_S_TARGET_FAILURE 6
+#define VIRTIO_SCSI_S_NEXUS_FAILURE 7
+#define VIRTIO_SCSI_S_FAILURE 8
+#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED 9
+#define VIRTIO_SCSI_S_FUNCTION_REJECTED 10
+#define VIRTIO_SCSI_S_INCORRECT_LUN 11
+
+/* Controlq type codes. */
+#define VIRTIO_SCSI_T_TMF 0
+#define VIRTIO_SCSI_T_AN_QUERY 1
+#define VIRTIO_SCSI_T_AN_SUBSCRIBE 2
+
+/* Valid TMF subtypes. */
+#define VIRTIO_SCSI_T_TMF_ABORT_TASK 0
+#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET 1
+#define VIRTIO_SCSI_T_TMF_CLEAR_ACA 2
+#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET 3
+#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET 4
+#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET 5
+#define VIRTIO_SCSI_T_TMF_QUERY_TASK 6
+#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET 7
+
+/* Events. */
+#define VIRTIO_SCSI_T_EVENTS_MISSED 0x80000000
+#define VIRTIO_SCSI_T_NO_EVENT 0
+#define VIRTIO_SCSI_T_TRANSPORT_RESET 1
+#define VIRTIO_SCSI_T_ASYNC_NOTIFY 2
+
+/* SCSI command request, followed by data-out */
+typedef struct {
+ uint8_t lun[8]; /* Logical Unit Number */
+ uint64_t tag; /* Command identifier */
+ uint8_t task_attr; /* Task attribute */
+ uint8_t prio;
+ uint8_t crn;
+ uint8_t cdb[];
+} QEMU_PACKED VirtIOSCSICmdReq;
+
+/* Response, followed by sense data and data-in */
+typedef struct {
+ uint32_t sense_len; /* Sense data length */
+ uint32_t resid; /* Residual bytes in data buffer */
+ uint16_t status_qualifier; /* Status qualifier */
+ uint8_t status; /* Command completion status */
+ uint8_t response; /* Response values */
+ uint8_t sense[];
+} QEMU_PACKED VirtIOSCSICmdResp;
+
+/* Task Management Request */
+typedef struct {
+ uint32_t type;
+ uint32_t subtype;
+ uint8_t lun[8];
+ uint64_t tag;
+} QEMU_PACKED VirtIOSCSICtrlTMFReq;
+
+typedef struct {
+ uint8_t response;
+} QEMU_PACKED VirtIOSCSICtrlTMFResp;
+
+/* Asynchronous notification query/subscription */
+typedef struct {
+ uint32_t type;
+ uint8_t lun[8];
+ uint32_t event_requested;
+} QEMU_PACKED VirtIOSCSICtrlANReq;
+
+typedef struct {
+ uint32_t event_actual;
+ uint8_t response;
+} QEMU_PACKED VirtIOSCSICtrlANResp;
+
+typedef struct {
+ uint32_t event;
+ uint8_t lun[8];
+ uint32_t reason;
+} QEMU_PACKED VirtIOSCSIEvent;
+
+typedef struct {
+ uint32_t num_queues;
+ uint32_t seg_max;
+ uint32_t event_info_size;
+ uint32_t sense_size;
+ uint32_t cdb_size;
+} QEMU_PACKED VirtIOSCSIConfig;
+
+typedef struct {
+ VirtIODevice vdev;
+ DeviceState *qdev;
+ VirtIOSCSIConf *conf;
+
+ VirtQueue *ctrl_vq;
+ VirtQueue *event_vq;
+ VirtQueue *cmd_vq;
+ uint32_t event_info_size;
+ uint32_t sense_size;
+ uint32_t cdb_size;
+} VirtIOSCSI;
+
+static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
+{
+ /* TODO */
+}
+
+static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
+{
+ /* TODO */
+}
+
+static void virtio_scsi_get_config(VirtIODevice *vdev,
+ uint8_t *config)
+{
+ VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
+ VirtIOSCSI *s = (VirtIOSCSI *)vdev;
+
+ stl_raw(&scsiconf->num_queues, s->conf->num_queues);
+ stl_raw(&scsiconf->seg_max, 128 - 2);
+ stl_raw(&scsiconf->event_info_size, s->event_info_size);
+ stl_raw(&scsiconf->sense_size, s->sense_size);
+ stl_raw(&scsiconf->cdb_size, s->cdb_size);
+}
+
+static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,
+ uint32_t requested_features)
+{
+ return requested_features;
+}
+
+VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
+{
+ VirtIOSCSI *s;
+
+ s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI,
+ sizeof(VirtIOSCSIConf),
+ sizeof(VirtIOSCSI));
+
+ s->qdev = dev;
+ s->conf = proxyconf;
+
+ /* TODO set up vdev function pointers */
+ s->vdev.get_config = virtio_scsi_get_config;
+ s->vdev.get_features = virtio_scsi_get_features;
+
+ s->event_info_size = sizeof(VirtIOSCSIEvent);
+ s->sense_size = VIRTIO_SCSI_SENSE_SIZE;
+ s->cdb_size = VIRTIO_SCSI_CDB_SIZE;
+
+ s->ctrl_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
+ virtio_scsi_handle_ctrl);
+ s->event_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
+ NULL);
+ s->cmd_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
+ virtio_scsi_handle_cmd);
+
+ /* TODO savevm */
+ /* TODO boot device path */
+
+ return &s->vdev;
+}
+
+void virtio_scsi_exit(VirtIODevice *vdev)
+{
+ virtio_cleanup(vdev);
+}
diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h
new file mode 100644
index 0000000..fcf8967
--- /dev/null
+++ b/hw/virtio-scsi.h
@@ -0,0 +1,28 @@
+/*
+ * Virtio SCSI HBA
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ * Stefan Hajnoczi <address@hidden>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef _QEMU_VIRTIO_SCSI_H
+#define _QEMU_VIRTIO_SCSI_H
+
+#include "virtio.h"
+#include "net.h"
+#include "pci.h"
+
+/* The ID for virtio_scsi */
+#define VIRTIO_ID_SCSI 6
+
+struct VirtIOSCSIConf {
+ uint32_t num_queues;
+};
+
+#endif /* _QEMU_VIRTIO_SCSI_H */
diff --git a/hw/virtio.h b/hw/virtio.h
index 2d18209..91daa32 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -198,6 +198,8 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf
*conf,
typedef struct virtio_serial_conf virtio_serial_conf;
VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *serial);
VirtIODevice *virtio_balloon_init(DeviceState *dev);
+typedef struct VirtIOSCSIConf VirtIOSCSIConf;
+VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *conf);
#ifdef CONFIG_LINUX
VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
#endif
@@ -207,6 +209,7 @@ void virtio_net_exit(VirtIODevice *vdev);
void virtio_blk_exit(VirtIODevice *vdev);
void virtio_serial_exit(VirtIODevice *vdev);
void virtio_balloon_exit(VirtIODevice *vdev);
+void virtio_scsi_exit(VirtIODevice *vdev);
#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
DEFINE_PROP_BIT("indirect_desc", _state, _field, \
--
1.7.7.1