qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH RFC 05/11] ide: bridge 'transfer' and 'complete' fun


From: Alexander Bezzubikov
Subject: [Qemu-devel] [PATCH RFC 05/11] ide: bridge 'transfer' and 'complete' functions added
Date: Tue, 18 Aug 2015 02:42:19 +0300

Signed-off-by: Alexander Bezzubikov <address@hidden>
---
 hw/ide/bridge.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 114 insertions(+)
 create mode 100644 hw/ide/bridge.c

diff --git a/hw/ide/bridge.c b/hw/ide/bridge.c
new file mode 100644
index 0000000..3a534de
--- /dev/null
+++ b/hw/ide/bridge.c
@@ -0,0 +1,114 @@
+#include "hw/ide/bridge.h"
+
+static void ide_bridge_do_transfer(IDEState *s)
+{
+    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, s->cur_req);
+
+    if (r->buflen > 0) {
+        int size = r->buflen;
+
+        int byte_count_limit = s->lcyl | (s->hcyl << 8);
+        if (byte_count_limit == 0xffff) {
+            byte_count_limit--;
+        }
+        if (size > byte_count_limit) {
+            /* byte count limit must be even if this case */
+            if (byte_count_limit & 1) {
+                byte_count_limit--;
+            }
+            size = byte_count_limit;
+        }
+        s->lcyl = size;
+        s->hcyl = size >> 8;
+        s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO;
+
+        int offset = (r->buflen == r->qiov.size) ? 0 : r->qiov.size - 
r->buflen;
+        r->buflen -= size;
+
+        ide_transfer_start(s, s->io_buffer + offset, size,
+                           &ide_bridge_do_transfer);
+        ide_set_irq(s->bus);
+    } else {
+        scsi_req_complete(s->cur_req, GOOD);
+    }
+}
+
+static void ide_bridge_dma_complete(void *opaque, int ret)
+{
+    IDEState *s = opaque;
+
+    s->io_buffer_size = s->bus->dma->iov.iov_len;
+    s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
+    s->bus->dma->ops->rw_buf(s->bus->dma, 1);
+    scsi_req_complete(s->cur_req, GOOD);
+
+    s->status = READY_STAT | SEEK_STAT;
+
+    ide_set_irq(s->bus);
+    ide_set_inactive(s, false);
+}
+
+void ide_bridge_start_transfer(SCSIRequest *req, uint32_t len)
+{
+    IDEDevice *dev = IDE_DEVICE(req->bus->qbus.parent);
+    IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
+    IDEState *s = bus->ifs;
+    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
+
+    int cmd = req->cmd.buf[0];
+    if (cmd == READ_10) {
+        if (s->feature & 1) {
+            s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;
+            qemu_iovec_clone(&s->bus->dma->qiov, &r->qiov, NULL);
+            qemu_iovec_to_buf(&r->qiov, 0, s->io_buffer, r->qiov.size);
+        } else {
+            qemu_iovec_to_buf(&r->qiov, 0, s->io_buffer, r->qiov.size);
+        }
+    } else {
+        if (cmd == INQUIRY) {
+            len = 36;
+        }
+        r->iov.iov_len = len;
+        qemu_iovec_concat_iov(&r->qiov, &r->iov, len, 0, len);
+        qemu_iovec_to_buf(&r->qiov, 0, s->io_buffer, r->qiov.size);
+    }
+
+    s->io_buffer_index = 0;
+    s->status = READY_STAT | SEEK_STAT;
+
+    if (cmd != TEST_UNIT_READY && cmd != ALLOW_MEDIUM_REMOVAL) {
+        if (s->feature & 1) {
+            s->io_buffer_index = 0;
+            s->bus->retry_unit = s->unit;
+            s->bus->retry_sector_num = ide_get_sector(s);
+            s->bus->retry_nsector = s->nsector;
+
+            s->bus->dma->iov.iov_base = (void *)(s->io_buffer);
+            s->bus->dma->iov.iov_len = r->qiov.size;
+
+            if (cmd != READ_10) {
+                s->status = READY_STAT | SEEK_STAT | DRQ_STAT;
+            }
+
+            if (s->bus->dma->ops->start_dma) {
+                s->bus->dma->ops->start_dma(s->bus->dma, s,
+                                            ide_bridge_dma_complete);
+            }
+        } else {
+            r->buflen = r->qiov.size;
+            ide_bridge_do_transfer(s);
+        }
+    } else {
+        scsi_req_complete(req, GOOD);
+    }
+}
+
+void ide_bridge_complete(SCSIRequest *req, uint32_t status, size_t resid)
+{
+    IDEDevice *dev = IDE_DEVICE(req->bus->qbus.parent);
+    IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
+    IDEState *s = bus->ifs;
+
+    ide_atapi_cmd_ok(s);
+    ide_set_irq(s->bus);
+}
-- 
2.1.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]