diff options
Diffstat (limited to 'hw/scsi-disk.c')
-rw-r--r-- | hw/scsi-disk.c | 59 |
1 files changed, 55 insertions, 4 deletions
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 2a24840ef2..ec8e7cbffd 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -111,12 +111,12 @@ static void scsi_cancel_io(SCSIRequest *req) r->req.aiocb = NULL; } -static uint32_t scsi_init_iovec(SCSIDiskReq *r) +static uint32_t scsi_init_iovec(SCSIDiskReq *r, size_t size) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); if (!r->iov.iov_base) { - r->buflen = SCSI_DMA_BUF_SIZE; + r->buflen = size; r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen); } r->iov.iov_len = MIN(r->sector_count * 512, r->buflen); @@ -124,6 +124,35 @@ static uint32_t scsi_init_iovec(SCSIDiskReq *r) return r->qiov.size / 512; } +static void scsi_disk_save_request(QEMUFile *f, SCSIRequest *req) +{ + SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req); + + qemu_put_be64s(f, &r->sector); + qemu_put_be32s(f, &r->sector_count); + qemu_put_be32s(f, &r->buflen); + if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) { + qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len); + } +} + +static void scsi_disk_load_request(QEMUFile *f, SCSIRequest *req) +{ + SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req); + + qemu_get_be64s(f, &r->sector); + qemu_get_be32s(f, &r->sector_count); + qemu_get_be32s(f, &r->buflen); + if (r->buflen) { + scsi_init_iovec(r, r->buflen); + if (r->req.cmd.mode == SCSI_XFER_TO_DEV) { + qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len); + } + } + + qemu_iovec_init_external(&r->qiov, &r->iov, 1); +} + static void scsi_dma_complete(void *opaque, int ret) { SCSIDiskReq *r = (SCSIDiskReq *)opaque; @@ -241,7 +270,7 @@ static void scsi_read_data(SCSIRequest *req) r->req.aiocb = dma_bdrv_read(s->qdev.conf.bs, r->req.sg, r->sector, scsi_dma_complete, r); } else { - n = scsi_init_iovec(r); + n = scsi_init_iovec(r, SCSI_DMA_BUF_SIZE); bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ); r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n, scsi_read_complete, r); @@ -316,7 +345,7 @@ static void scsi_write_complete(void * opaque, int ret) if (r->sector_count == 0) { scsi_req_complete(&r->req, GOOD); } else { - scsi_init_iovec(r); + scsi_init_iovec(r, SCSI_DMA_BUF_SIZE); DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, r->qiov.size); scsi_req_data(&r->req, r->qiov.size); } @@ -1621,6 +1650,8 @@ static const SCSIReqOps scsi_disk_reqops = { .write_data = scsi_write_data, .cancel_io = scsi_cancel_io, .get_buf = scsi_get_buf, + .load_request = scsi_disk_load_request, + .save_request = scsi_disk_save_request, }; static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun, @@ -1755,6 +1786,22 @@ static Property scsi_hd_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +static const VMStateDescription vmstate_scsi_disk_state = { + .name = "scsi-disk", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_SCSI_DEVICE(qdev, SCSIDiskState), + VMSTATE_BOOL(media_changed, SCSIDiskState), + VMSTATE_BOOL(media_event, SCSIDiskState), + VMSTATE_BOOL(eject_request, SCSIDiskState), + VMSTATE_BOOL(tray_open, SCSIDiskState), + VMSTATE_BOOL(tray_locked, SCSIDiskState), + VMSTATE_END_OF_LIST() + } +}; + static void scsi_hd_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -1768,6 +1815,7 @@ static void scsi_hd_class_initfn(ObjectClass *klass, void *data) dc->desc = "virtual SCSI disk"; dc->reset = scsi_disk_reset; dc->props = scsi_hd_properties; + dc->vmsd = &vmstate_scsi_disk_state; } static TypeInfo scsi_hd_info = { @@ -1795,6 +1843,7 @@ static void scsi_cd_class_initfn(ObjectClass *klass, void *data) dc->desc = "virtual SCSI CD-ROM"; dc->reset = scsi_disk_reset; dc->props = scsi_cd_properties; + dc->vmsd = &vmstate_scsi_disk_state; } static TypeInfo scsi_cd_info = { @@ -1822,6 +1871,7 @@ static void scsi_block_class_initfn(ObjectClass *klass, void *data) dc->desc = "SCSI block device passthrough"; dc->reset = scsi_disk_reset; dc->props = scsi_block_properties; + dc->vmsd = &vmstate_scsi_disk_state; } static TypeInfo scsi_block_info = { @@ -1851,6 +1901,7 @@ static void scsi_disk_class_initfn(ObjectClass *klass, void *data) dc->desc = "virtual SCSI disk or CD-ROM (legacy)"; dc->reset = scsi_disk_reset; dc->props = scsi_disk_properties; + dc->vmsd = &vmstate_scsi_disk_state; } static TypeInfo scsi_disk_info = { |