Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> --- hw/scsi-disk.c | 52 +++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 41 insertions(+), 11 deletions(-)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 509407f..81117d2 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -37,6 +37,7 @@ do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0) #include "scsi-defs.h" #include "sysemu.h" #include "blockdev.h" +#include "dma.h" #define SCSI_DMA_BUF_SIZE 131072 #define SCSI_MAX_INQUIRY_LEN 256 @@ -123,6 +124,25 @@ static uint32_t scsi_init_iovec(SCSIDiskReq *r) return r->qiov.size / 512; } +static void scsi_dma_complete(void *opaque, int ret) +{ + SCSIDiskReq *r = (SCSIDiskReq *)opaque; + + r->req.resid = qemu_sglist_get_resid(r->req.sg); + r->req.aiocb = NULL; + if (ret) { + int is_read = (r->req.cmd.mode == SCSI_XFER_FROM_DEV); + int retry = is_read ? SCSI_REQ_STATUS_RETRY_READ : SCSI_REQ_STATUS_RETRY_WRITE; + if (scsi_handle_rw_error(r, -ret, retry)) { + return; + } + } + + r->sector += r->sector_count; + r->sector_count = 0; + scsi_req_complete(&r->req, GOOD); +} + static void scsi_read_complete(void * opaque, int ret) { SCSIDiskReq *r = (SCSIDiskReq *)opaque; @@ -174,9 +194,14 @@ static void scsi_read_data(SCSIRequest *req) return; } - n = scsi_init_iovec(r); - r->req.aiocb = bdrv_aio_readv(s->bs, r->sector, &r->qiov, n, - scsi_read_complete, r); + if (r->req.sg) { + r->req.aiocb = dma_bdrv_read(s->bs, r->req.sg, r->sector, + scsi_dma_complete, r); + } else { + n = scsi_init_iovec(r); + r->req.aiocb = bdrv_aio_readv(s->bs, r->sector, &r->qiov, n, + scsi_read_complete, r); + } if (r->req.aiocb == NULL) { scsi_read_complete(r, -EIO); } @@ -258,16 +283,21 @@ static void scsi_write_data(SCSIRequest *req) return; } - n = r->qiov.size / 512; - if (n) { + if (r->req.sg) { + r->req.aiocb = dma_bdrv_write(s->bs, r->req.sg, r->sector, + scsi_dma_complete, r); + } else { + n = r->qiov.size / 512; + if (!n) { + /* Called for the first time. Ask the driver to send us more data. */ + scsi_write_complete(r, 0); + return; + } r->req.aiocb = bdrv_aio_writev(s->bs, r->sector, &r->qiov, n, scsi_write_complete, r); - if (r->req.aiocb == NULL) { - scsi_write_complete(r, -ENOMEM); - } - } else { - /* Called for the first time. Ask the driver to send us more data. */ - scsi_write_complete(r, 0); + } + if (r->req.aiocb == NULL) { + scsi_write_complete(r, -ENOMEM); } } -- 1.7.6