diff options
author | Avi Kivity <avi@redhat.com> | 2009-04-09 17:51:08 +0300 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-04-09 17:51:08 +0300 |
commit | 7756cbe81190ab846ad09ce81fe6101a798eb646 (patch) | |
tree | d1496195da1826da9cd5f2b9ccd2dbb103677eda | |
parent | 67afa42dada0e8eab8b88bcc12447bddfccad5f7 (diff) | |
parent | 9d1b494a2d5dd2c129994edcf4eb7630bb554964 (diff) |
Merge commit 'qemu-svn/trunk'
-rw-r--r-- | CODING_STYLE | 2 | ||||
-rw-r--r-- | Changelog | 16 | ||||
-rw-r--r-- | block-qcow.c | 112 | ||||
-rw-r--r-- | block-qcow2.c | 122 | ||||
-rw-r--r-- | block-raw-posix.c | 113 | ||||
-rw-r--r-- | block-raw-win32.c | 33 | ||||
-rw-r--r-- | block.c | 189 | ||||
-rw-r--r-- | block.h | 7 | ||||
-rw-r--r-- | block_int.h | 8 | ||||
-rw-r--r-- | cmd.c | 2 | ||||
-rw-r--r-- | cmd.h | 2 | ||||
-rwxr-xr-x | configure | 19 | ||||
-rw-r--r-- | dma-helpers.c | 2 | ||||
-rw-r--r-- | hw/bt-hci.c | 26 | ||||
-rw-r--r-- | hw/bt-hid.c | 2 | ||||
-rw-r--r-- | hw/cirrus_vga.c | 11 | ||||
-rw-r--r-- | hw/fw_cfg.c | 4 | ||||
-rw-r--r-- | hw/ide.c | 10 | ||||
-rw-r--r-- | hw/lm832x.c | 6 | ||||
-rw-r--r-- | hw/scsi-disk.c | 125 | ||||
-rw-r--r-- | hw/vga.c | 276 | ||||
-rw-r--r-- | hw/vga_int.h | 4 | ||||
-rw-r--r-- | hw/wm8750.c | 2 | ||||
-rw-r--r-- | posix-aio-compat.c | 197 | ||||
-rw-r--r-- | posix-aio-compat.h | 9 | ||||
-rw-r--r-- | target-mips/helper.h | 8 | ||||
-rw-r--r-- | tcg/tcg.c | 12 | ||||
-rw-r--r-- | tcg/tcg.h | 8 | ||||
-rw-r--r-- | vnc.c | 2 |
29 files changed, 736 insertions, 593 deletions
diff --git a/CODING_STYLE b/CODING_STYLE index 1ab13b686..a579cb1b5 100644 --- a/CODING_STYLE +++ b/CODING_STYLE @@ -10,7 +10,7 @@ of approximately fifteen parsecs. Many a flamewar have been fought and lost on this issue. QEMU indents are four spaces. Tabs are never used, except in Makefiles -where they have been irreversibly coded into the syntax by some moron. +where they have been irreversibly coded into the syntax. Spaces of course are superior to tabs because: - You have just one way to specify whitespace, not two. Ambiguity breeds @@ -1,3 +1,19 @@ +version 0.10.2: + + - fix savevm/loadvm (Anthony Liguori) + - live migration: fix dirty tracking windows (Glauber Costa) + - live migration: improve error propogation (Glauber Costa) + - qcow2: fix image creation for > ~2TB images (Chris Wright) + - hotplug: fix error handling for if= parameter (Eduardo Habkost) + - qcow2: fix data corruption (Nolan Leake) + - virtio: fix guest oops with 2.6.25 kernels (Rusty Russell) + - SH4: add support for -kernel (Takashi Yoshii, Aurelien Jarno) + - hotplug: fix closing of char devices (Jan Kiszka) + - hotplug: remove incorrect check for device name (Eduardo Habkost) + - enable -k on win32 (Herve Poussineau) + - configure: use LANG=C for grep (Andreas Faerber) + - fix VGA regression (malc) + version 0.10.1: - virtio-net: check right return size on sg list (Alex Williamson) diff --git a/block-qcow.c b/block-qcow.c index 1fabc494d..b60f4c192 100644 --- a/block-qcow.c +++ b/block-qcow.c @@ -525,11 +525,15 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num, typedef struct QCowAIOCB { BlockDriverAIOCB common; int64_t sector_num; + QEMUIOVector *qiov; uint8_t *buf; + void *orig_buf; int nb_sectors; int n; uint64_t cluster_offset; uint8_t *cluster_data; + struct iovec hd_iov; + QEMUIOVector hd_qiov; BlockDriverAIOCB *hd_aiocb; } QCowAIOCB; @@ -541,12 +545,8 @@ static void qcow_aio_read_cb(void *opaque, int ret) int index_in_cluster; acb->hd_aiocb = NULL; - if (ret < 0) { - fail: - acb->common.cb(acb->common.opaque, ret); - qemu_aio_release(acb); - return; - } + if (ret < 0) + goto done; redo: /* post process the read buffer */ @@ -568,9 +568,8 @@ static void qcow_aio_read_cb(void *opaque, int ret) if (acb->nb_sectors == 0) { /* request completed */ - acb->common.cb(acb->common.opaque, 0); - qemu_aio_release(acb); - return; + ret = 0; + goto done; } /* prepare next AIO request */ @@ -584,10 +583,13 @@ static void qcow_aio_read_cb(void *opaque, int ret) if (!acb->cluster_offset) { if (bs->backing_hd) { /* read from the base image */ - acb->hd_aiocb = bdrv_aio_read(bs->backing_hd, - acb->sector_num, acb->buf, acb->n, qcow_aio_read_cb, acb); + acb->hd_iov.iov_base = acb->buf; + acb->hd_iov.iov_len = acb->n * 512; + qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1); + acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num, + &acb->hd_qiov, acb->n, qcow_aio_read_cb, acb); if (acb->hd_aiocb == NULL) - goto fail; + goto done; } else { /* Note: in this case, no need to wait */ memset(acb->buf, 0, 512 * acb->n); @@ -596,25 +598,38 @@ static void qcow_aio_read_cb(void *opaque, int ret) } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) { /* add AIO support for compressed blocks ? */ if (decompress_cluster(s, acb->cluster_offset) < 0) - goto fail; + goto done; memcpy(acb->buf, s->cluster_cache + index_in_cluster * 512, 512 * acb->n); goto redo; } else { if ((acb->cluster_offset & 511) != 0) { ret = -EIO; - goto fail; + goto done; } - acb->hd_aiocb = bdrv_aio_read(s->hd, + acb->hd_iov.iov_base = acb->buf; + acb->hd_iov.iov_len = acb->n * 512; + qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1); + acb->hd_aiocb = bdrv_aio_readv(s->hd, (acb->cluster_offset >> 9) + index_in_cluster, - acb->buf, acb->n, qcow_aio_read_cb, acb); + &acb->hd_qiov, acb->n, qcow_aio_read_cb, acb); if (acb->hd_aiocb == NULL) - goto fail; + goto done; } + + return; + +done: + if (acb->qiov->niov > 1) { + qemu_iovec_from_buffer(acb->qiov, acb->orig_buf, acb->qiov->size); + qemu_vfree(acb->orig_buf); + } + acb->common.cb(acb->common.opaque, ret); + qemu_aio_release(acb); } -static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs, - int64_t sector_num, uint8_t *buf, int nb_sectors, +static BlockDriverAIOCB *qcow_aio_readv(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { QCowAIOCB *acb; @@ -624,7 +639,11 @@ static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs, return NULL; acb->hd_aiocb = NULL; acb->sector_num = sector_num; - acb->buf = buf; + acb->qiov = qiov; + if (qiov->niov > 1) + acb->buf = acb->orig_buf = qemu_memalign(512, qiov->size); + else + acb->buf = qiov->iov->iov_base; acb->nb_sectors = nb_sectors; acb->n = 0; acb->cluster_offset = 0; @@ -644,12 +663,8 @@ static void qcow_aio_write_cb(void *opaque, int ret) acb->hd_aiocb = NULL; - if (ret < 0) { - fail: - acb->common.cb(acb->common.opaque, ret); - qemu_aio_release(acb); - return; - } + if (ret < 0) + goto done; acb->nb_sectors -= acb->n; acb->sector_num += acb->n; @@ -657,9 +672,8 @@ static void qcow_aio_write_cb(void *opaque, int ret) if (acb->nb_sectors == 0) { /* request completed */ - acb->common.cb(acb->common.opaque, 0); - qemu_aio_release(acb); - return; + ret = 0; + goto done; } index_in_cluster = acb->sector_num & (s->cluster_sectors - 1); @@ -671,14 +685,14 @@ static void qcow_aio_write_cb(void *opaque, int ret) index_in_cluster + acb->n); if (!cluster_offset || (cluster_offset & 511) != 0) { ret = -EIO; - goto fail; + goto done; } if (s->crypt_method) { if (!acb->cluster_data) { acb->cluster_data = qemu_mallocz(s->cluster_size); if (!acb->cluster_data) { ret = -ENOMEM; - goto fail; + goto done; } } encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf, @@ -687,16 +701,27 @@ static void qcow_aio_write_cb(void *opaque, int ret) } else { src_buf = acb->buf; } - acb->hd_aiocb = bdrv_aio_write(s->hd, - (cluster_offset >> 9) + index_in_cluster, - src_buf, acb->n, - qcow_aio_write_cb, acb); + + acb->hd_iov.iov_base = (void *)src_buf; + acb->hd_iov.iov_len = acb->n * 512; + qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1); + acb->hd_aiocb = bdrv_aio_writev(s->hd, + (cluster_offset >> 9) + index_in_cluster, + &acb->hd_qiov, acb->n, + qcow_aio_write_cb, acb); if (acb->hd_aiocb == NULL) - goto fail; + goto done; + return; + +done: + if (acb->qiov->niov > 1) + qemu_vfree(acb->orig_buf); + acb->common.cb(acb->common.opaque, ret); + qemu_aio_release(acb); } -static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs, - int64_t sector_num, const uint8_t *buf, int nb_sectors, +static BlockDriverAIOCB *qcow_aio_writev(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { BDRVQcowState *s = bs->opaque; @@ -709,7 +734,12 @@ static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs, return NULL; acb->hd_aiocb = NULL; acb->sector_num = sector_num; - acb->buf = (uint8_t *)buf; + acb->qiov = qiov; + if (qiov->niov > 1) { + acb->buf = acb->orig_buf = qemu_memalign(512, qiov->size); + qemu_iovec_to_buffer(qiov, acb->buf); + } else + acb->buf = qiov->iov->iov_base; acb->nb_sectors = nb_sectors; acb->n = 0; @@ -897,8 +927,8 @@ BlockDriver bdrv_qcow = { .bdrv_is_allocated = qcow_is_allocated, .bdrv_set_key = qcow_set_key, .bdrv_make_empty = qcow_make_empty, - .bdrv_aio_read = qcow_aio_read, - .bdrv_aio_write = qcow_aio_write, + .bdrv_aio_readv = qcow_aio_readv, + .bdrv_aio_writev = qcow_aio_writev, .bdrv_aio_cancel = qcow_aio_cancel, .aiocb_size = sizeof(QCowAIOCB), .bdrv_write_compressed = qcow_write_compressed, diff --git a/block-qcow2.c b/block-qcow2.c index 6eba524a2..3bd38b0d9 100644 --- a/block-qcow2.c +++ b/block-qcow2.c @@ -1264,12 +1264,16 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num, typedef struct QCowAIOCB { BlockDriverAIOCB common; int64_t sector_num; + QEMUIOVector *qiov; uint8_t *buf; + void *orig_buf; int nb_sectors; int n; uint64_t cluster_offset; uint8_t *cluster_data; BlockDriverAIOCB *hd_aiocb; + struct iovec hd_iov; + QEMUIOVector hd_qiov; QEMUBH *bh; QCowL2Meta l2meta; } QCowAIOCB; @@ -1305,12 +1309,8 @@ static void qcow_aio_read_cb(void *opaque, int ret) int index_in_cluster, n1; acb->hd_aiocb = NULL; - if (ret < 0) { -fail: - acb->common.cb(acb->common.opaque, ret); - qemu_aio_release(acb); - return; - } + if (ret < 0) + goto done; /* post process the read buffer */ if (!acb->cluster_offset) { @@ -1331,9 +1331,8 @@ fail: if (acb->nb_sectors == 0) { /* request completed */ - acb->common.cb(acb->common.opaque, 0); - qemu_aio_release(acb); - return; + ret = 0; + goto done; } /* prepare next AIO request */ @@ -1347,47 +1346,64 @@ fail: n1 = backing_read1(bs->backing_hd, acb->sector_num, acb->buf, acb->n); if (n1 > 0) { - acb->hd_aiocb = bdrv_aio_read(bs->backing_hd, acb->sector_num, - acb->buf, acb->n, qcow_aio_read_cb, acb); + acb->hd_iov.iov_base = acb->buf; + acb->hd_iov.iov_len = acb->n * 512; + qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1); + acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num, + &acb->hd_qiov, acb->n, + qcow_aio_read_cb, acb); if (acb->hd_aiocb == NULL) - goto fail; + goto done; } else { ret = qcow_schedule_bh(qcow_aio_read_bh, acb); if (ret < 0) - goto fail; + goto done; } } else { /* Note: in this case, no need to wait */ memset(acb->buf, 0, 512 * acb->n); ret = qcow_schedule_bh(qcow_aio_read_bh, acb); if (ret < 0) - goto fail; + goto done; } } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) { /* add AIO support for compressed blocks ? */ if (decompress_cluster(s, acb->cluster_offset) < 0) - goto fail; + goto done; memcpy(acb->buf, s->cluster_cache + index_in_cluster * 512, 512 * acb->n); ret = qcow_schedule_bh(qcow_aio_read_bh, acb); if (ret < 0) - goto fail; + goto done; } else { if ((acb->cluster_offset & 511) != 0) { ret = -EIO; - goto fail; + goto done; } - acb->hd_aiocb = bdrv_aio_read(s->hd, + + acb->hd_iov.iov_base = acb->buf; + acb->hd_iov.iov_len = acb->n * 512; + qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1); + acb->hd_aiocb = bdrv_aio_readv(s->hd, (acb->cluster_offset >> 9) + index_in_cluster, - acb->buf, acb->n, qcow_aio_read_cb, acb); + &acb->hd_qiov, acb->n, qcow_aio_read_cb, acb); if (acb->hd_aiocb == NULL) - goto fail; + goto done; + } + + return; +done: + if (acb->qiov->niov > 1) { + qemu_iovec_from_buffer(acb->qiov, acb->orig_buf, acb->qiov->size); + qemu_vfree(acb->orig_buf); } + acb->common.cb(acb->common.opaque, ret); + qemu_aio_release(acb); } static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs, - int64_t sector_num, uint8_t *buf, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque, int is_write) { QCowAIOCB *acb; @@ -1396,7 +1412,13 @@ static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs, return NULL; acb->hd_aiocb = NULL; acb->sector_num = sector_num; - acb->buf = buf; + acb->qiov = qiov; + if (qiov->niov > 1) { + acb->buf = acb->orig_buf = qemu_memalign(512, qiov->size); + if (is_write) + qemu_iovec_to_buffer(qiov, acb->buf); + } else + acb->buf = qiov->iov->iov_base; acb->nb_sectors = nb_sectors; acb->n = 0; acb->cluster_offset = 0; @@ -1404,13 +1426,13 @@ static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs, return acb; } -static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs, - int64_t sector_num, uint8_t *buf, int nb_sectors, +static BlockDriverAIOCB *qcow_aio_readv(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { QCowAIOCB *acb; - acb = qcow_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque); + acb = qcow_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0); if (!acb) return NULL; @@ -1429,16 +1451,12 @@ static void qcow_aio_write_cb(void *opaque, int ret) acb->hd_aiocb = NULL; - if (ret < 0) { - fail: - acb->common.cb(acb->common.opaque, ret); - qemu_aio_release(acb); - return; - } + if (ret < 0) + goto done; if (alloc_cluster_link_l2(bs, acb->cluster_offset, &acb->l2meta) < 0) { free_any_clusters(bs, acb->cluster_offset, acb->l2meta.nb_clusters); - goto fail; + goto done; } acb->nb_sectors -= acb->n; @@ -1447,9 +1465,8 @@ static void qcow_aio_write_cb(void *opaque, int ret) if (acb->nb_sectors == 0) { /* request completed */ - acb->common.cb(acb->common.opaque, 0); - qemu_aio_release(acb); - return; + ret = 0; + goto done; } index_in_cluster = acb->sector_num & (s->cluster_sectors - 1); @@ -1463,7 +1480,7 @@ static void qcow_aio_write_cb(void *opaque, int ret) n_end, &acb->n, &acb->l2meta); if (!acb->cluster_offset || (acb->cluster_offset & 511) != 0) { ret = -EIO; - goto fail; + goto done; } if (s->crypt_method) { if (!acb->cluster_data) { @@ -1476,16 +1493,27 @@ static void qcow_aio_write_cb(void *opaque, int ret) } else { src_buf = acb->buf; } - acb->hd_aiocb = bdrv_aio_write(s->hd, - (acb->cluster_offset >> 9) + index_in_cluster, - src_buf, acb->n, - qcow_aio_write_cb, acb); + acb->hd_iov.iov_base = (void *)src_buf; + acb->hd_iov.iov_len = acb->n * 512; + qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1); + acb->hd_aiocb = bdrv_aio_writev(s->hd, + (acb->cluster_offset >> 9) + index_in_cluster, + &acb->hd_qiov, acb->n, + qcow_aio_write_cb, acb); if (acb->hd_aiocb == NULL) - goto fail; + goto done; + + return; + +done: + if (acb->qiov->niov > 1) + qemu_vfree(acb->orig_buf); + acb->common.cb(acb->common.opaque, ret); + qemu_aio_release(acb); } -static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs, - int64_t sector_num, const uint8_t *buf, int nb_sectors, +static BlockDriverAIOCB *qcow_aio_writev(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { BDRVQcowState *s = bs->opaque; @@ -1493,7 +1521,7 @@ static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs, s->cluster_cache_offset = -1; /* disable compressed cache */ - acb = qcow_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque); + acb = qcow_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 1); if (!acb) return NULL; @@ -2758,8 +2786,8 @@ BlockDriver bdrv_qcow2 = { .bdrv_set_key = qcow_set_key, .bdrv_make_empty = qcow_make_empty, - .bdrv_aio_read = qcow_aio_read, - .bdrv_aio_write = qcow_aio_write, + .bdrv_aio_readv = qcow_aio_readv, + .bdrv_aio_writev = qcow_aio_writev, .bdrv_aio_cancel = qcow_aio_cancel, .aiocb_size = sizeof(QCowAIOCB), .bdrv_write_compressed = qcow_write_compressed, diff --git a/block-raw-posix.c b/block-raw-posix.c index a972f80ae..f033baee5 100644 --- a/block-raw-posix.c +++ b/block-raw-posix.c @@ -596,8 +596,8 @@ static int posix_aio_init(void) return 0; } -static RawAIOCB *raw_aio_setup(BlockDriverState *bs, - int64_t sector_num, uint8_t *buf, int nb_sectors, +static RawAIOCB *raw_aio_setup(BlockDriverState *bs, int64_t sector_num, + QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { BDRVRawState *s = bs->opaque; @@ -611,24 +611,25 @@ static RawAIOCB *raw_aio_setup(BlockDriverState *bs, return NULL; acb->aiocb.aio_fildes = s->fd; acb->aiocb.ev_signo = SIGUSR2; - acb->aiocb.aio_buf = buf; - if (nb_sectors < 0) - acb->aiocb.aio_nbytes = -nb_sectors; - else - acb->aiocb.aio_nbytes = nb_sectors * 512; + acb->aiocb.aio_iov = qiov->iov; + acb->aiocb.aio_niov = qiov->niov; + acb->aiocb.aio_nbytes = nb_sectors * 512; acb->aiocb.aio_offset = sector_num * 512; + acb->aiocb.aio_flags = 0; + + /* + * If O_DIRECT is used the buffer needs to be aligned on a sector + * boundary. Tell the low level code to ensure that in case it's + * not done yet. + */ + if (s->aligned_buf) + acb->aiocb.aio_flags |= QEMU_AIO_SECTOR_ALIGNED; + acb->next = posix_aio_state->first_aio; posix_aio_state->first_aio = acb; return acb; } -static void raw_aio_em_cb(void* opaque) -{ - RawAIOCB *acb = opaque; - acb->common.cb(acb->common.opaque, acb->ret); - qemu_aio_release(acb); -} - static void raw_aio_remove(RawAIOCB *acb) { RawAIOCB **pacb; @@ -648,28 +649,13 @@ static void raw_aio_remove(RawAIOCB *acb) } } -static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs, - int64_t sector_num, uint8_t *buf, int nb_sectors, +static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { RawAIOCB *acb; - /* - * If O_DIRECT is used and the buffer is not aligned fall back - * to synchronous IO. - */ - BDRVRawState *s = bs->opaque; - - if (unlikely(s->aligned_buf != NULL && ((uintptr_t) buf % 512))) { - QEMUBH *bh; - acb = qemu_aio_get(bs, cb, opaque); - acb->ret = raw_pread(bs, 512 * sector_num, buf, 512 * nb_sectors); - bh = qemu_bh_new(raw_aio_em_cb, acb); - qemu_bh_schedule(bh); - return &acb->common; - } - - acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque); + acb = raw_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque); if (!acb) return NULL; if (qemu_paio_read(&acb->aiocb) < 0) { @@ -679,28 +665,13 @@ static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs, return &acb->common; } -static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs, - int64_t sector_num, const uint8_t *buf, int nb_sectors, +static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { RawAIOCB *acb; - /* - * If O_DIRECT is used and the buffer is not aligned fall back - * to synchronous IO. - */ - BDRVRawState *s = bs->opaque; - - if (unlikely(s->aligned_buf != NULL && ((uintptr_t) buf % 512))) { - QEMUBH *bh; - acb = qemu_aio_get(bs, cb, opaque); - acb->ret = raw_pwrite(bs, 512 * sector_num, buf, 512 * nb_sectors); - bh = qemu_bh_new(raw_aio_em_cb, acb); - qemu_bh_schedule(bh); - return &acb->common; - } - - acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque); + acb = raw_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque); if (!acb) return NULL; if (qemu_paio_write(&acb->aiocb) < 0) { @@ -873,25 +844,23 @@ static void raw_flush(BlockDriverState *bs) } BlockDriver bdrv_raw = { - "raw", - sizeof(BDRVRawState), - NULL, /* no probe for protocols */ - raw_open, - NULL, - NULL, - raw_close, - raw_create, - raw_flush, + .format_name = "raw", + .instance_size = sizeof(BDRVRawState), + .bdrv_probe = NULL, /* no probe for protocols */ + .bdrv_open = raw_open, + .bdrv_read = raw_read, + .bdrv_write = raw_write, + .bdrv_close = raw_close, + .bdrv_create = raw_create, + .bdrv_flush = raw_flush, #ifdef CONFIG_AIO - .bdrv_aio_read = raw_aio_read, - .bdrv_aio_write = raw_aio_write, + .bdrv_aio_readv = raw_aio_readv, + .bdrv_aio_writev = raw_aio_writev, .bdrv_aio_cancel = raw_aio_cancel, .aiocb_size = sizeof(RawAIOCB), #endif - .bdrv_read = raw_read, - .bdrv_write = raw_write, .bdrv_truncate = raw_truncate, .bdrv_getlength = raw_getlength, }; @@ -1214,12 +1183,24 @@ static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs, unsigned long int req, void *buf, BlockDriverCompletionFunc *cb, void *opaque) { + BDRVRawState *s = bs->opaque; RawAIOCB *acb; - acb = raw_aio_setup(bs, 0, buf, 0, cb, opaque); + if (fd_open(bs) < 0) + return NULL; + + acb = qemu_aio_get(bs, cb, opaque); if (!acb) return NULL; + acb->aiocb.aio_fildes = s->fd; + acb->aiocb.ev_signo = SIGUSR2; + acb->aiocb.aio_offset = 0; + acb->aiocb.aio_flags = 0; + + acb->next = posix_aio_state->first_aio; + posix_aio_state->first_aio = acb; + acb->aiocb.aio_ioctl_buf = buf; acb->aiocb.aio_ioctl_cmd = req; if (qemu_paio_ioctl(&acb->aiocb) < 0) { raw_aio_remove(acb); @@ -1423,8 +1404,8 @@ BlockDriver bdrv_host_device = { .bdrv_flush = raw_flush, #ifdef CONFIG_AIO - .bdrv_aio_read = raw_aio_read, - .bdrv_aio_write = raw_aio_write, + .bdrv_aio_readv = raw_aio_readv, + .bdrv_aio_writev = raw_aio_writev, .bdrv_aio_cancel = raw_aio_cancel, .aiocb_size = sizeof(RawAIOCB), #endif diff --git a/block-raw-win32.c b/block-raw-win32.c index af9cc6db3..b5287d2a5 100644 --- a/block-raw-win32.c +++ b/block-raw-win32.c @@ -229,20 +229,16 @@ static int raw_create(const char *filename, int64_t total_size, } BlockDriver bdrv_raw = { - "raw", - sizeof(BDRVRawState), - NULL, /* no probe for protocols */ - raw_open, - NULL, - NULL, - raw_close, - raw_create, - raw_flush, - - .bdrv_read = raw_read, - .bdrv_write = raw_write, - .bdrv_truncate = raw_truncate, - .bdrv_getlength = raw_getlength, + .format_name = "raw", + .instance_size = sizeof(BDRVRawState), + .bdrv_open = raw_open, + .bdrv_close = raw_close, + .bdrv_create = raw_create, + .bdrv_flush = raw_flush, + .bdrv_read = raw_read, + .bdrv_write = raw_write, + .bdrv_truncate = raw_truncate, + .bdrv_getlength = raw_getlength, }; /***********************************************/ @@ -280,10 +276,15 @@ static int find_device_type(BlockDriverState *bs, const char *filename) return FTYPE_HARDDISK; snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", p[0]); type = GetDriveType(s->drive_path); - if (type == DRIVE_CDROM) + switch (type) { + case DRIVE_REMOVABLE: + case DRIVE_FIXED: + return FTYPE_HARDDISK; + case DRIVE_CDROM: return FTYPE_CD; - else + default: return FTYPE_FILE; + } } else { return FTYPE_FILE; } @@ -48,19 +48,21 @@ #define SECTOR_BITS 9 #define SECTOR_SIZE (1 << SECTOR_BITS) -static AIOPool vectored_aio_pool; - typedef struct BlockDriverAIOCBSync { BlockDriverAIOCB common; QEMUBH *bh; int ret; + /* vector translation state */ + QEMUIOVector *qiov; + uint8_t *bounce; + int is_write; } BlockDriverAIOCBSync; -static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs, - int64_t sector_num, uint8_t *buf, int nb_sectors, +static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque); -static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs, - int64_t sector_num, const uint8_t *buf, int nb_sectors, +static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque); static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb); static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, @@ -139,10 +141,10 @@ void path_combine(char *dest, int dest_size, static void bdrv_register(BlockDriver *bdrv) { - if (!bdrv->bdrv_aio_read) { + if (!bdrv->bdrv_aio_readv) { /* add AIO emulation layer */ - bdrv->bdrv_aio_read = bdrv_aio_read_em; - bdrv->bdrv_aio_write = bdrv_aio_write_em; + bdrv->bdrv_aio_readv = bdrv_aio_readv_em; + bdrv->bdrv_aio_writev = bdrv_aio_writev_em; bdrv->bdrv_aio_cancel = bdrv_aio_cancel_em; bdrv->aiocb_size = sizeof(BlockDriverAIOCBSync); } else if (!bdrv->bdrv_read) { @@ -1298,91 +1300,10 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn) /**************************************************************/ /* async I/Os */ -typedef struct VectorTranslationAIOCB { - BlockDriverAIOCB common; - QEMUIOVector *iov; - uint8_t *bounce; - int is_write; - BlockDriverAIOCB *aiocb; -} VectorTranslationAIOCB; - -static void bdrv_aio_cancel_vector(BlockDriverAIOCB *_acb) -{ - VectorTranslationAIOCB *acb - = container_of(_acb, VectorTranslationAIOCB, common); - - bdrv_aio_cancel(acb->aiocb); -} - -static void bdrv_aio_rw_vector_cb(void *opaque, int ret) -{ - VectorTranslationAIOCB *s = (VectorTranslationAIOCB *)opaque; - - if (!s->is_write) { - qemu_iovec_from_buffer(s->iov, s->bounce, s->iov->size); - } - qemu_vfree(s->bounce); - s->common.cb(s->common.opaque, ret); - qemu_aio_release(s); -} - -static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *iov, - int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque, - int is_write) - -{ - VectorTranslationAIOCB *s = qemu_aio_get_pool(&vectored_aio_pool, bs, - cb, opaque); - - s->iov = iov; - s->bounce = qemu_memalign(512, nb_sectors * 512); - s->is_write = is_write; - if (is_write) { - qemu_iovec_to_buffer(s->iov, s->bounce); - s->aiocb = bdrv_aio_write(bs, sector_num, s->bounce, nb_sectors, - bdrv_aio_rw_vector_cb, s); - } else { - s->aiocb = bdrv_aio_read(bs, sector_num, s->bounce, nb_sectors, - bdrv_aio_rw_vector_cb, s); - } - if (!s->aiocb) { - qemu_vfree(s->bounce); - qemu_aio_release(s); - return NULL; - } - return &s->common; -} - BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num, - QEMUIOVector *iov, int nb_sectors, + QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { - if (bdrv_check_request(bs, sector_num, nb_sectors)) - return NULL; - - return bdrv_aio_rw_vector(bs, sector_num, iov, nb_sectors, - cb, opaque, 0); -} - -BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, - QEMUIOVector *iov, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) -{ - if (bdrv_check_request(bs, sector_num, nb_sectors)) - return NULL; - - return bdrv_aio_rw_vector(bs, sector_num, iov, nb_sectors, - cb, opaque, 1); -} - -BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) -{ BlockDriver *drv = bs->drv; BlockDriverAIOCB *ret; @@ -1391,7 +1312,8 @@ BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num, if (bdrv_check_request(bs, sector_num, nb_sectors)) return NULL; - ret = drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque); + ret = drv->bdrv_aio_readv(bs, sector_num, qiov, nb_sectors, + cb, opaque); if (ret) { /* Update stats even though technically transfer has not happened. */ @@ -1402,9 +1324,9 @@ BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num, return ret; } -BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num, - const uint8_t *buf, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) +BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, + QEMUIOVector *qiov, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) { BlockDriver *drv = bs->drv; BlockDriverAIOCB *ret; @@ -1416,7 +1338,8 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num, if (bdrv_check_request(bs, sector_num, nb_sectors)) return NULL; - ret = drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque); + ret = drv->bdrv_aio_writev(bs, sector_num, qiov, nb_sectors, + cb, opaque); if (ret) { /* Update stats even though technically transfer has not happened. */ @@ -1439,42 +1362,61 @@ void bdrv_aio_cancel(BlockDriverAIOCB *acb) static void bdrv_aio_bh_cb(void *opaque) { BlockDriverAIOCBSync *acb = opaque; + + if (!acb->is_write) + qemu_iovec_from_buffer(acb->qiov, acb->bounce, acb->qiov->size); + qemu_vfree(acb->bounce); acb->common.cb(acb->common.opaque, acb->ret); + qemu_aio_release(acb); } -static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs, - int64_t sector_num, uint8_t *buf, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) +static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs, + int64_t sector_num, + QEMUIOVector *qiov, + int nb_sectors, + BlockDriverCompletionFunc *cb, + void *opaque, + int is_write) + { BlockDriverAIOCBSync *acb; - int ret; acb = qemu_aio_get(bs, cb, opaque); + acb->is_write = is_write; + acb->qiov = qiov; + acb->bounce = qemu_memalign(512, qiov->size); + if (!acb->bh) acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb); - ret = bdrv_read(bs, sector_num, buf, nb_sectors); - acb->ret = ret; + + if (is_write) { + qemu_iovec_to_buffer(acb->qiov, acb->bounce); + acb->ret = bdrv_write(bs, sector_num, acb->bounce, nb_sectors); + } else { + acb->ret = bdrv_read(bs, sector_num, acb->bounce, nb_sectors); + } + qemu_bh_schedule(acb->bh); + return &acb->common; } -static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs, - int64_t sector_num, const uint8_t *buf, int nb_sectors, +static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { - BlockDriverAIOCBSync *acb; - int ret; + return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 0); +} - acb = qemu_aio_get(bs, cb, opaque); - if (!acb->bh) - acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb); - ret = bdrv_write(bs, sector_num, buf, nb_sectors); - acb->ret = ret; - qemu_bh_schedule(acb->bh); - return &acb->common; +static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) +{ + return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 1); } + static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb) { BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb; @@ -1497,10 +1439,15 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, { int async_ret; BlockDriverAIOCB *acb; + struct iovec iov; + QEMUIOVector qiov; async_ret = NOT_DONE; - acb = bdrv_aio_read(bs, sector_num, buf, nb_sectors, - bdrv_rw_em_cb, &async_ret); + iov.iov_base = buf; + iov.iov_len = nb_sectors * 512; + qemu_iovec_init_external(&qiov, &iov, 1); + acb = bdrv_aio_readv(bs, sector_num, &qiov, nb_sectors, + bdrv_rw_em_cb, &async_ret); if (acb == NULL) return -1; @@ -1516,10 +1463,15 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num, { int async_ret; BlockDriverAIOCB *acb; + struct iovec iov; + QEMUIOVector qiov; async_ret = NOT_DONE; - acb = bdrv_aio_write(bs, sector_num, buf, nb_sectors, - bdrv_rw_em_cb, &async_ret); + iov.iov_base = (void *)buf; + iov.iov_len = nb_sectors * 512; + qemu_iovec_init_external(&qiov, &iov, 1); + acb = bdrv_aio_writev(bs, sector_num, &qiov, nb_sectors, + bdrv_rw_em_cb, &async_ret); if (acb == NULL) return -1; while (async_ret == NOT_DONE) { @@ -1530,9 +1482,6 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num, void bdrv_init(void) { - aio_pool_init(&vectored_aio_pool, sizeof(VectorTranslationAIOCB), - bdrv_aio_cancel_vector); - bdrv_register(&bdrv_raw); bdrv_register(&bdrv_host_device); #ifndef _WIN32 @@ -96,13 +96,6 @@ BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num, BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *iov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque); - -BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); -BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num, - const uint8_t *buf, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque); void bdrv_aio_cancel(BlockDriverAIOCB *acb); /* sg packet commands */ diff --git a/block_int.h b/block_int.h index a59f54c4c..31609aa01 100644 --- a/block_int.h +++ b/block_int.h @@ -54,11 +54,11 @@ struct BlockDriver { int (*bdrv_set_key)(BlockDriverState *bs, const char *key); int (*bdrv_make_empty)(BlockDriverState *bs); /* aio */ - BlockDriverAIOCB *(*bdrv_aio_read)(BlockDriverState *bs, - int64_t sector_num, uint8_t *buf, int nb_sectors, + BlockDriverAIOCB *(*bdrv_aio_readv)(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque); - BlockDriverAIOCB *(*bdrv_aio_write)(BlockDriverState *bs, - int64_t sector_num, const uint8_t *buf, int nb_sectors, + BlockDriverAIOCB *(*bdrv_aio_writev)(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque); void (*bdrv_aio_cancel)(BlockDriverAIOCB *acb); int aiocb_size; @@ -212,8 +212,6 @@ command_loop(void) # include <histedit.h> #endif -extern char *progname; - static char * get_prompt(void) { @@ -75,4 +75,6 @@ enum { extern void timestr(struct timeval *tv, char *str, size_t sz, int flags); +extern char *progname; + #endif /* __COMMAND_H__ */ @@ -572,6 +572,8 @@ echo " --source-path=PATH path of source code [$source_path]" echo " --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]" echo " --cc=CC use C compiler CC [$cc]" echo " --host-cc=CC use C compiler CC [$host_cc] for dyngen etc." +echo " --extra-cflags=CFLAGS add C compiler flags CFLAGS" +echo " --extra-ldflags=LDFLAGS add linker flags LDFLAGS" echo " --make=MAKE use specified make [$make]" echo " --install=INSTALL use specified install [$install]" echo " --static enable static build [$static]" @@ -1179,6 +1181,19 @@ if $cc $ARCH_CFLAGS -o $TMPE $TMPC > /dev/null 2> /dev/null ; then fi ########################################## +# preadv probe +cat > $TMPC <<EOF +#include <sys/types.h> +#include <sys/uio.h> +#include <unistd.h> +int main(void) { preadv; } +EOF +preadv=no +if $cc $ARCH_CFLAGS -o $TMPE $TMPC > /dev/null 2> /dev/null ; then + preadv=yes +fi + +########################################## # fdt probe if test "$fdt" = "yes" ; then fdt=no @@ -1321,6 +1336,7 @@ echo "AIO support $aio" echo "Install blobs $blobs" echo "KVM support $kvm" echo "fdt support $fdt" +echo "preadv support $preadv" if test $sdl_too_old = "yes"; then echo "-> Your SDL version is too old - please upgrade to have SDL support" @@ -1623,6 +1639,9 @@ fi if test "$iovec" = "yes" ; then echo "#define HAVE_IOVEC 1" >> $config_h fi +if test "$preadv" = "yes" ; then + echo "#define HAVE_PREADV 1" >> $config_h +fi if test "$fdt" = "yes" ; then echo "#define HAVE_FDT 1" >> $config_h echo "FDT_LIBS=-lfdt" >> $config_mak diff --git a/dma-helpers.c b/dma-helpers.c index 1469e34df..f9eb2240b 100644 --- a/dma-helpers.c +++ b/dma-helpers.c @@ -81,7 +81,7 @@ static void dma_bdrv_unmap(DMAAIOCB *dbs) } } -void dma_bdrv_cb(void *opaque, int ret) +static void dma_bdrv_cb(void *opaque, int ret) { DMAAIOCB *dbs = (DMAAIOCB *)opaque; target_phys_addr_t cur_addr, cur_len; diff --git a/hw/bt-hci.c b/hw/bt-hci.c index 7e93e26c8..a5902b03f 100644 --- a/hw/bt-hci.c +++ b/hw/bt-hci.c @@ -564,9 +564,11 @@ static void bt_hci_inquiry_result(struct bt_hci_s *hci, switch (hci->lm.inquiry_mode) { case 0x00: - return bt_hci_inquiry_result_standard(hci, slave); + bt_hci_inquiry_result_standard(hci, slave); + return; case 0x01: - return bt_hci_inquiry_result_with_rssi(hci, slave); + bt_hci_inquiry_result_with_rssi(hci, slave); + return; default: fprintf(stderr, "%s: bad inquiry mode %02x\n", __FUNCTION__, hci->lm.inquiry_mode); @@ -771,9 +773,11 @@ static void bt_hci_lmp_connection_request(struct bt_link_s *link) struct bt_hci_s *hci = hci_from_device(link->slave); evt_conn_request params; - if (hci->conn_req_host) - return bt_hci_connection_reject(hci, link->host, - HCI_REJECTED_LIMITED_RESOURCES); + if (hci->conn_req_host) { + bt_hci_connection_reject(hci, link->host, + HCI_REJECTED_LIMITED_RESOURCES); + return; + } hci->conn_req_host = link->host; /* TODO: if masked and auto-accept, then auto-accept, * if masked and not auto-accept, then auto-reject */ @@ -2125,7 +2129,7 @@ static void bt_hci_evt_submit(void *opaque, int len) /* TODO: notify upper layer */ struct bt_hci_s *s = opaque; - return s->info.evt_recv(s->info.opaque, s->evt_buf, len); + s->info.evt_recv(s->info.opaque, s->evt_buf, len); } static int bt_hci_bdaddr_set(struct HCIInfo *info, const uint8_t *bd_addr) @@ -2141,7 +2145,7 @@ static void bt_hci_destroy(struct bt_device_s *dev) { struct bt_hci_s *hci = hci_from_device(dev); - return bt_hci_done(&hci->info); + bt_hci_done(&hci->info); } struct HCIInfo *bt_new_hci(struct bt_scatternet_s *net) @@ -2196,9 +2200,11 @@ static void bt_hci_done(struct HCIInfo *info) /* Be gentle and send DISCONNECT to all connected peers and those * currently waiting for us to accept or reject a connection request. * This frees the links. */ - if (hci->conn_req_host) - return bt_hci_connection_reject(hci, - hci->conn_req_host, HCI_OE_POWER_OFF); + if (hci->conn_req_host) { + bt_hci_connection_reject(hci, + hci->conn_req_host, HCI_OE_POWER_OFF); + return; + } for (handle = HCI_HANDLE_OFFSET; handle < (HCI_HANDLE_OFFSET | HCI_HANDLES_MAX); handle ++) diff --git a/hw/bt-hid.c b/hw/bt-hid.c index 3317ecc03..af0c3d5f2 100644 --- a/hw/bt-hid.c +++ b/hw/bt-hid.c @@ -383,7 +383,7 @@ static void bt_hid_control_sdu(void *opaque, const uint8_t *data, int len) { struct bt_hid_device_s *hid = opaque; - return bt_hid_control_transaction(hid, data, len); + bt_hid_control_transaction(hid, data, len); } static void bt_hid_datain(void *opaque) diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index e79dd1765..dfbb59ad7 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -1393,8 +1393,6 @@ cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value) break; } - vga_update_resolution((VGAState *)s); - return CIRRUS_HOOK_HANDLED; } @@ -1422,7 +1420,6 @@ static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value) #endif } s->cirrus_hidden_dac_lockindex = 0; - vga_update_resolution((VGAState *)s); } /*************************************** @@ -1709,8 +1706,6 @@ cirrus_hook_write_cr(CirrusVGAState * s, unsigned reg_index, int reg_value) break; } - vga_update_resolution((VGAState *)s); - return CIRRUS_HOOK_HANDLED; } @@ -2838,7 +2833,6 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) if (s->ar_flip_flop == 0) { val &= 0x3f; s->ar_index = val; - vga_update_resolution((VGAState *)s); } else { index = s->ar_index & 0x1f; switch (index) { @@ -2932,7 +2926,6 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) /* can always write bit 4 of CR7 */ if (s->cr_index == 7) s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10); - vga_update_resolution((VGAState *)s); return; } switch (s->cr_index) { @@ -2961,7 +2954,6 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) s->update_retrace_info((VGAState *) s); break; } - vga_update_resolution((VGAState *)s); break; case 0x3ba: case 0x3da: @@ -3168,8 +3160,7 @@ static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id) cirrus_update_memory_access(s); /* force refresh */ - vga_update_resolution((VGAState *)s); - s->want_full_update = 1; + s->graphic_mode = -1; cirrus_update_bank_ptr(s, 0); cirrus_update_bank_ptr(s, 1); return 0; diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c index e324e8d7b..e1b19d72e 100644 --- a/hw/fw_cfg.c +++ b/hw/fw_cfg.c @@ -108,7 +108,7 @@ static uint32_t fw_cfg_io_readb(void *opaque, uint32_t addr) static void fw_cfg_io_writeb(void *opaque, uint32_t addr, uint32_t value) { - return fw_cfg_write(opaque, (uint8_t)value); + fw_cfg_write(opaque, (uint8_t)value); } static void fw_cfg_io_writew(void *opaque, uint32_t addr, uint32_t value) @@ -124,7 +124,7 @@ static uint32_t fw_cfg_mem_readb(void *opaque, target_phys_addr_t addr) static void fw_cfg_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t value) { - return fw_cfg_write(opaque, (uint8_t)value); + fw_cfg_write(opaque, (uint8_t)value); } static void fw_cfg_mem_writew(void *opaque, target_phys_addr_t addr, @@ -496,6 +496,8 @@ typedef struct BMDMAState { IDEState *ide_if; BlockDriverCompletionFunc *dma_cb; BlockDriverAIOCB *aiocb; + struct iovec iov; + QEMUIOVector qiov; int64_t sector_num; uint32_t nsector; } BMDMAState; @@ -1467,9 +1469,11 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret) #ifdef DEBUG_AIO printf("aio_read_cd: lba=%u n=%d\n", s->lba, n); #endif - bm->aiocb = bdrv_aio_read(s->bs, (int64_t)s->lba << 2, - s->io_buffer + data_offset, n * 4, - ide_atapi_cmd_read_dma_cb, bm); + bm->iov.iov_base = s->io_buffer + data_offset; + bm->iov.iov_len = n * 4 * 512; + qemu_iovec_init_external(&bm->qiov, &bm->iov, 1); + bm->aiocb = bdrv_aio_readv(s->bs, (int64_t)s->lba << 2, &bm->qiov, + n * 4, ide_atapi_cmd_read_dma_cb, bm); if (!bm->aiocb) { /* Note: media not present is the most likely case */ ide_atapi_cmd_error(s, SENSE_NOT_READY, diff --git a/hw/lm832x.c b/hw/lm832x.c index dd94310f6..6479e1487 100644 --- a/hw/lm832x.c +++ b/hw/lm832x.c @@ -519,8 +519,10 @@ void lm832x_key_event(struct i2c_slave *i2c, int key, int state) if ((s->status & INT_ERROR) && (s->error & ERR_FIFOOVR)) return; - if (s->kbd.len >= sizeof(s->kbd.fifo)) - return lm_kbd_error(s, ERR_FIFOOVR); + if (s->kbd.len >= sizeof(s->kbd.fifo)) { + lm_kbd_error(s, ERR_FIFOOVR); + return; + } s->kbd.fifo[(s->kbd.start + s->kbd.len ++) & (sizeof(s->kbd.fifo) - 1)] = key | (state << 7); diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index c7b2febd8..2edd047a8 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -52,9 +52,8 @@ typedef struct SCSIRequest { /* Both sector and sector_count are in terms of qemu 512 byte blocks. */ uint64_t sector; uint32_t sector_count; - /* The amounnt of data in the buffer. */ - int buf_len; - uint8_t *dma_buf; + struct iovec iov; + QEMUIOVector qiov; BlockDriverAIOCB *aiocb; struct SCSIRequest *next; uint32_t status; @@ -89,12 +88,12 @@ static SCSIRequest *scsi_new_request(SCSIDeviceState *s, uint32_t tag) free_requests = r->next; } else { r = qemu_malloc(sizeof(SCSIRequest)); - r->dma_buf = qemu_memalign(512, SCSI_DMA_BUF_SIZE); + r->iov.iov_base = qemu_memalign(512, SCSI_DMA_BUF_SIZE); } r->dev = s; r->tag = tag; r->sector_count = 0; - r->buf_len = 0; + r->iov.iov_len = 0; r->aiocb = NULL; r->status = 0; @@ -173,9 +172,9 @@ static void scsi_read_complete(void * opaque, int ret) scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NO_SENSE); return; } - DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, r->buf_len); + DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, r->iov.iov_len); - s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->buf_len); + s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->iov.iov_len); } /* Read more data from scsi device into buffer. */ @@ -193,9 +192,9 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag) return; } if (r->sector_count == (uint32_t)-1) { - DPRINTF("Read buf_len=%d\n", r->buf_len); + DPRINTF("Read buf_len=%d\n", r->iov.iov_len); r->sector_count = 0; - s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->buf_len); + s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->iov.iov_len); return; } DPRINTF("Read sector_count=%d\n", r->sector_count); @@ -208,9 +207,10 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag) if (n > SCSI_DMA_BUF_SIZE / 512) n = SCSI_DMA_BUF_SIZE / 512; - r->buf_len = n * 512; - r->aiocb = bdrv_aio_read(s->bdrv, r->sector, r->dma_buf, n, - scsi_read_complete, r); + r->iov.iov_len = n * 512; + qemu_iovec_init_external(&r->qiov, &r->iov, 1); + r->aiocb = bdrv_aio_readv(s->bdrv, r->sector, &r->qiov, n, + scsi_read_complete, r); if (r->aiocb == NULL) scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR); r->sector += n; @@ -250,7 +250,7 @@ static void scsi_write_complete(void * opaque, int ret) return; } - n = r->buf_len / 512; + n = r->iov.iov_len / 512; r->sector += n; r->sector_count -= n; if (r->sector_count == 0) { @@ -260,7 +260,7 @@ static void scsi_write_complete(void * opaque, int ret) if (len > SCSI_DMA_BUF_SIZE) { len = SCSI_DMA_BUF_SIZE; } - r->buf_len = len; + r->iov.iov_len = len; DPRINTF("Write complete tag=0x%x more=%d\n", r->tag, len); s->completion(s->opaque, SCSI_REASON_DATA, r->tag, len); } @@ -271,10 +271,11 @@ static void scsi_write_request(SCSIRequest *r) SCSIDeviceState *s = r->dev; uint32_t n; - n = r->buf_len / 512; + n = r->iov.iov_len / 512; if (n) { - r->aiocb = bdrv_aio_write(s->bdrv, r->sector, r->dma_buf, n, - scsi_write_complete, r); + qemu_iovec_init_external(&r->qiov, &r->iov, 1); + r->aiocb = bdrv_aio_writev(s->bdrv, r->sector, &r->qiov, n, + scsi_write_complete, r); if (r->aiocb == NULL) scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR); @@ -334,7 +335,7 @@ static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag) BADF("Bad buffer tag 0x%x\n", tag); return NULL; } - return r->dma_buf; + return r->iov.iov_base; } /* Execute a scsi command. Returns the length of the data expected by the @@ -364,7 +365,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, /* ??? Tags are not unique for different luns. We only implement a single lun, so this should not matter. */ r = scsi_new_request(s, tag); - outbuf = r->dma_buf; + outbuf = r->iov.iov_base; is_write = 0; DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]); switch (command >> 5) { @@ -425,10 +426,10 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, if (len < 4) goto fail; memset(outbuf, 0, 4); - r->buf_len = 4; + r->iov.iov_len = 4; if (s->sense == SENSE_NOT_READY && len >= 18) { memset(outbuf, 0, 18); - r->buf_len = 18; + r->iov.iov_len = 18; outbuf[7] = 10; /* asc 0x3a, ascq 0: Medium not present */ outbuf[12] = 0x3a; @@ -461,20 +462,20 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, DPRINTF("Inquiry EVPD[Supported pages] " "buffer size %d\n", len); - r->buf_len = 0; + r->iov.iov_len = 0; if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) { - outbuf[r->buf_len++] = 5; + outbuf[r->iov.iov_len++] = 5; } else { - outbuf[r->buf_len++] = 0; + outbuf[r->iov.iov_len++] = 0; } - outbuf[r->buf_len++] = 0x00; // this page - outbuf[r->buf_len++] = 0x00; - outbuf[r->buf_len++] = 3; // number of pages - outbuf[r->buf_len++] = 0x00; // list of supported pages (this page) - outbuf[r->buf_len++] = 0x80; // unit serial number - outbuf[r->buf_len++] = 0x83; // device identification + outbuf[r->iov.iov_len++] = 0x00; // this page + outbuf[r->iov.iov_len++] = 0x00; + outbuf[r->iov.iov_len++] = 3; // number of pages + outbuf[r->iov.iov_len++] = 0x00; // list of supported pages (this page) + outbuf[r->iov.iov_len++] = 0x80; // unit serial number + outbuf[r->iov.iov_len++] = 0x83; // device identification } break; case 0x80: @@ -491,20 +492,20 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, DPRINTF("Inquiry EVPD[Serial number] buffer size %d\n", len); l = MIN(len, strlen(s->drive_serial_str)); - r->buf_len = 0; + r->iov.iov_len = 0; /* Supported page codes */ if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) { - outbuf[r->buf_len++] = 5; + outbuf[r->iov.iov_len++] = 5; } else { - outbuf[r->buf_len++] = 0; + outbuf[r->iov.iov_len++] = 0; } - outbuf[r->buf_len++] = 0x80; // this page - outbuf[r->buf_len++] = 0x00; - outbuf[r->buf_len++] = l; - memcpy(&outbuf[r->buf_len], s->drive_serial_str, l); - r->buf_len += l; + outbuf[r->iov.iov_len++] = 0x80; // this page + outbuf[r->iov.iov_len++] = 0x00; + outbuf[r->iov.iov_len++] = l; + memcpy(&outbuf[r->iov.iov_len], s->drive_serial_str, l); + r->iov.iov_len += l; } break; @@ -518,25 +519,25 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, DPRINTF("Inquiry EVPD[Device identification] " "buffer size %d\n", len); - r->buf_len = 0; + r->iov.iov_len = 0; if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) { - outbuf[r->buf_len++] = 5; + outbuf[r->iov.iov_len++] = 5; } else { - outbuf[r->buf_len++] = 0; + outbuf[r->iov.iov_len++] = 0; } - outbuf[r->buf_len++] = 0x83; // this page - outbuf[r->buf_len++] = 0x00; - outbuf[r->buf_len++] = 3 + id_len; + outbuf[r->iov.iov_len++] = 0x83; // this page + outbuf[r->iov.iov_len++] = 0x00; + outbuf[r->iov.iov_len++] = 3 + id_len; - outbuf[r->buf_len++] = 0x2; // ASCII - outbuf[r->buf_len++] = 0; // not officially assigned - outbuf[r->buf_len++] = 0; // reserved - outbuf[r->buf_len++] = id_len; // length of data following + outbuf[r->iov.iov_len++] = 0x2; // ASCII + outbuf[r->iov.iov_len++] = 0; // not officially assigned + outbuf[r->iov.iov_len++] = 0; // reserved + outbuf[r->iov.iov_len++] = id_len; // length of data following - memcpy(&outbuf[r->buf_len], + memcpy(&outbuf[r->iov.iov_len], bdrv_get_device_name(s->bdrv), id_len); - r->buf_len += id_len; + r->iov.iov_len += id_len; } break; default: @@ -592,7 +593,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, outbuf[4] = len - 5; /* Additional Length = (Len - 1) - 4 */ /* Sync data transfer and TCQ. */ outbuf[7] = 0x10 | (s->tcq ? 0x02 : 0); - r->buf_len = len; + r->iov.iov_len = len; break; case 0x16: DPRINTF("Reserve(6)\n"); @@ -727,10 +728,10 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, p[21] = (16 * 176) & 0xff; p += 22; } - r->buf_len = p - outbuf; - outbuf[0] = r->buf_len - 4; - if (r->buf_len > len) - r->buf_len = len; + r->iov.iov_len = p - outbuf; + outbuf[0] = r->iov.iov_len - 4; + if (r->iov.iov_len > len) + r->iov.iov_len = len; } break; case 0x1b: @@ -766,7 +767,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, outbuf[5] = 0; outbuf[6] = s->cluster_size * 2; outbuf[7] = 0; - r->buf_len = 8; + r->iov.iov_len = 8; } else { notready: scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NOT_READY); @@ -827,7 +828,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, if (toclen > 0) { if (len > toclen) len = toclen; - r->buf_len = len; + r->iov.iov_len = len; break; } error_cmd: @@ -840,7 +841,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, /* ??? This should probably return much more information. For now just return the basic header indicating the CD-ROM profile. */ outbuf[7] = 8; // CD-ROM - r->buf_len = 8; + r->iov.iov_len = 8; break; case 0x56: DPRINTF("Reserve(10)\n"); @@ -877,7 +878,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, outbuf[10] = s->cluster_size * 2; outbuf[11] = 0; /* Protection, exponent and lowest lba field left blank. */ - r->buf_len = len; + r->iov.iov_len = len; } else { scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NOT_READY); return 0; @@ -892,7 +893,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, goto fail; memset(outbuf, 0, 16); outbuf[3] = 8; - r->buf_len = 16; + r->iov.iov_len = 16; break; case 0x2f: DPRINTF("Verify (sector %d, count %d)\n", lba, len); @@ -906,10 +907,10 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR); return 0; } - if (r->sector_count == 0 && r->buf_len == 0) { + if (r->sector_count == 0 && r->iov.iov_len == 0) { scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE); } - len = r->sector_count * 512 + r->buf_len; + len = r->sector_count * 512 + r->iov.iov_len; if (is_write) { return -len; } else { @@ -37,10 +37,6 @@ //#define DEBUG_BOCHS_VBE -#define GMODE_TEXT 0 -#define GMODE_GRAPH 1 -#define GMODE_BLANK 2 - /* force some bits to zero */ const uint8_t sr_mask[8] = { 0x03, @@ -398,7 +394,6 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) if (s->ar_flip_flop == 0) { val &= 0x3f; s->ar_index = val; - vga_update_resolution(s); } else { index = s->ar_index & 0x1f; switch(index) { @@ -439,7 +434,6 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) #endif s->sr[s->sr_index] = val & sr_mask[s->sr_index]; if (s->sr_index == 1) s->update_retrace_info(s); - vga_update_resolution(s); break; case 0x3c7: s->dac_read_index = val; @@ -467,7 +461,6 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) printf("vga: write GR%x = 0x%02x\n", s->gr_index, val); #endif s->gr[s->gr_index] = val & gr_mask[s->gr_index]; - vga_update_resolution(s); break; case 0x3b4: case 0x3d4: @@ -483,7 +476,6 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) /* can always write bit 4 of CR7 */ if (s->cr_index == 7) s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10); - vga_update_resolution(s); return; } switch(s->cr_index) { @@ -511,7 +503,6 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) s->update_retrace_info(s); break; } - vga_update_resolution(s); break; case 0x3ba: case 0x3da: @@ -591,13 +582,11 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) { s->vbe_regs[s->vbe_index] = val; } - vga_update_resolution(s); break; case VBE_DISPI_INDEX_YRES: if (val <= VBE_DISPI_MAX_YRES) { s->vbe_regs[s->vbe_index] = val; } - vga_update_resolution(s); break; case VBE_DISPI_INDEX_BPP: if (val == 0) @@ -606,7 +595,6 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) val == 16 || val == 24 || val == 32) { s->vbe_regs[s->vbe_index] = val; } - vga_update_resolution(s); break; case VBE_DISPI_INDEX_BANK: if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) { @@ -675,7 +663,6 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) } s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0; s->vbe_regs[s->vbe_index] = val; - vga_update_resolution(s); break; case VBE_DISPI_INDEX_VIRT_WIDTH: { @@ -696,7 +683,6 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h; s->vbe_line_offset = line_offset; } - vga_update_resolution(s); break; case VBE_DISPI_INDEX_X_OFFSET: case VBE_DISPI_INDEX_Y_OFFSET: @@ -711,7 +697,6 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3); s->vbe_start_addr >>= 2; } - vga_update_resolution(s); break; default: break; @@ -1318,6 +1303,7 @@ static void vga_draw_text(VGAState *s, int full_update) s->plane_updated = 0; full_update = 1; } + full_update |= update_basic_params(s); line_offset = s->line_offset; s1 = s->vram_ptr + (s->start_addr * 4); @@ -1329,6 +1315,18 @@ static void vga_draw_text(VGAState *s, int full_update) return; } + if (width != s->last_width || height != s->last_height || + cw != s->last_cw || cheight != s->last_ch || s->last_depth) { + s->last_scr_width = width * cw; + s->last_scr_height = height * cheight; + qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height); + s->last_depth = 0; + s->last_width = width; + s->last_height = height; + s->last_ch = cheight; + s->last_cw = cw; + full_update = 1; + } s->rgb_to_pixel = rgb_to_pixel_dup_table[get_depth_index(s->ds)]; full_update |= update_palette16(s); @@ -1585,21 +1583,39 @@ static void vga_sync_dirty_bitmap(VGAState *s) vga_dirty_log_start(s); } -static void vga_update_resolution_graphics(VGAState *s) +/* + * graphic modes + */ +static void vga_draw_graphic(VGAState *s, int full_update) { - int depth = s->get_bpp(s); - int width, height, shift_control, double_scan; + int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask, depth; + int width, height, shift_control, line_offset, page0, page1, bwidth, bits; int disp_width, multi_scan, multi_run; + uint8_t *d; + uint32_t v, addr1, addr; + vga_draw_line_func *vga_draw_line; + + full_update |= update_basic_params(s); + + if (!full_update) + vga_sync_dirty_bitmap(s); s->get_resolution(s, &width, &height); disp_width = width; shift_control = (s->gr[0x05] >> 5) & 3; double_scan = (s->cr[0x09] >> 7); - + if (shift_control != 1) { + multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1; + } else { + /* in CGA modes, multi_scan is ignored */ + /* XXX: is it correct ? */ + multi_scan = double_scan; + } + multi_run = multi_scan; if (shift_control != s->shift_control || double_scan != s->double_scan) { - s->want_full_update = 1; + full_update = 1; s->shift_control = shift_control; s->double_scan = double_scan; } @@ -1613,28 +1629,12 @@ static void vga_update_resolution_graphics(VGAState *s) disp_width <<= 1; } } - disp_width = width; - - if (shift_control != 1) { - multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1; - } else { - /* in CGA modes, multi_scan is ignored */ - /* XXX: is it correct ? */ - multi_scan = double_scan; - } - - multi_run = multi_scan; + depth = s->get_bpp(s); if (s->line_offset != s->last_line_offset || disp_width != s->last_width || height != s->last_height || - s->last_depth != depth || - s->multi_run != multi_run || - s->multi_scan != multi_scan || - s->want_full_update) { - if (s->ds->surface->pf.depth == 0) { - goto dont_touch_display_surface; - } + s->last_depth != depth) { #if defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) if (depth == 16 || depth == 32) { #else @@ -1651,91 +1651,14 @@ static void vga_update_resolution_graphics(VGAState *s) } else { qemu_console_resize(s->ds, disp_width, height); } - dont_touch_display_surface: s->last_scr_width = disp_width; s->last_scr_height = height; s->last_width = disp_width; s->last_height = height; s->last_line_offset = s->line_offset; s->last_depth = depth; - s->multi_run = multi_run; - s->multi_scan = multi_scan; - s->want_full_update = 1; - } -} - -static void vga_update_resolution_text(VGAState *s) -{ - int width, height, cw, cheight; - - vga_get_text_resolution(s, &width, &height, &cw, &cheight); - if (width != s->last_width || height != s->last_height || - cw != s->last_cw || cheight != s->last_ch || s->last_depth) { - s->last_scr_width = width * cw; - s->last_scr_height = height * cheight; - if (s->ds->surface->pf.depth != 0) { - qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height); - } else { - /* - * curses expects width and height to be in character cell - * dimensions, not pixels. - */ - s->ds->surface->width = width; - s->ds->surface->height = height; - dpy_resize(s->ds); - } - s->last_depth = 0; - s->last_width = width; - s->last_height = height; - s->last_ch = cheight; - s->last_cw = cw; - s->want_full_update = 1; - } -} - -void vga_update_resolution(VGAState *s) -{ - int graphic_mode; - - if (!(s->ar_index & 0x20)) { - graphic_mode = GMODE_BLANK; - } else { - graphic_mode = s->gr[6] & 1; - } - if (graphic_mode != s->graphic_mode) { - s->graphic_mode = graphic_mode; - s->want_full_update = 1; - } - s->want_full_update |= update_basic_params(s); - switch (graphic_mode) { - case GMODE_TEXT: - vga_update_resolution_text(s); - break; - case GMODE_GRAPH: - vga_update_resolution_graphics(s); - break; - } -} - -/* - * graphic modes - */ -static void vga_draw_graphic(VGAState *s, int full_update) -{ - int y1, y, update, linesize, y_start, mask; - int width, height, line_offset, bwidth, bits; - int multi_run; - uint8_t *d; - uint32_t v, addr1, addr; - long page0, page1, page_min, page_max; - vga_draw_line_func *vga_draw_line; - - if (!full_update) - vga_sync_dirty_bitmap(s); - - s->get_resolution(s, &width, &height); - multi_run = s->multi_run; - if (is_buffer_shared(s->ds->surface) && + full_update = 1; + } else if (is_buffer_shared(s->ds->surface) && (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) { s->ds->surface->data = s->vram_ptr + (s->start_addr * 4); dpy_setdata(s->ds); @@ -1744,7 +1667,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) s->rgb_to_pixel = rgb_to_pixel_dup_table[get_depth_index(s->ds)]; - if (s->shift_control == 0) { + if (shift_control == 0) { full_update |= update_palette16(s); if (s->sr[0x01] & 8) { v = VGA_DRAW_LINE4D2; @@ -1752,7 +1675,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) v = VGA_DRAW_LINE4; } bits = 4; - } else if (s->shift_control == 1) { + } else if (shift_control == 1) { full_update |= update_palette16(s); if (s->sr[0x01] & 8) { v = VGA_DRAW_LINE2D2; @@ -1848,7 +1771,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) if (y_start >= 0) { /* flush to display */ dpy_update(s->ds, 0, y_start, - s->last_width, y - y_start); + disp_width, y - y_start); y_start = -1; } } @@ -1857,7 +1780,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) if ((y1 & mask) == mask) addr1 += line_offset; y1++; - multi_run = s->multi_scan; + multi_run = multi_scan; } else { multi_run--; } @@ -1869,7 +1792,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) if (y_start >= 0) { /* flush to display */ dpy_update(s->ds, 0, y_start, - s->last_width, y - y_start); + disp_width, y - y_start); } /* reset modified pages */ if (page_max != -1) { @@ -1906,17 +1829,29 @@ static void vga_draw_blank(VGAState *s, int full_update) s->last_scr_width, s->last_scr_height); } +#define GMODE_TEXT 0 +#define GMODE_GRAPH 1 +#define GMODE_BLANK 2 + static void vga_update_display(void *opaque) { VGAState *s = (VGAState *)opaque; - int full_update; + int full_update, graphic_mode; if (ds_get_bits_per_pixel(s->ds) == 0) { /* nothing to do */ } else { - full_update = s->want_full_update; - s->want_full_update = 0; - switch(s->graphic_mode) { + full_update = 0; + if (!(s->ar_index & 0x20)) { + graphic_mode = GMODE_BLANK; + } else { + graphic_mode = s->gr[6] & 1; + } + if (graphic_mode != s->graphic_mode) { + s->graphic_mode = graphic_mode; + full_update = 1; + } + switch(graphic_mode) { case GMODE_TEXT: vga_draw_text(s, full_update); break; @@ -1939,8 +1874,8 @@ static void vga_invalidate_display(void *opaque) { VGAState *s = (VGAState *)opaque; - vga_update_resolution(s); - s->want_full_update = 1; + s->last_width = -1; + s->last_height = -1; } void vga_reset(void *opaque) @@ -1984,6 +1919,7 @@ void vga_reset(void *opaque) s->vbe_bank_mask = (s->vram_size >> 16) - 1; #endif memset(s->font_offsets, '\0', sizeof(s->font_offsets)); + s->graphic_mode = -1; /* force full update */ s->shift_control = 0; s->double_scan = 0; s->line_offset = 0; @@ -2009,7 +1945,6 @@ void vga_reset(void *opaque) memset(&s->retrace_info, 0, sizeof (s->retrace_info)); break; } - vga_update_resolution(s); } #define TEXTMODE_X(x) ((x) % width) @@ -2021,28 +1956,50 @@ void vga_reset(void *opaque) static void vga_update_text(void *opaque, console_ch_t *chardata) { VGAState *s = (VGAState *) opaque; - int i, cursor_offset, cursor_visible; + int graphic_mode, i, cursor_offset, cursor_visible; int cw, cheight, width, height, size, c_min, c_max; uint32_t *src; console_ch_t *dst, val; char msg_buffer[80]; - int full_update = s->want_full_update; + int full_update = 0; + + if (!(s->ar_index & 0x20)) { + graphic_mode = GMODE_BLANK; + } else { + graphic_mode = s->gr[6] & 1; + } + if (graphic_mode != s->graphic_mode) { + s->graphic_mode = graphic_mode; + full_update = 1; + } + if (s->last_width == -1) { + s->last_width = 0; + full_update = 1; + } - s->want_full_update = 0; - switch (s->graphic_mode) { + switch (graphic_mode) { case GMODE_TEXT: /* TODO: update palette */ + full_update |= update_basic_params(s); - vga_get_text_resolution(s, &width, &height, &cw, &cheight); - - if (s->ds->surface->width != width - || s->ds->surface->height != height) { - s->ds->surface->width = width; - s->ds->surface->height = height; - dpy_resize(s->ds); + /* total width & height */ + cheight = (s->cr[9] & 0x1f) + 1; + cw = 8; + if (!(s->sr[1] & 0x01)) + cw = 9; + if (s->sr[1] & 0x08) + cw = 16; /* NOTE: no 18 pixel wide */ + width = (s->cr[0x01] + 1); + if (s->cr[0x06] == 100) { + /* ugly hack for CGA 160x100x16 - explain me the logic */ + height = 100; + } else { + height = s->cr[0x12] | + ((s->cr[0x07] & 0x02) << 7) | + ((s->cr[0x07] & 0x40) << 3); + height = (height + 1) / cheight; } - /* total width & height */ size = (height * width); if (size > CH_ATTR_SIZE) { if (!full_update) @@ -2053,6 +2010,20 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) break; } + if (width != s->last_width || height != s->last_height || + cw != s->last_cw || cheight != s->last_ch) { + s->last_scr_width = width * cw; + s->last_scr_height = height * cheight; + s->ds->surface->width = width; + s->ds->surface->height = height; + dpy_resize(s->ds); + s->last_width = width; + s->last_height = height; + s->last_ch = cheight; + s->last_cw = cw; + full_update = 1; + } + /* Update "hardware" cursor */ cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr; if (cursor_offset != s->cursor_offset || @@ -2251,8 +2222,7 @@ static int vga_load(QEMUFile *f, void *opaque, int version_id) #endif /* force refresh */ - vga_update_resolution(s); - s->want_full_update = 1; + s->graphic_mode = -1; return 0; } @@ -2834,8 +2804,7 @@ static void vga_screen_dump_common(VGAState *s, const char *filename, ds->surface = qemu_create_displaysurface(ds, w, h); s->ds = ds; - vga_update_resolution(s); - s->want_full_update = 1; + s->graphic_mode = -1; vga_update_display(s); ppm_save(filename, ds->surface); @@ -2866,16 +2835,11 @@ static void vga_screen_dump(void *opaque, const char *filename) { VGAState *s = (VGAState *)opaque; - switch (s->graphic_mode) { - case GMODE_TEXT: - vga_screen_dump_text(s, filename); - break; - case GMODE_GRAPH: - vga_screen_dump_graphic(s, filename); - break; - case GMODE_BLANK: - default: + if (!(s->ar_index & 0x20)) vga_screen_dump_blank(s, filename); - break; - } + else if (s->gr[6] & 1) + vga_screen_dump_graphic(s, filename); + else + vga_screen_dump_text(s, filename); + vga_invalidate_display(s); } diff --git a/hw/vga_int.h b/hw/vga_int.h index 71ffeb569..8ba8a60f2 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -147,11 +147,8 @@ typedef void (* vga_update_retrace_info_fn)(struct VGAState *s); DisplayState *ds; \ uint32_t font_offsets[2]; \ int graphic_mode; \ - int want_full_update; \ uint8_t shift_control; \ uint8_t double_scan; \ - uint8_t multi_run; \ - uint8_t multi_scan; \ uint32_t line_offset; \ uint32_t line_compare; \ uint32_t start_addr; \ @@ -198,7 +195,6 @@ void vga_common_init(VGAState *s, uint8_t *vga_ram_base, ram_addr_t vga_ram_offset, int vga_ram_size); void vga_init(VGAState *s); void vga_reset(void *s); -void vga_update_resolution(VGAState *s); void vga_dirty_log_start(VGAState *s); void vga_dirty_log_stop(VGAState *s); diff --git a/hw/wm8750.c b/hw/wm8750.c index e5324ec41..02d5f5e5b 100644 --- a/hw/wm8750.c +++ b/hw/wm8750.c @@ -706,7 +706,7 @@ void wm8750_dac_commit(void *opaque) { struct wm8750_s *s = (struct wm8750_s *) opaque; - return wm8750_out_flush(s); + wm8750_out_flush(s); } uint32_t wm8750_adc_dat(void *opaque) diff --git a/posix-aio-compat.c b/posix-aio-compat.c index 65c80ecc3..c7fdac70b 100644 --- a/posix-aio-compat.c +++ b/posix-aio-compat.c @@ -20,6 +20,7 @@ #include <stdlib.h> #include <stdio.h> #include "osdep.h" +#include "qemu-common.h" #include "posix-aio-compat.h" @@ -32,6 +33,12 @@ static int cur_threads = 0; static int idle_threads = 0; static TAILQ_HEAD(, qemu_paiocb) request_list; +#ifdef HAVE_PREADV +static int preadv_present = 1; +#else +static int preadv_present = 0; +#endif + static void die2(int err, const char *what) { fprintf(stderr, "%s failed: %s\n", what, strerror(err)); @@ -76,45 +83,185 @@ static void thread_create(pthread_t *thread, pthread_attr_t *attr, if (ret) die2(ret, "pthread_create"); } -static size_t handle_aiocb_readwrite(struct qemu_paiocb *aiocb) +static size_t handle_aiocb_ioctl(struct qemu_paiocb *aiocb) +{ + int ret; + + ret = ioctl(aiocb->aio_fildes, aiocb->aio_ioctl_cmd, aiocb->aio_ioctl_buf); + if (ret == -1) + return -errno; + return ret; +} + +#ifdef HAVE_PREADV + +static ssize_t +qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset) +{ + return preadv(fd, iov, nr_iov, offset); +} + +static ssize_t +qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset) +{ + return pwritev(fd, iov, nr_iov, offset); +} + +#else + +static ssize_t +qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset) +{ + return -ENOSYS; +} + +static ssize_t +qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset) +{ + return -ENOSYS; +} + +#endif + +/* + * Check if we need to copy the data in the aiocb into a new + * properly aligned buffer. + */ +static int aiocb_needs_copy(struct qemu_paiocb *aiocb) +{ + if (aiocb->aio_flags & QEMU_AIO_SECTOR_ALIGNED) { + int i; + + for (i = 0; i < aiocb->aio_niov; i++) + if ((uintptr_t) aiocb->aio_iov[i].iov_base % 512) + return 1; + } + + return 0; +} + +static size_t handle_aiocb_rw_vector(struct qemu_paiocb *aiocb) { size_t offset = 0; ssize_t len; - while (offset < aiocb->aio_nbytes) { + do { if (aiocb->aio_type == QEMU_PAIO_WRITE) - len = pwrite(aiocb->aio_fildes, - (const char *)aiocb->aio_buf + offset, + len = qemu_pwritev(aiocb->aio_fildes, + aiocb->aio_iov, + aiocb->aio_niov, + aiocb->aio_offset + offset); + else + len = qemu_preadv(aiocb->aio_fildes, + aiocb->aio_iov, + aiocb->aio_niov, + aiocb->aio_offset + offset); + } while (len == -1 && errno == EINTR); + + if (len == -1) + return -errno; + return len; +} + +static size_t handle_aiocb_rw_linear(struct qemu_paiocb *aiocb, char *buf) +{ + size_t offset = 0; + size_t len; + + while (offset < aiocb->aio_nbytes) { + if (aiocb->aio_type == QEMU_PAIO_WRITE) + len = pwrite(aiocb->aio_fildes, + (const char *)buf + offset, + aiocb->aio_nbytes - offset, + aiocb->aio_offset + offset); + else + len = pread(aiocb->aio_fildes, + buf + offset, aiocb->aio_nbytes - offset, aiocb->aio_offset + offset); - else - len = pread(aiocb->aio_fildes, - (char *)aiocb->aio_buf + offset, - aiocb->aio_nbytes - offset, - aiocb->aio_offset + offset); - - if (len == -1 && errno == EINTR) - continue; - else if (len == -1) { - offset = -errno; - break; - } else if (len == 0) - break; - offset += len; + if (len == -1 && errno == EINTR) + continue; + else if (len == -1) { + offset = -errno; + break; + } else if (len == 0) + break; + + offset += len; } return offset; } -static size_t handle_aiocb_ioctl(struct qemu_paiocb *aiocb) +static size_t handle_aiocb_rw(struct qemu_paiocb *aiocb) { - int ret; + size_t nbytes; + char *buf; + + if (!aiocb_needs_copy(aiocb)) { + /* + * If there is just a single buffer, and it is properly aligned + * we can just use plain pread/pwrite without any problems. + */ + if (aiocb->aio_niov == 1) + return handle_aiocb_rw_linear(aiocb, aiocb->aio_iov->iov_base); + + /* + * We have more than one iovec, and all are properly aligned. + * + * Try preadv/pwritev first and fall back to linearizing the + * buffer if it's not supported. + */ + if (preadv_present) { + nbytes = handle_aiocb_rw_vector(aiocb); + if (nbytes == aiocb->aio_nbytes) + return nbytes; + if (nbytes < 0 && nbytes != -ENOSYS) + return nbytes; + preadv_present = 0; + } - ret = ioctl(aiocb->aio_fildes, aiocb->aio_ioctl_cmd, aiocb->aio_buf); - if (ret == -1) - return -errno; - return ret; + /* + * XXX(hch): short read/write. no easy way to handle the reminder + * using these interfaces. For now retry using plain + * pread/pwrite? + */ + } + + /* + * Ok, we have to do it the hard way, copy all segments into + * a single aligned buffer. + */ + buf = qemu_memalign(512, aiocb->aio_nbytes); + if (aiocb->aio_type == QEMU_PAIO_WRITE) { + char *p = buf; + int i; + + for (i = 0; i < aiocb->aio_niov; ++i) { + memcpy(p, aiocb->aio_iov[i].iov_base, aiocb->aio_iov[i].iov_len); + p += aiocb->aio_iov[i].iov_len; + } + } + + nbytes = handle_aiocb_rw_linear(aiocb, buf); + if (aiocb->aio_type != QEMU_PAIO_WRITE) { + char *p = buf; + size_t count = aiocb->aio_nbytes, copy; + int i; + + for (i = 0; i < aiocb->aio_niov && count; ++i) { + copy = count; + if (copy > aiocb->aio_iov[i].iov_len) + copy = aiocb->aio_iov[i].iov_len; + memcpy(aiocb->aio_iov[i].iov_base, p, copy); + p += copy; + count -= copy; + } + } + qemu_vfree(buf); + + return nbytes; } static void *aio_thread(void *unused) @@ -157,7 +304,7 @@ static void *aio_thread(void *unused) switch (aiocb->aio_type) { case QEMU_PAIO_READ: case QEMU_PAIO_WRITE: - ret = handle_aiocb_readwrite(aiocb); + ret = handle_aiocb_rw(aiocb); break; case QEMU_PAIO_IOCTL: ret = handle_aiocb_ioctl(aiocb); diff --git a/posix-aio-compat.h b/posix-aio-compat.h index a1cdfd7f1..1c5dcbd92 100644 --- a/posix-aio-compat.h +++ b/posix-aio-compat.h @@ -27,11 +27,18 @@ struct qemu_paiocb { int aio_fildes; - void *aio_buf; + union { + struct iovec *aio_iov; + void *aio_ioctl_buf; + }; + int aio_niov; size_t aio_nbytes; #define aio_ioctl_cmd aio_nbytes /* for QEMU_PAIO_IOCTL */ int ev_signo; off_t aio_offset; + unsigned aio_flags; +/* 512 byte alignment required for buffer, offset and length */ +#define QEMU_AIO_SECTOR_ALIGNED 0x01 /* private */ TAILQ_ENTRY(qemu_paiocb) node; diff --git a/target-mips/helper.h b/target-mips/helper.h index e44657837..b8ec15eab 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -15,11 +15,11 @@ DEF_HELPER_3(lwr, tl, tl, tl, int) DEF_HELPER_3(swl, void, tl, tl, int) DEF_HELPER_3(swr, void, tl, tl, int) -DEF_HELPER_1(clo, tl, tl) -DEF_HELPER_1(clz, tl, tl) +DEF_HELPER_FLAGS_1(clo, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl) +DEF_HELPER_FLAGS_1(clz, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl) #ifdef TARGET_MIPS64 -DEF_HELPER_1(dclo, tl, tl) -DEF_HELPER_1(dclz, tl, tl) +DEF_HELPER_FLAGS_1(dclo, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl) +DEF_HELPER_FLAGS_1(dclz, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl) DEF_HELPER_2(dmult, void, tl, tl) DEF_HELPER_2(dmultu, void, tl, tl) #endif @@ -1122,9 +1122,11 @@ static void tcg_liveness_analysis(TCGContext *s) dead_temps[arg] = 1; } - /* globals are live (they may be used by the call) */ - memset(dead_temps, 0, s->nb_globals); - + if (!(call_flags & TCG_CALL_CONST)) { + /* globals are live (they may be used by the call) */ + memset(dead_temps, 0, s->nb_globals); + } + /* input args are live */ dead_iargs = 0; for(i = 0; i < nb_iargs; i++) { @@ -1821,7 +1823,9 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, /* store globals and free associated registers (we assume the call can modify any global. */ - save_globals(s, allocated_regs); + if (!(flags & TCG_CALL_CONST)) { + save_globals(s, allocated_regs); + } tcg_out_op(s, opc, &func_arg, &const_func_arg); @@ -174,10 +174,14 @@ typedef int TCGv_i64; #define TCG_CALL_TYPE_REGPARM_1 0x0001 /* i386 style regparm call (1 reg) */ #define TCG_CALL_TYPE_REGPARM_2 0x0002 /* i386 style regparm call (2 regs) */ #define TCG_CALL_TYPE_REGPARM 0x0003 /* i386 style regparm call (3 regs) */ -/* A pure function only reads its arguments and globals variables and - cannot raise exceptions. Hence a call to a pure function can be +/* A pure function only reads its arguments and TCG global variables + and cannot raise exceptions. Hence a call to a pure function can be safely suppressed if the return value is not used. */ #define TCG_CALL_PURE 0x0010 +/* A const function only reads its arguments and does not use TCG + global variables. Hence a call to such a function does not + save TCG global variables back to their canonical location. */ +#define TCG_CALL_CONST 0x0020 /* used to align parameters */ #define TCG_CALL_DUMMY_TCGV MAKE_TCGV_I32(-1) @@ -1598,7 +1598,7 @@ static void pixel_format_message (VncState *vs) { else if (vs->ds->surface->pf.bits_per_pixel == 8) vs->send_hextile_tile = send_hextile_tile_8; vs->clientds = *(vs->ds->surface); - vs->clientds.flags |= ~QEMU_ALLOCATED_FLAG; + vs->clientds.flags &= ~QEMU_ALLOCATED_FLAG; vs->write_pixels = vnc_write_pixels_copy; vnc_write(vs, pad, 3); /* padding */ |