[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v4 12/18] virtio-scsi: Add basic request processing
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PATCH v4 12/18] virtio-scsi: Add basic request processing infrastructure |
Date: |
Wed, 22 Feb 2012 15:33:50 +0100 |
From: Stefan Hajnoczi <address@hidden>
Signed-off-by: Stefan Hajnoczi <address@hidden>
Reviewed-by: Stefan Hajnoczi <address@hidden>
Signed-off-by: Paolo Bonzini <address@hidden>
---
hw/virtio-scsi.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 140 insertions(+), 2 deletions(-)
diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index a297fed..a9f883c 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -135,14 +135,152 @@ typedef struct {
uint32_t cdb_size;
} VirtIOSCSI;
+typedef struct VirtIOSCSIReq {
+ VirtIOSCSI *dev;
+ VirtQueue *vq;
+ VirtQueueElement elem;
+ QEMUSGList qsgl;
+ SCSIRequest *sreq;
+ union {
+ char *buf;
+ VirtIOSCSICmdReq *cmd;
+ VirtIOSCSICtrlTMFReq *tmf;
+ VirtIOSCSICtrlANReq *an;
+ } req;
+ union {
+ char *buf;
+ VirtIOSCSICmdResp *cmd;
+ VirtIOSCSICtrlTMFResp *tmf;
+ VirtIOSCSICtrlANResp *an;
+ VirtIOSCSIEvent *event;
+ } resp;
+} VirtIOSCSIReq;
+
+static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
+{
+ VirtIOSCSI *s = req->dev;
+ VirtQueue *vq = req->vq;
+ virtqueue_push(vq, &req->elem, req->qsgl.size +
req->elem.in_sg[0].iov_len);
+ qemu_sglist_destroy(&req->qsgl);
+ if (req->sreq) {
+ req->sreq->hba_private = NULL;
+ scsi_req_unref(req->sreq);
+ }
+ g_free(req);
+ virtio_notify(&s->vdev, vq);
+}
+
+static void virtio_scsi_bad_req(void)
+{
+ error_report("wrong size for virtio-scsi headers");
+ exit(1);
+}
+
+static void qemu_sgl_init_external(QEMUSGList *qsgl, struct iovec *sg,
+ target_phys_addr_t *addr, int num)
+{
+ memset(qsgl, 0, sizeof(*qsgl));
+ while (num--) {
+ qemu_sglist_add(qsgl, *(addr++), (sg++)->iov_len);
+ }
+}
+
+static void virtio_scsi_parse_req(VirtIOSCSI *s, VirtQueue *vq,
+ VirtIOSCSIReq *req)
+{
+ assert(req->elem.out_num && req->elem.in_num);
+ req->vq = vq;
+ req->dev = s;
+ req->sreq = NULL;
+ req->req.buf = req->elem.out_sg[0].iov_base;
+ req->resp.buf = req->elem.in_sg[0].iov_base;
+
+ if (req->elem.out_num > 1) {
+ qemu_sgl_init_external(&req->qsgl, &req->elem.out_sg[1],
+ &req->elem.out_addr[1],
+ req->elem.out_num - 1);
+ } else {
+ qemu_sgl_init_external(&req->qsgl, &req->elem.in_sg[1],
+ &req->elem.in_addr[1],
+ req->elem.in_num - 1);
+ }
+}
+
+static VirtIOSCSIReq *virtio_scsi_pop_req(VirtIOSCSI *s, VirtQueue *vq)
+{
+ VirtIOSCSIReq *req;
+ req = g_malloc(sizeof(*req));
+ if (!virtqueue_pop(vq, &req->elem)) {
+ g_free(req);
+ return NULL;
+ }
+
+ virtio_scsi_parse_req(s, vq, req);
+ return req;
+}
+
+static void virtio_scsi_fail_ctrl_req(VirtIOSCSIReq *req)
+{
+ if (req->req.tmf->type == VIRTIO_SCSI_T_TMF) {
+ req->resp.tmf->response = VIRTIO_SCSI_S_FAILURE;
+ } else {
+ req->resp.an->response = VIRTIO_SCSI_S_FAILURE;
+ }
+
+ virtio_scsi_complete_req(req);
+}
+
static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
{
- /* TODO */
+ VirtIOSCSI *s = (VirtIOSCSI *)vdev;
+ VirtIOSCSIReq *req;
+
+ while ((req = virtio_scsi_pop_req(s, vq))) {
+ virtio_scsi_fail_ctrl_req(req);
+ }
+}
+
+static void virtio_scsi_fail_cmd_req(VirtIOSCSI *s, VirtIOSCSIReq *req)
+{
+ req->resp.cmd->response = VIRTIO_SCSI_S_FAILURE;
+ virtio_scsi_complete_req(req);
}
static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
{
- /* TODO */
+ VirtIOSCSI *s = (VirtIOSCSI *)vdev;
+ VirtIOSCSIReq *req;
+
+ while ((req = virtio_scsi_pop_req(s, vq))) {
+ int out_size, in_size;
+ if (req->elem.out_num < 1 || req->elem.in_num < 1) {
+ virtio_scsi_bad_req();
+ }
+
+ out_size = req->elem.out_sg[0].iov_len;
+ in_size = req->elem.in_sg[0].iov_len;
+ if (out_size < sizeof(VirtIOSCSICmdReq) + s->cdb_size ||
+ in_size < sizeof(VirtIOSCSICmdResp) + s->sense_size) {
+ virtio_scsi_bad_req();
+ }
+
+ if (req->elem.out_num > 1 && req->elem.in_num > 1) {
+ virtio_scsi_fail_cmd_req(s, req);
+ continue;
+ }
+
+ req->resp.cmd->resid = 0;
+ req->resp.cmd->status_qualifier = 0;
+ req->resp.cmd->status = CHECK_CONDITION;
+ req->resp.cmd->sense_len = 4;
+ req->resp.cmd->sense[0] = 0xf0; /* Fixed format current sense */
+ req->resp.cmd->sense[1] = ILLEGAL_REQUEST;
+ req->resp.cmd->sense[2] = 0x20;
+ req->resp.cmd->sense[3] = 0x00;
+ req->resp.cmd->response = VIRTIO_SCSI_S_OK;
+
+ virtio_scsi_complete_req(req);
+ }
}
static void virtio_scsi_get_config(VirtIODevice *vdev,
--
1.7.7.6
- [Qemu-devel] [PULL v4 00/18] virtio-scsi driver, Paolo Bonzini, 2012/02/22
- [Qemu-devel] [PATCH v4 02/18] dma-helpers: add dma_buf_read and dma_buf_write, Paolo Bonzini, 2012/02/22
- [Qemu-devel] [PATCH v4 03/18] dma-helpers: add accounting wrappers, Paolo Bonzini, 2012/02/22
- [Qemu-devel] [PATCH v4 04/18] ahci: use new DMA helpers, Paolo Bonzini, 2012/02/22
- [Qemu-devel] [PATCH v4 01/18] dma-helpers: make QEMUSGList target independent, Paolo Bonzini, 2012/02/22
- [Qemu-devel] [PATCH v4 05/18] scsi: pass residual amount to command_complete, Paolo Bonzini, 2012/02/22
- [Qemu-devel] [PATCH v4 07/18] scsi-disk: enable scatter/gather functionality, Paolo Bonzini, 2012/02/22
- [Qemu-devel] [PATCH v4 06/18] scsi: add scatter/gather functionality, Paolo Bonzini, 2012/02/22
- [Qemu-devel] [PATCH v4 08/18] scsi: add SCSIDevice vmstate definitions, Paolo Bonzini, 2012/02/22
- [Qemu-devel] [PATCH v4 09/18] scsi-generic: add migration support, Paolo Bonzini, 2012/02/22
- [Qemu-devel] [PATCH v4 12/18] virtio-scsi: Add basic request processing infrastructure,
Paolo Bonzini <=
- [Qemu-devel] [PATCH v4 10/18] scsi-disk: add migration support, Paolo Bonzini, 2012/02/22
- [Qemu-devel] [PATCH v4 11/18] virtio-scsi: Add virtio-scsi stub device, Paolo Bonzini, 2012/02/22
- [Qemu-devel] [PATCH v4 14/18] virtio-scsi: process control queue requests, Paolo Bonzini, 2012/02/22
- [Qemu-devel] [PATCH v4 15/18] virtio-scsi: add migration support, Paolo Bonzini, 2012/02/22
- [Qemu-devel] [PATCH v4 13/18] virtio-scsi: add basic SCSI bus operation, Paolo Bonzini, 2012/02/22
- [Qemu-devel] [PATCH v4 16/18] scsi: fix wrong return for target INQUIRY, Paolo Bonzini, 2012/02/22
- [Qemu-devel] [PATCH v4 17/18] scsi: fix searching for an empty id, Paolo Bonzini, 2012/02/22