[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] merge with xen-unstable.hg
# HG changeset patch # User awilliam@xxxxxxxxxxx # Node ID f7b43e5c42b981fa16ad9bfc5339ff8496dd2288 # Parent 2db50529223e20a3d48d96e8cbfe3eaf7998b58c # Parent d71e72d8532cfdf5896f560d98d45262841c8b83 merge with xen-unstable.hg --- patches/linux-2.6.16.13/net-gso.patch | 2516 --- tools/examples/vtpm-addtodb | 10 tools/ioemu/cpu.h | 76 tools/ioemu/create_keysym_header.sh | 77 tools/ioemu/hw/acpi.c | 178 tools/ioemu/hw/i8259_stub.c | 81 tools/ioemu/hw/m48t08.c | 391 tools/ioemu/hw/m48t08.h | 12 tools/ioemu/hw/magic-load.c | 324 tools/ioemu/hw/pcnet.c | 1154 - tools/ioemu/hw/pcnet.h | 537 tools/ioemu/hw/port-e9.c | 47 tools/ioemu/hw/sched.c | 268 tools/ioemu/hw/timer.c | 97 tools/ioemu/ia64_intrinsic.h | 276 tools/ioemu/keyboard_rdesktop.c | 165 tools/ioemu/keymaps/convert-map | 63 tools/ioemu/main.c | 250 tools/ioemu/path.c | 147 tools/ioemu/target-i386-dm/Makefile | 406 tools/ioemu/x86_32.ld | 140 tools/vtpm/tpm_emulator-0.3-x86_64.patch | 657 - .hgignore | 51 Config.mk | 4 buildconfigs/Rules.mk | 14 buildconfigs/conf.linux-native/00_xen_to_native | 84 buildconfigs/create_config.sh | 50 buildconfigs/linux-defconfig_xen0_ia64 | 1 buildconfigs/linux-defconfig_xen0_x86_32 | 1 buildconfigs/linux-defconfig_xen0_x86_64 | 1 buildconfigs/linux-defconfig_xen_ia64 | 1 buildconfigs/linux-defconfig_xen_x86_32 | 1 buildconfigs/linux-defconfig_xen_x86_64 | 1 buildconfigs/mk.linux-2.6-native | 4 buildconfigs/mk.linux-2.6-xen | 17 config/ia64.mk | 1 config/powerpc64.mk | 4 config/x86_32.mk | 2 config/x86_64.mk | 2 extras/mini-os/mm.c | 2 linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c | 23 linux-2.6-xen-sparse/drivers/xen/Kconfig | 104 linux-2.6-xen-sparse/drivers/xen/Makefile | 1 linux-2.6-xen-sparse/drivers/xen/blktap/Makefile | 3 linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c | 1439 ++ linux-2.6-xen-sparse/drivers/xen/blktap/common.h | 120 linux-2.6-xen-sparse/drivers/xen/blktap/interface.c | 165 linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c | 354 linux-2.6-xen-sparse/drivers/xen/console/console.c | 33 linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c | 4 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h | 2 linux-2.6-xen-sparse/include/linux/skbuff.h | 5 linux-2.6-xen-sparse/net/core/dev.c | 36 patches/linux-2.6.16.13/blktap-aio-16_03_06.patch | 164 patches/linux-2.6.16.13/net-csum.patch | 15 patches/linux-2.6.16.13/net-gso-0-base.patch | 1974 +++ patches/linux-2.6.16.13/net-gso-1-check-dodgy.patch | 16 patches/linux-2.6.16.13/net-gso-2-checksum-fix.patch | 311 patches/linux-2.6.16.13/net-gso-3-fix-errorcheck.patch | 13 patches/linux-2.6.16.13/xenoprof-generic.patch | 144 tools/Makefile | 15 tools/blktap/Makefile | 28 tools/blktap/README | 122 tools/blktap/drivers/Makefile | 76 tools/blktap/drivers/aes.c | 1319 ++ tools/blktap/drivers/aes.h | 26 tools/blktap/drivers/blktapctrl.c | 704 + tools/blktap/drivers/blktapctrl.h | 55 tools/blktap/drivers/block-aio.c | 327 tools/blktap/drivers/block-qcow.c | 1369 ++ tools/blktap/drivers/block-ram.c | 296 tools/blktap/drivers/block-sync.c | 242 tools/blktap/drivers/block-vmdk.c | 415 tools/blktap/drivers/bswap.h | 202 tools/blktap/drivers/img2qcow.c | 289 tools/blktap/drivers/qcow-create.c | 80 tools/blktap/drivers/qcow2raw.c | 346 tools/blktap/drivers/tapdisk.c | 674 + tools/blktap/drivers/tapdisk.h | 211 tools/blktap/lib/Makefile | 68 tools/blktap/lib/blkif.c | 185 tools/blktap/lib/blktaplib.h | 223 tools/blktap/lib/list.h | 55 tools/blktap/lib/xenbus.c | 387 tools/blktap/lib/xs_api.c | 364 tools/blktap/lib/xs_api.h | 50 tools/examples/Makefile | 3 tools/examples/README | 1 tools/examples/blktap | 15 tools/examples/vtpm-common.sh | 48 tools/examples/vtpm-impl | 58 tools/examples/xen-backend.agent | 3 tools/examples/xen-backend.rules | 1 tools/examples/xmexample.hvm | 15 tools/firmware/vmxassist/vmxassist.ld | 3 tools/ioemu/.cvsignore | 29 tools/ioemu/CVS/Entries | 109 tools/ioemu/CVS/Repository | 1 tools/ioemu/CVS/Root | 1 tools/ioemu/CVS/Tag | 1 tools/ioemu/Changelog | 81 tools/ioemu/LICENSE | 12 tools/ioemu/Makefile | 135 tools/ioemu/Makefile.target | 531 tools/ioemu/README | 53 tools/ioemu/README.distrib | 16 tools/ioemu/TODO | 21 tools/ioemu/VERSION | 2 tools/ioemu/a.out.h | 431 tools/ioemu/audio/CVS/Entries | 19 tools/ioemu/audio/CVS/Repository | 1 tools/ioemu/audio/CVS/Root | 1 tools/ioemu/audio/CVS/Tag | 1 tools/ioemu/audio/alsaaudio.c | 981 + tools/ioemu/audio/audio.c | 2047 ++- tools/ioemu/audio/audio.h | 114 tools/ioemu/audio/audio_int.h | 340 tools/ioemu/audio/audio_template.h | 565 tools/ioemu/audio/coreaudio.c | 564 tools/ioemu/audio/dsound_template.h | 282 tools/ioemu/audio/dsoundaudio.c | 1076 + tools/ioemu/audio/fmodaudio.c | 683 + tools/ioemu/audio/mixeng.c | 298 tools/ioemu/audio/mixeng.h | 26 tools/ioemu/audio/mixeng_template.h | 140 tools/ioemu/audio/noaudio.c | 170 tools/ioemu/audio/ossaudio.c | 707 - tools/ioemu/audio/rate_template.h | 111 tools/ioemu/audio/sdlaudio.c | 423 tools/ioemu/audio/sys-queue.h | 241 tools/ioemu/audio/wavaudio.c | 208 tools/ioemu/block-bochs.c | 224 tools/ioemu/block-cloop.c | 12 tools/ioemu/block-cow.c | 7 tools/ioemu/block-dmg.c | 297 tools/ioemu/block-qcow.c | 53 tools/ioemu/block-vmdk.c | 200 tools/ioemu/block-vpc.c | 242 tools/ioemu/block-vvfat.c | 2807 ++++ tools/ioemu/block.c | 272 tools/ioemu/block_int.h | 5 tools/ioemu/cocoa.m | 911 + tools/ioemu/configure | 673 - tools/ioemu/console.c | 389 tools/ioemu/cpu-all.h | 503 tools/ioemu/cpu-defs.h | 54 tools/ioemu/cpu-exec.c | 1480 ++ tools/ioemu/dis-asm.h | 455 tools/ioemu/disas.c | 413 tools/ioemu/disas.h | 23 tools/ioemu/dyngen-exec.h | 257 tools/ioemu/dyngen-op.h | 9 tools/ioemu/dyngen.c | 2550 +++ tools/ioemu/dyngen.h | 429 tools/ioemu/elf.h | 1160 + tools/ioemu/elf_ops.h | 205 tools/ioemu/exec-all.h | 251 tools/ioemu/exec.c | 2117 +++ tools/ioemu/fpu/CVS/Entries | 7 tools/ioemu/fpu/CVS/Repository | 1 tools/ioemu/fpu/CVS/Root | 1 tools/ioemu/fpu/CVS/Tag | 1 tools/ioemu/fpu/softfloat-macros.h | 720 + tools/ioemu/fpu/softfloat-native.c | 363 tools/ioemu/fpu/softfloat-native.h | 359 tools/ioemu/fpu/softfloat-specialize.h | 464 tools/ioemu/fpu/softfloat.c | 5320 ++++++++ tools/ioemu/fpu/softfloat.h | 398 tools/ioemu/gdbstub.c | 943 + tools/ioemu/gdbstub.h | 12 tools/ioemu/hw/CVS/Entries | 72 tools/ioemu/hw/CVS/Repository | 1 tools/ioemu/hw/CVS/Root | 1 tools/ioemu/hw/CVS/Tag | 1 tools/ioemu/hw/adb.c | 36 tools/ioemu/hw/adlib.c | 390 tools/ioemu/hw/apic.c | 1042 + tools/ioemu/hw/arm_boot.c | 105 tools/ioemu/hw/arm_pic.c | 73 tools/ioemu/hw/arm_pic.h | 27 tools/ioemu/hw/arm_timer.c | 383 tools/ioemu/hw/cirrus_vga.c | 226 tools/ioemu/hw/cuda.c | 104 tools/ioemu/hw/dma.c | 4 tools/ioemu/hw/es1370.c | 1062 + tools/ioemu/hw/esp.c | 747 + tools/ioemu/hw/fdc.c | 58 tools/ioemu/hw/heathrow_pic.c | 168 tools/ioemu/hw/i8254.c | 63 tools/ioemu/hw/i8259.c | 212 tools/ioemu/hw/ide.c | 617 tools/ioemu/hw/integratorcp.c | 546 tools/ioemu/hw/iommu.c | 208 tools/ioemu/hw/lance.c | 292 tools/ioemu/hw/m48t59.c | 204 tools/ioemu/hw/m48t59.h | 10 tools/ioemu/hw/mips_r4k.c | 295 tools/ioemu/hw/ne2000.c | 219 tools/ioemu/hw/openpic.c | 22 tools/ioemu/hw/parallel.c | 183 tools/ioemu/hw/pc.c | 506 tools/ioemu/hw/pci.c | 721 - tools/ioemu/hw/pckbd.c | 628 tools/ioemu/hw/pcspk.c | 147 tools/ioemu/hw/piix4acpi.c | 27 tools/ioemu/hw/pl011.c | 251 tools/ioemu/hw/pl050.c | 127 tools/ioemu/hw/pl080.c | 328 tools/ioemu/hw/pl110.c | 420 tools/ioemu/hw/pl110_template.h | 252 tools/ioemu/hw/pl190.c | 252 tools/ioemu/hw/ppc.c | 84 tools/ioemu/hw/ppc_chrp.c | 473 tools/ioemu/hw/ppc_prep.c | 216 tools/ioemu/hw/ps2.c | 566 tools/ioemu/hw/rtl8139.c | 2875 ++++ tools/ioemu/hw/sb16.c | 333 tools/ioemu/hw/serial.c | 228 tools/ioemu/hw/sh7750.c | 836 + tools/ioemu/hw/sh7750_regnames.c | 128 tools/ioemu/hw/sh7750_regnames.h | 6 tools/ioemu/hw/sh7750_regs.h | 1623 ++ tools/ioemu/hw/shix.c | 111 tools/ioemu/hw/slavio_intctl.c | 400 tools/ioemu/hw/slavio_misc.c | 244 tools/ioemu/hw/slavio_serial.c | 545 tools/ioemu/hw/slavio_timer.c | 288 tools/ioemu/hw/smc91c111.c | 714 + tools/ioemu/hw/sun4m.c | 339 tools/ioemu/hw/sun4u.c | 376 tools/ioemu/hw/tc58128.c | 181 tools/ioemu/hw/tcx.c | 407 tools/ioemu/hw/versatilepb.c | 271 tools/ioemu/hw/vga.c | 274 tools/ioemu/hw/vga_int.h | 2 tools/ioemu/i386-dis.c | 4143 ++++++ tools/ioemu/i386-vl.ld | 140 tools/ioemu/i386.ld | 140 tools/ioemu/ia64.ld | 211 tools/ioemu/keymaps.c | 145 tools/ioemu/keymaps/CVS/Entries | 36 tools/ioemu/keymaps/CVS/Repository | 1 tools/ioemu/keymaps/CVS/Root | 1 tools/ioemu/keymaps/CVS/Tag | 1 tools/ioemu/kqemu.c | 900 + tools/ioemu/kqemu.h | 132 tools/ioemu/loader.c | 235 tools/ioemu/monitor.c | 1773 ++ tools/ioemu/osdep.c | 129 tools/ioemu/osdep.h | 3 tools/ioemu/patches/acpi-poweroff-support | 26 tools/ioemu/patches/acpi-support | 58 tools/ioemu/patches/acpi-timer-support | 43 tools/ioemu/patches/domain-destroy | 24 tools/ioemu/patches/domain-reset | 45 tools/ioemu/patches/domain-timeoffset | 138 tools/ioemu/patches/hypervisor-pit | 48 tools/ioemu/patches/ide-hd-multithread | 75 tools/ioemu/patches/qemu-64bit | 80 tools/ioemu/patches/qemu-bugfixes | 19 tools/ioemu/patches/qemu-cleanup | 66 tools/ioemu/patches/qemu-dm | 399 tools/ioemu/patches/qemu-hvm-banner | 19 tools/ioemu/patches/qemu-infrastructure | 9 tools/ioemu/patches/qemu-logging | 57 tools/ioemu/patches/qemu-no-apic | 42 tools/ioemu/patches/qemu-nobios | 48 tools/ioemu/patches/qemu-smp | 38 tools/ioemu/patches/qemu-target-i386-dm | 115 tools/ioemu/patches/qemu-timer | 37 tools/ioemu/patches/sdl-mouse-invisible-wall | 17 tools/ioemu/patches/serial-non-block | 23 tools/ioemu/patches/series | 33 tools/ioemu/patches/shadow-vram | 32 tools/ioemu/patches/shared-vram | 123 tools/ioemu/patches/support-xm-console | 37 tools/ioemu/patches/vnc-cleanup | 63 tools/ioemu/patches/vnc-fixes | 321 tools/ioemu/patches/vnc-start-vncviewer | 69 tools/ioemu/patches/xen-build | 179 tools/ioemu/patches/xen-domain-name | 64 tools/ioemu/patches/xen-domid | 37 tools/ioemu/patches/xen-mm | 63 tools/ioemu/patches/xen-network | 52 tools/ioemu/pc-bios/CVS/Entries | 15 tools/ioemu/pc-bios/CVS/Repository | 1 tools/ioemu/pc-bios/CVS/Root | 1 tools/ioemu/pc-bios/CVS/Tag | 1 tools/ioemu/pc-bios/Makefile | 24 tools/ioemu/pc-bios/README | 17 tools/ioemu/pc-bios/bios.diff | 87 tools/ioemu/pc-bios/linux_boot.S | 29 tools/ioemu/pc-bios/ohw.diff | 1153 + tools/ioemu/pc-bios/proll.patch | 939 + tools/ioemu/pc-bios/vgabios.diff | 318 tools/ioemu/qemu-binfmt-conf.sh | 15 tools/ioemu/qemu-doc.texi | 1748 ++ tools/ioemu/qemu-img.c | 17 tools/ioemu/qemu-img.texi | 126 tools/ioemu/qemu-tech.texi | 595 tools/ioemu/qemu_socket.h | 30 tools/ioemu/readline.c | 1 tools/ioemu/sdl.c | 239 tools/ioemu/sdl_keysym.h | 278 tools/ioemu/softmmu_exec.h | 65 tools/ioemu/softmmu_header.h | 385 tools/ioemu/softmmu_template.h | 313 tools/ioemu/tap-win32.c | 680 + tools/ioemu/target-i386-dm/cpu.h | 86 tools/ioemu/target-i386-dm/exec-dm.c | 512 tools/ioemu/target-i386-dm/helper2.c | 270 tools/ioemu/target-i386-dm/i8259-dm.c | 107 tools/ioemu/target-i386-dm/qemu-ifup | 2 tools/ioemu/target-i386/CVS/Entries | 13 tools/ioemu/target-i386/CVS/Repository | 1 tools/ioemu/target-i386/CVS/Root | 1 tools/ioemu/target-i386/CVS/Tag | 1 tools/ioemu/target-i386/cpu.h | 653 + tools/ioemu/target-i386/exec.h | 572 tools/ioemu/target-i386/helper.c | 3505 +++++ tools/ioemu/target-i386/helper2.c | 1028 + tools/ioemu/target-i386/op.c | 2437 +++ tools/ioemu/target-i386/opreg_template.h | 190 tools/ioemu/target-i386/ops_mem.h | 156 tools/ioemu/target-i386/ops_sse.h | 1374 ++ tools/ioemu/target-i386/ops_template.h | 597 tools/ioemu/target-i386/ops_template_mem.h | 483 tools/ioemu/target-i386/translate-copy.c | 1323 ++ tools/ioemu/target-i386/translate.c | 6468 ++++++++++ tools/ioemu/tests/.cvsignore | 23 tools/ioemu/tests/CVS/Entries | 18 tools/ioemu/tests/CVS/Repository | 1 tools/ioemu/tests/CVS/Root | 1 tools/ioemu/tests/CVS/Tag | 1 tools/ioemu/tests/Makefile | 92 tools/ioemu/tests/hello-arm.c | 113 tools/ioemu/tests/hello-i386.c | 26 tools/ioemu/tests/linux-test.c | 536 tools/ioemu/tests/qruncom.c | 327 tools/ioemu/tests/runcom.c | 195 tools/ioemu/tests/sha1.c | 242 tools/ioemu/tests/test-i386-code16.S | 79 tools/ioemu/tests/test-i386-muldiv.h | 76 tools/ioemu/tests/test-i386-shift.h | 187 tools/ioemu/tests/test-i386-vm86.S | 104 tools/ioemu/tests/test-i386.c | 2611 ++++ tools/ioemu/tests/test-i386.h | 152 tools/ioemu/tests/test_path.c | 152 tools/ioemu/tests/testthread.c | 51 tools/ioemu/texi2pod.pl | 428 tools/ioemu/thunk.c | 2 tools/ioemu/translate-all.c | 311 tools/ioemu/translate-op.c | 37 tools/ioemu/vl.c | 4464 +++++- tools/ioemu/vl.h | 539 tools/ioemu/vnc.c | 1576 +- tools/ioemu/vnc_keysym.h | 275 tools/ioemu/vnchextile.h | 189 tools/libaio/COPYING | 515 tools/libaio/ChangeLog | 43 tools/libaio/INSTALL | 18 tools/libaio/Makefile | 40 tools/libaio/TODO | 4 tools/libaio/harness/Makefile | 37 tools/libaio/harness/README | 19 tools/libaio/harness/attic/0.t | 9 tools/libaio/harness/attic/1.t | 9 tools/libaio/harness/cases/10.t | 53 tools/libaio/harness/cases/11.t | 39 tools/libaio/harness/cases/12.t | 49 tools/libaio/harness/cases/13.t | 66 tools/libaio/harness/cases/14.t | 90 tools/libaio/harness/cases/2.t | 41 tools/libaio/harness/cases/3.t | 25 tools/libaio/harness/cases/4.t | 72 tools/libaio/harness/cases/5.t | 47 tools/libaio/harness/cases/6.t | 57 tools/libaio/harness/cases/7.t | 27 tools/libaio/harness/cases/8.t | 49 tools/libaio/harness/cases/aio_setup.h | 98 tools/libaio/harness/cases/common-7-8.h | 37 tools/libaio/harness/main.c | 39 tools/libaio/harness/runtests.sh | 19 tools/libaio/libaio.spec | 187 tools/libaio/man/aio.3 | 315 tools/libaio/man/aio_cancel.3 | 137 tools/libaio/man/aio_cancel64.3 | 50 tools/libaio/man/aio_error.3 | 81 tools/libaio/man/aio_error64.3 | 64 tools/libaio/man/aio_fsync.3 | 139 tools/libaio/man/aio_fsync64.3 | 51 tools/libaio/man/aio_init.3 | 96 tools/libaio/man/aio_read.3 | 146 tools/libaio/man/aio_read64.3 | 60 tools/libaio/man/aio_return.3 | 71 tools/libaio/man/aio_return64.3 | 51 tools/libaio/man/aio_suspend.3 | 123 tools/libaio/man/aio_suspend64.3 | 51 tools/libaio/man/aio_write.3 | 176 tools/libaio/man/aio_write64.3 | 61 tools/libaio/man/io.3 | 351 tools/libaio/man/io_cancel.1 | 21 tools/libaio/man/io_cancel.3 | 65 tools/libaio/man/io_destroy.1 | 17 tools/libaio/man/io_fsync.3 | 82 tools/libaio/man/io_getevents.1 | 29 tools/libaio/man/io_getevents.3 | 79 tools/libaio/man/io_prep_fsync.3 | 89 tools/libaio/man/io_prep_pread.3 | 79 tools/libaio/man/io_prep_pwrite.3 | 77 tools/libaio/man/io_queue_init.3 | 63 tools/libaio/man/io_queue_release.3 | 48 tools/libaio/man/io_queue_run.3 | 50 tools/libaio/man/io_queue_wait.3 | 56 tools/libaio/man/io_set_callback.3 | 44 tools/libaio/man/io_setup.1 | 15 tools/libaio/man/io_submit.1 | 109 tools/libaio/man/io_submit.3 | 135 tools/libaio/man/lio_listio.3 | 229 tools/libaio/man/lio_listio64.3 | 39 tools/libaio/src/Makefile | 64 tools/libaio/src/compat-0_1.c | 62 tools/libaio/src/io_cancel.c | 23 tools/libaio/src/io_destroy.c | 23 tools/libaio/src/io_getevents.c | 57 tools/libaio/src/io_queue_init.c | 33 tools/libaio/src/io_queue_release.c | 27 tools/libaio/src/io_queue_run.c | 39 tools/libaio/src/io_queue_wait.c | 31 tools/libaio/src/io_setup.c | 23 tools/libaio/src/io_submit.c | 23 tools/libaio/src/libaio.h | 222 tools/libaio/src/libaio.map | 22 tools/libaio/src/raw_syscall.c | 19 tools/libaio/src/syscall-alpha.h | 209 tools/libaio/src/syscall-i386.h | 72 tools/libaio/src/syscall-ia64.h | 45 tools/libaio/src/syscall-ppc.h | 94 tools/libaio/src/syscall-s390.h | 131 tools/libaio/src/syscall-x86_64.h | 63 tools/libaio/src/syscall.h | 27 tools/libaio/src/vsys_def.h | 24 tools/libxc/Makefile | 3 tools/libxc/xc_load_elf.c | 4 tools/libxc/xc_ppc_linux_build.c | 408 tools/libxc/xenctrl.h | 5 tools/misc/lomount/lomount.c | 430 tools/misc/xend | 7 tools/pygrub/README | 2 tools/python/xen/util/dictio.py | 50 tools/python/xen/util/security.py | 98 tools/python/xen/xend/XendDomain.py | 30 tools/python/xen/xend/XendDomainInfo.py | 14 tools/python/xen/xend/XendLogging.py | 2 tools/python/xen/xend/image.py | 54 tools/python/xen/xend/server/BlktapController.py | 14 tools/python/xen/xend/server/DevController.py | 7 tools/python/xen/xend/server/SrvDaemon.py | 2 tools/python/xen/xend/server/blkif.py | 12 tools/python/xen/xm/addlabel.py | 154 tools/python/xen/xm/create.py | 172 tools/python/xen/xm/dry-run.py | 56 tools/python/xen/xm/getlabel.py | 114 tools/python/xen/xm/main.py | 38 tools/python/xen/xm/resources.py | 56 tools/python/xen/xm/rmlabel.py | 118 tools/vtpm/Makefile | 43 tools/vtpm/tpm_emulator.patch | 1284 - tools/vtpm/vtpm.patch | 1134 - tools/vtpm_manager/Makefile | 14 tools/vtpm_manager/Rules.mk | 1 tools/vtpm_manager/crypto/sym_crypto.c | 17 tools/vtpm_manager/manager/dmictl.c | 114 tools/vtpm_manager/manager/migration.c | 307 tools/vtpm_manager/manager/securestorage.c | 85 tools/vtpm_manager/manager/vtpm_ipc.c | 2 tools/vtpm_manager/manager/vtpm_manager.c | 4 tools/vtpm_manager/manager/vtpm_manager.h | 16 tools/vtpm_manager/manager/vtpm_manager_handler.c | 21 tools/vtpm_manager/manager/vtpmd.c | 3 tools/vtpm_manager/manager/vtpmpriv.h | 39 tools/vtpm_manager/manager/vtsp.c | 68 tools/vtpm_manager/manager/vtsp.h | 3 tools/vtpm_manager/migration/Makefile | 39 tools/vtpm_manager/migration/vtpm_manager_if.c | 186 tools/vtpm_manager/migration/vtpm_migrator.h | 104 tools/vtpm_manager/migration/vtpm_migrator_if.c | 219 tools/vtpm_manager/migration/vtpm_migratorc.c | 211 tools/vtpm_manager/migration/vtpm_migratord.c | 202 tools/vtpm_manager/migration/vtpm_migratord_handler.c | 171 tools/vtpm_manager/tcs/tcs.c | 3 tools/vtpm_manager/tcs/transmit.c | 4 tools/vtpm_manager/util/buffer.c | 23 tools/vtpm_manager/util/buffer.h | 4 tools/vtpm_manager/util/log.h | 4 tools/vtpm_manager/util/tcg.h | 18 tools/xenmon/xenbaked.c | 269 tools/xenmon/xenmon.py | 52 tools/xenstore/Makefile | 24 tools/xm-test/configure.ac | 8 tools/xm-test/ramdisk/Makefile.am | 9 tools/xm-test/ramdisk/bin/create_disk_image | 33 tools/xm-test/tests/enforce_dom0_cpus/01_enforce_dom0_cpus_basic_pos.py | 8 xen/Makefile | 2 xen/Rules.mk | 6 xen/arch/powerpc/0opt.c | 28 xen/arch/powerpc/Makefile | 117 xen/arch/powerpc/Rules.mk | 51 xen/arch/powerpc/audit.c | 45 xen/arch/powerpc/bitops.c | 94 xen/arch/powerpc/boot/boot32.S | 75 xen/arch/powerpc/boot/start.S | 51 xen/arch/powerpc/boot_of.c | 1016 + xen/arch/powerpc/dart.c | 299 xen/arch/powerpc/dart.h | 36 xen/arch/powerpc/dart_u3.c | 108 xen/arch/powerpc/dart_u4.c | 177 xen/arch/powerpc/delay.c | 37 xen/arch/powerpc/dom0_ops.c | 87 xen/arch/powerpc/domain.c | 251 xen/arch/powerpc/domain_build.c | 285 xen/arch/powerpc/elf32.c | 5 xen/arch/powerpc/exceptions.c | 87 xen/arch/powerpc/exceptions.h | 57 xen/arch/powerpc/external.c | 247 xen/arch/powerpc/float.S | 243 xen/arch/powerpc/gdbstub.c | 207 xen/arch/powerpc/hcalls.c | 172 xen/arch/powerpc/htab.c | 69 xen/arch/powerpc/iommu.c | 79 xen/arch/powerpc/iommu.h | 28 xen/arch/powerpc/irq.c | 22 xen/arch/powerpc/mambo.S | 64 xen/arch/powerpc/mm.c | 141 xen/arch/powerpc/mpic.c | 1109 + xen/arch/powerpc/mpic_init.c | 390 xen/arch/powerpc/mpic_init.h | 29 xen/arch/powerpc/of-devtree.c | 1088 + xen/arch/powerpc/of-devtree.h | 139 xen/arch/powerpc/of-devwalk.c | 135 xen/arch/powerpc/of_handler/Makefile | 31 xen/arch/powerpc/of_handler/console.c | 233 xen/arch/powerpc/of_handler/control.c | 90 xen/arch/powerpc/of_handler/cpu.c | 82 xen/arch/powerpc/of_handler/devtree.c | 266 xen/arch/powerpc/of_handler/head.S | 152 xen/arch/powerpc/of_handler/io.c | 160 xen/arch/powerpc/of_handler/leap.S | 38 xen/arch/powerpc/of_handler/memcmp.c | 39 xen/arch/powerpc/of_handler/memory.c | 129 xen/arch/powerpc/of_handler/memset.c | 67 xen/arch/powerpc/of_handler/ofh.c | 454 xen/arch/powerpc/of_handler/ofh.h | 164 xen/arch/powerpc/of_handler/papr.S | 97 xen/arch/powerpc/of_handler/papr.h | 69 xen/arch/powerpc/of_handler/services.c | 96 xen/arch/powerpc/of_handler/snprintf.c | 332 xen/arch/powerpc/of_handler/strcmp.c | 36 xen/arch/powerpc/of_handler/strlen.c | 30 xen/arch/powerpc/of_handler/strncmp.c | 39 xen/arch/powerpc/of_handler/strncpy.c | 54 xen/arch/powerpc/of_handler/strnlen.c | 30 xen/arch/powerpc/of_handler/vdevice.c | 74 xen/arch/powerpc/of_handler/xen_hvcall.S | 28 xen/arch/powerpc/of_handler/xencomm.c | 84 xen/arch/powerpc/ofd_fixup.c | 509 xen/arch/powerpc/oftree.h | 33 xen/arch/powerpc/papr/Makefile | 10 xen/arch/powerpc/papr/debug.c | 84 xen/arch/powerpc/papr/tce.c | 84 xen/arch/powerpc/papr/vtce.c | 158 xen/arch/powerpc/papr/vterm.c | 70 xen/arch/powerpc/papr/xlate.c | 499 xen/arch/powerpc/physdev.c | 24 xen/arch/powerpc/powerpc64/Makefile | 11 xen/arch/powerpc/powerpc64/asm-offsets.c | 65 xen/arch/powerpc/powerpc64/domain.c | 143 xen/arch/powerpc/powerpc64/exceptions.S | 519 xen/arch/powerpc/powerpc64/hypercall_table.S | 83 xen/arch/powerpc/powerpc64/io.S | 142 xen/arch/powerpc/powerpc64/memcpy.S | 171 xen/arch/powerpc/powerpc64/ppc970.c | 164 xen/arch/powerpc/powerpc64/prom_call.S | 116 xen/arch/powerpc/powerpc64/string.S | 286 xen/arch/powerpc/powerpc64/traps.c | 50 xen/arch/powerpc/ppc32/prom_call.c | 41 xen/arch/powerpc/rtas.c | 24 xen/arch/powerpc/setup.c | 370 xen/arch/powerpc/smp.c | 60 xen/arch/powerpc/tce.h | 71 xen/arch/powerpc/time.c | 131 xen/arch/powerpc/usercopy.c | 232 xen/arch/powerpc/xen.lds | 226 xen/arch/x86/hvm/i8254.c | 10 xen/arch/x86/hvm/intercept.c | 4 xen/arch/x86/hvm/io.c | 66 xen/arch/x86/hvm/platform.c | 19 xen/arch/x86/hvm/svm/intr.c | 1 xen/arch/x86/hvm/svm/svm.c | 29 xen/arch/x86/hvm/vmx/io.c | 1 xen/arch/x86/hvm/vmx/vmcs.c | 20 xen/arch/x86/hvm/vmx/vmx.c | 29 xen/arch/x86/irq.c | 15 xen/arch/x86/mm.c | 12 xen/arch/x86/shadow.c | 19 xen/arch/x86/traps.c | 87 xen/arch/x86/x86_emulate.c | 19 xen/common/grant_table.c | 6 xen/common/memory.c | 4 xen/common/trace.c | 24 xen/include/asm-powerpc/asm_defns.h | 28 xen/include/asm-powerpc/atomic.h | 211 xen/include/asm-powerpc/bitops.h | 309 xen/include/asm-powerpc/cache.h | 60 xen/include/asm-powerpc/config.h | 77 xen/include/asm-powerpc/current.h | 79 xen/include/asm-powerpc/debugger.h | 44 xen/include/asm-powerpc/delay.h | 28 xen/include/asm-powerpc/desc.h | 25 xen/include/asm-powerpc/div64.h | 33 xen/include/asm-powerpc/domain.h | 114 xen/include/asm-powerpc/event.h | 99 xen/include/asm-powerpc/flushtlb.h | 108 xen/include/asm-powerpc/grant_table.h | 64 xen/include/asm-powerpc/guest_access.h | 99 xen/include/asm-powerpc/hardirq.h | 21 xen/include/asm-powerpc/hcalls.h | 34 xen/include/asm-powerpc/htab.h | 142 xen/include/asm-powerpc/hypercall.h | 26 xen/include/asm-powerpc/init.h | 59 xen/include/asm-powerpc/io.h | 67 xen/include/asm-powerpc/iocap.h | 26 xen/include/asm-powerpc/irq.h | 31 xen/include/asm-powerpc/mach-default/irq_vectors.h | 105 xen/include/asm-powerpc/memory.h | 39 xen/include/asm-powerpc/misc.h | 33 xen/include/asm-powerpc/mm.h | 224 xen/include/asm-powerpc/mpic.h | 294 xen/include/asm-powerpc/msr.h | 66 xen/include/asm-powerpc/multicall.h | 27 xen/include/asm-powerpc/page.h | 116 xen/include/asm-powerpc/papr.h | 218 xen/include/asm-powerpc/pci.h | 35 xen/include/asm-powerpc/powerpc64/config.h | 45 xen/include/asm-powerpc/powerpc64/ppc970-hid.h | 107 xen/include/asm-powerpc/powerpc64/ppc970.h | 31 xen/include/asm-powerpc/powerpc64/procarea.h | 36 xen/include/asm-powerpc/powerpc64/processor.h | 193 xen/include/asm-powerpc/powerpc64/string.h | 40 xen/include/asm-powerpc/processor.h | 202 xen/include/asm-powerpc/reg_defs.h | 180 xen/include/asm-powerpc/regs.h | 25 xen/include/asm-powerpc/shadow.h | 45 xen/include/asm-powerpc/smp.h | 36 xen/include/asm-powerpc/smpboot.h | 21 xen/include/asm-powerpc/spinlock.h | 221 xen/include/asm-powerpc/string.h | 26 xen/include/asm-powerpc/system.h | 243 xen/include/asm-powerpc/time.h | 42 xen/include/asm-powerpc/types.h | 69 xen/include/asm-powerpc/uaccess.h | 38 xen/include/asm-x86/hvm/io.h | 4 xen/include/asm-x86/hvm/vcpu.h | 18 xen/include/asm-x86/hvm/vpit.h | 4 xen/include/public/arch-powerpc.h | 119 xen/include/public/grant_table.h | 4 xen/include/public/trace.h | 1 xen/include/public/xen.h | 2 xen/include/public/xencomm.h | 37 xen/include/xen/irq.h | 1 xen/include/xen/perfc_defn.h | 2 671 files changed, 143820 insertions(+), 17596 deletions(-) diff -r 2db50529223e -r f7b43e5c42b9 .hgignore --- a/.hgignore Tue Jul 25 09:51:50 2006 -0600 +++ b/.hgignore Tue Jul 25 12:19:05 2006 -0600 @@ -54,6 +54,7 @@ ^extras/mini-os/h/xen-public$ ^extras/mini-os/mini-os\..*$ ^install/.*$ +^linux-[^/]*-native/.*$ ^linux-[^/]*-xen/.*$ ^linux-[^/]*-xen0/.*$ ^linux-[^/]*-xenU/.*$ @@ -73,27 +74,11 @@ ^tools/.*/TAGS$ ^tools/.*/build/lib.*/.*\.py$ ^tools/blktap/Makefile\.smh$ -^tools/blktap/blkcow$ -^tools/blktap/blkcowgnbd$ -^tools/blktap/blkcowimg$ -^tools/blktap/blkdump$ -^tools/blktap/blkgnbd$ -^tools/blktap/blkimg$ -^tools/blktap/bstest$ -^tools/blktap/parallax/blockstored$ -^tools/blktap/parallax/parallax$ -^tools/blktap/parallax/vdi_create$ -^tools/blktap/parallax/vdi_fill$ -^tools/blktap/parallax/vdi_list$ -^tools/blktap/parallax/vdi_snap$ -^tools/blktap/parallax/vdi_snap_delete$ -^tools/blktap/parallax/vdi_snap_list$ -^tools/blktap/parallax/vdi_tree$ -^tools/blktap/parallax/vdi_validate$ -^tools/blktap/ublkback/ublkback$ -^tools/blktap/vdi\.dot$ -^tools/blktap/vdi\.ps$ -^tools/blktap/xen/.*$ +^tools/blktap/drivers/blktapctrl$ +^tools/blktap/drivers/img2qcow$ +^tools/blktap/drivers/qcow-create$ +^tools/blktap/drivers/qcow2raw$ +^tools/blktap/drivers/tapdisk$ ^tools/check/\..*$ ^tools/console/xenconsole$ ^tools/console/xenconsoled$ @@ -122,13 +107,21 @@ ^tools/firmware/vmxassist/roms\.h$ ^tools/firmware/vmxassist/vmxassist$ ^tools/firmware/vmxassist/vmxloader$ -^tools/ioemu/config-host\..*$ -^tools/ioemu/keysym_adapter_sdl\.h$ -^tools/ioemu/keysym_adapter_vnc\.h$ -^tools/ioemu/target-.*/Makefile$ -^tools/ioemu/target-.*/config\..*$ -^tools/ioemu/target-.*/qemu-dm$ +^tools/ioemu/\.pc/.*$ +^tools/ioemu/config-host\.h$ +^tools/ioemu/config-host\.mak$ +^tools/ioemu/i386-dm/config\.h$ +^tools/ioemu/i386-dm/config\.mak$ +^tools/ioemu/i386-dm/qemu-dm$ +^tools/ioemu/qemu-doc\.html$ +^tools/ioemu/qemu-img\.1$ +^tools/ioemu/qemu-img\.pod$ +^tools/ioemu/qemu-tech\.html$ +^tools/ioemu/qemu\.1$ +^tools/ioemu/qemu\.pod$ ^tools/libxc/xen/.*$ +^tools/libaio/src/.*\.ol$ +^tools/libaio/src/.*\.os$ ^tools/misc/cpuperf/cpuperf-perfcntr$ ^tools/misc/cpuperf/cpuperf-xen$ ^tools/misc/lomount/lomount$ @@ -203,3 +196,7 @@ ^xen/xen$ ^xen/xen-syms$ ^xen/xen\..*$ +^xen/arch/ppc/dom0\.bin$ +^xen/arch/ppc/asm-offsets\.s$ +^xen/arch/ppc/firmware +^xen/arch/ppc/firmware_image diff -r 2db50529223e -r f7b43e5c42b9 Config.mk --- a/Config.mk Tue Jul 25 09:51:50 2006 -0600 +++ b/Config.mk Tue Jul 25 12:19:05 2006 -0600 @@ -3,8 +3,8 @@ # A debug build of Xen and tools? debug ?= n -# Currently supported architectures: x86_32, x86_64 -XEN_COMPILE_ARCH ?= $(shell uname -m | sed -e s/i.86/x86_32/) +XEN_COMPILE_ARCH ?= $(shell uname -m | sed -e s/i.86/x86_32/ \ + -e s/ppc/powerpc/) XEN_TARGET_ARCH ?= $(XEN_COMPILE_ARCH) XEN_TARGET_X86_PAE ?= n diff -r 2db50529223e -r f7b43e5c42b9 buildconfigs/Rules.mk --- a/buildconfigs/Rules.mk Tue Jul 25 09:51:50 2006 -0600 +++ b/buildconfigs/Rules.mk Tue Jul 25 12:19:05 2006 -0600 @@ -69,9 +69,6 @@ ref-%/.valid-ref: pristine-%/.valid-pris touch $@ # update timestamp to avoid rebuild endif -%-prep: - $(MAKE) -f buildconfigs/mk.$* prep - %-install: $(MAKE) -f buildconfigs/mk.$* build @@ -83,14 +80,19 @@ endif %-build: %-dist @: # do nothing +%-prep: DESTDIR=$(DISTDIR)/install +%-prep: + $(MAKE) -f buildconfigs/mk.$* prep + +%-config: DESTDIR=$(DISTDIR)/install +%-config: + $(MAKE) -f buildconfigs/mk.$* config + %-delete: $(MAKE) -f buildconfigs/mk.$* delete %-clean: $(MAKE) -f buildconfigs/mk.$* clean - -%-config: - $(MAKE) -f buildconfigs/mk.$* config linux-2.6-xen.patch: ref-linux-$(LINUX_VER)/.valid-ref rm -rf tmp-$@ diff -r 2db50529223e -r f7b43e5c42b9 buildconfigs/linux-defconfig_xen0_ia64 --- a/buildconfigs/linux-defconfig_xen0_ia64 Tue Jul 25 09:51:50 2006 -0600 +++ b/buildconfigs/linux-defconfig_xen0_ia64 Tue Jul 25 12:19:05 2006 -0600 @@ -1527,6 +1527,7 @@ CONFIG_XEN_BACKEND=y # CONFIG_XEN_PCIDEV_BACKEND is not set CONFIG_XEN_BLKDEV_BACKEND=y CONFIG_XEN_XENBUS_DEV=y +# CONFIG_XEN_BLKDEV_TAP is not set # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set CONFIG_XEN_NETDEV_LOOPBACK=y # CONFIG_XEN_TPMDEV_BACKEND is not set diff -r 2db50529223e -r f7b43e5c42b9 buildconfigs/linux-defconfig_xen0_x86_32 --- a/buildconfigs/linux-defconfig_xen0_x86_32 Tue Jul 25 09:51:50 2006 -0600 +++ b/buildconfigs/linux-defconfig_xen0_x86_32 Tue Jul 25 12:19:05 2006 -0600 @@ -1322,6 +1322,7 @@ CONFIG_XEN_PCIDEV_BACKEND_PASS=y CONFIG_XEN_PCIDEV_BACKEND_PASS=y # CONFIG_XEN_PCIDEV_BE_DEBUG is not set CONFIG_XEN_BLKDEV_BACKEND=y +CONFIG_XEN_BLKDEV_TAP=y CONFIG_XEN_NETDEV_BACKEND=y # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set CONFIG_XEN_NETDEV_LOOPBACK=y diff -r 2db50529223e -r f7b43e5c42b9 buildconfigs/linux-defconfig_xen0_x86_64 --- a/buildconfigs/linux-defconfig_xen0_x86_64 Tue Jul 25 09:51:50 2006 -0600 +++ b/buildconfigs/linux-defconfig_xen0_x86_64 Tue Jul 25 12:19:05 2006 -0600 @@ -1263,6 +1263,7 @@ CONFIG_XEN_PCIDEV_BACKEND_PASS=y CONFIG_XEN_PCIDEV_BACKEND_PASS=y # CONFIG_XEN_PCIDEV_BE_DEBUG is not set CONFIG_XEN_BLKDEV_BACKEND=y +CONFIG_XEN_BLKDEV_TAP=y CONFIG_XEN_NETDEV_BACKEND=y # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set CONFIG_XEN_NETDEV_LOOPBACK=y diff -r 2db50529223e -r f7b43e5c42b9 buildconfigs/linux-defconfig_xen_ia64 --- a/buildconfigs/linux-defconfig_xen_ia64 Tue Jul 25 09:51:50 2006 -0600 +++ b/buildconfigs/linux-defconfig_xen_ia64 Tue Jul 25 12:19:05 2006 -0600 @@ -1533,6 +1533,7 @@ CONFIG_XEN_BACKEND=y # CONFIG_XEN_PCIDEV_BACKEND is not set CONFIG_XEN_BLKDEV_BACKEND=y CONFIG_XEN_XENBUS_DEV=y +# CONFIG_XEN_BLKDEV_TAP is not set # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set CONFIG_XEN_NETDEV_LOOPBACK=y # CONFIG_XEN_TPMDEV_BACKEND is not set diff -r 2db50529223e -r f7b43e5c42b9 buildconfigs/linux-defconfig_xen_x86_32 --- a/buildconfigs/linux-defconfig_xen_x86_32 Tue Jul 25 09:51:50 2006 -0600 +++ b/buildconfigs/linux-defconfig_xen_x86_32 Tue Jul 25 12:19:05 2006 -0600 @@ -3023,6 +3023,7 @@ CONFIG_XEN_PCIDEV_BACKEND_VPCI=y # CONFIG_XEN_PCIDEV_BACKEND_PASS is not set # CONFIG_XEN_PCIDEV_BE_DEBUG is not set CONFIG_XEN_BLKDEV_BACKEND=y +CONFIG_XEN_BLKDEV_TAP=y CONFIG_XEN_NETDEV_BACKEND=y # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set CONFIG_XEN_NETDEV_LOOPBACK=y diff -r 2db50529223e -r f7b43e5c42b9 buildconfigs/linux-defconfig_xen_x86_64 --- a/buildconfigs/linux-defconfig_xen_x86_64 Tue Jul 25 09:51:50 2006 -0600 +++ b/buildconfigs/linux-defconfig_xen_x86_64 Tue Jul 25 12:19:05 2006 -0600 @@ -2855,6 +2855,7 @@ CONFIG_XEN_PCIDEV_BACKEND_PASS=y CONFIG_XEN_PCIDEV_BACKEND_PASS=y # CONFIG_XEN_PCIDEV_BE_DEBUG is not set CONFIG_XEN_BLKDEV_BACKEND=y +CONFIG_XEN_BLKDEV_TAP=y CONFIG_XEN_NETDEV_BACKEND=y # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set CONFIG_XEN_NETDEV_LOOPBACK=y diff -r 2db50529223e -r f7b43e5c42b9 buildconfigs/mk.linux-2.6-xen --- a/buildconfigs/mk.linux-2.6-xen Tue Jul 25 09:51:50 2006 -0600 +++ b/buildconfigs/mk.linux-2.6-xen Tue Jul 25 12:19:05 2006 -0600 @@ -4,6 +4,11 @@ EXTRAVERSION ?= xen EXTRAVERSION ?= xen LINUX_DIR = linux-$(LINUX_VER)-$(EXTRAVERSION) + +IMAGE_TARGET ?= vmlinuz +INSTALL_BOOT_PATH ?= $(DESTDIR) + +LINUX_VER3 := $(LINUX_SERIES).$(word 3, $(subst ., ,$(LINUX_VER))) include buildconfigs/Rules.mk @@ -14,8 +19,9 @@ build: $(LINUX_DIR)/include/linux/autoco $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) modules ; \ $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_MOD_PATH=$(DESTDIR) modules_install ; \ fi - $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_PATH=$(DESTDIR) vmlinuz - $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_PATH=$(DESTDIR) install + $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_PATH=$(DESTDIR) $(IMAGE_TARGET) + mkdir -p $(INSTALL_BOOT_PATH) + $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_PATH=$(INSTALL_BOOT_PATH) install $(LINUX_DIR)/include/linux/autoconf.h: ref-linux-$(LINUX_VER)/.valid-ref rm -rf $(LINUX_DIR) @@ -25,10 +31,9 @@ build: $(LINUX_DIR)/include/linux/autoco LINUX_ARCH=$(LINUX_ARCH) bash ./mkbuildtree ../$(LINUX_DIR) ) # Re-use config from install dir if one exits else use default config CONFIG_VERSION=$$(sed -ne 's/^EXTRAVERSION = //p' $(LINUX_DIR)/Makefile); \ - [ -r $(DESTDIR)/boot/config-$(LINUX_VER)$$CONFIG_VERSION-$(EXTRAVERSION) ] && \ - cp $(DESTDIR)/boot/config-$(LINUX_VER)$$CONFIG_VERSION-$(EXTRAVERSION) $(LINUX_DIR)/.config \ - || cp buildconfigs/linux-defconfig_$(EXTRAVERSION)_$(XEN_TARGET_ARCH)$(XEN_SYSTYPE) \ - $(LINUX_DIR)/.config + [ -r $(DESTDIR)/boot/config-$(LINUX_VER3)$$CONFIG_VERSION-$(EXTRAVERSION) ] && \ + cp $(DESTDIR)/boot/config-$(LINUX_VER3)$$CONFIG_VERSION-$(EXTRAVERSION) $(LINUX_DIR)/.config \ + || sh buildconfigs/create_config.sh $(LINUX_DIR)/.config $(EXTRAVERSION) $(XEN_TARGET_ARCH) $(XEN_SYSTYPE) # See if we need to munge config to enable PAE $(MAKE) CONFIG_FILE=$(LINUX_DIR)/.config -f buildconfigs/Rules.mk config-update-pae # Patch kernel Makefile to set EXTRAVERSION diff -r 2db50529223e -r f7b43e5c42b9 config/ia64.mk --- a/config/ia64.mk Tue Jul 25 09:51:50 2006 -0600 +++ b/config/ia64.mk Tue Jul 25 12:19:05 2006 -0600 @@ -1,4 +1,5 @@ CONFIG_IA64 := y CONFIG_IA64 := y CONFIG_IOEMU := y +CONFIG_XCUTILS := y LIBDIR := lib diff -r 2db50529223e -r f7b43e5c42b9 config/x86_32.mk --- a/config/x86_32.mk Tue Jul 25 09:51:50 2006 -0600 +++ b/config/x86_32.mk Tue Jul 25 12:19:05 2006 -0600 @@ -1,7 +1,7 @@ CONFIG_X86 := y CONFIG_X86 := y -CONFIG_PLAN9 := y CONFIG_HVM := y CONFIG_MIGRATE := y +CONFIG_XCUTILS := y CONFIG_IOEMU := y CONFIG_MBOOTPACK := y diff -r 2db50529223e -r f7b43e5c42b9 config/x86_64.mk --- a/config/x86_64.mk Tue Jul 25 09:51:50 2006 -0600 +++ b/config/x86_64.mk Tue Jul 25 12:19:05 2006 -0600 @@ -1,7 +1,7 @@ CONFIG_X86 := y CONFIG_X86 := y -CONFIG_PLAN9 := y CONFIG_HVM := y CONFIG_MIGRATE := y +CONFIG_XCUTILS := y CONFIG_IOEMU := y CONFIG_MBOOTPACK := y diff -r 2db50529223e -r f7b43e5c42b9 extras/mini-os/mm.c --- a/extras/mini-os/mm.c Tue Jul 25 09:51:50 2006 -0600 +++ b/extras/mini-os/mm.c Tue Jul 25 12:19:05 2006 -0600 @@ -687,7 +687,7 @@ void *map_frames(unsigned long *f, unsig /* Find a run of n contiguous frames */ for (x = 0; x <= 1024 - n; x += y + 1) { for (y = 0; y < n; y++) - if (demand_map_pgt[y] & _PAGE_PRESENT) + if (demand_map_pgt[x+y] & _PAGE_PRESENT) break; if (y == n) break; diff -r 2db50529223e -r f7b43e5c42b9 linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c --- a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Tue Jul 25 09:51:50 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Tue Jul 25 12:19:05 2006 -0600 @@ -29,6 +29,7 @@ #include <xen/interface/xen.h> #include <xen/interface/xenoprof.h> #include <../../../drivers/oprofile/cpu_buffer.h> +#include <../../../drivers/oprofile/event_buffer.h> static int xenoprof_start(void); static void xenoprof_stop(void); @@ -151,16 +152,27 @@ static void xenoprof_handle_passive(void static void xenoprof_handle_passive(void) { int i, j; - - for (i = 0; i < pdomains; i++) + int flag_domain, flag_switch = 0; + + for (i = 0; i < pdomains; i++) { + flag_domain = 0; for (j = 0; j < passive_domains[i].nbuf; j++) { xenoprof_buf_t *buf = p_xenoprof_buf[i][j]; if (buf->event_head == buf->event_tail) continue; - oprofile_add_pc(IGNORED_PC, CPU_MODE_PASSIVE_START, passive_domains[i].domain_id); + if (!flag_domain) { + if (!oprofile_add_domain_switch(passive_domains[i]. + domain_id)) + goto done; + flag_domain = 1; + } xenoprof_add_pc(buf, 1); - oprofile_add_pc(IGNORED_PC, CPU_MODE_PASSIVE_STOP, passive_domains[i].domain_id); - } + flag_switch = 1; + } + } +done: + if (flag_switch) + oprofile_add_domain_switch(COORDINATOR_DOMAIN); } static irqreturn_t @@ -177,6 +189,7 @@ xenoprof_ovf_interrupt(int irq, void * d if (is_primary && !test_and_set_bit(0, &flag)) { xenoprof_handle_passive(); + smp_mb__before_clear_bit(); clear_bit(0, &flag); } diff -r 2db50529223e -r f7b43e5c42b9 linux-2.6-xen-sparse/drivers/xen/Kconfig --- a/linux-2.6-xen-sparse/drivers/xen/Kconfig Tue Jul 25 09:51:50 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig Tue Jul 25 12:19:05 2006 -0600 @@ -29,6 +29,11 @@ config XEN_UNPRIVILEGED_GUEST default !XEN_PRIVILEGED_GUEST config XEN_PRIVCMD + bool + depends on PROC_FS + default y + +config XEN_XENBUS_DEV bool depends on PROC_FS default y @@ -40,8 +45,59 @@ config XEN_BACKEND Support for backend device drivers that provide I/O services to other virtual machines. +config XEN_BLKDEV_BACKEND + tristate "Block-device backend driver" + depends on XEN_BACKEND + default y + help + The block-device backend driver allows the kernel to export its + block devices to other guests via a high-performance shared-memory + interface. + +config XEN_BLKDEV_TAP + tristate "Block-device tap backend driver" + depends on XEN_BACKEND + default XEN_PRIVILEGED_GUEST + help + The block tap driver is an alternative to the block back driver + and allows VM block requests to be redirected to userspace through + a device interface. The tap allows user-space development of + high-performance block backends, where disk images may be implemented + as files, in memory, or on other hosts across the network. This + driver can safely coexist with the existing blockback driver. + +config XEN_NETDEV_BACKEND + tristate "Network-device backend driver" + depends on XEN_BACKEND && NET + default y + help + The network-device backend driver allows the kernel to export its + network devices to other guests via a high-performance shared-memory + interface. + +config XEN_NETDEV_PIPELINED_TRANSMITTER + bool "Pipelined transmitter (DANGEROUS)" + depends on XEN_NETDEV_BACKEND + default n + help + If the net backend is a dumb domain, such as a transparent Ethernet + bridge with no local IP interface, it is safe to say Y here to get + slightly lower network overhead. + If the backend has a local IP interface; or may be doing smart things + like reassembling packets to perform firewall filtering; or if you + are unsure; or if you experience network hangs when this option is + enabled; then you must say N here. + +config XEN_NETDEV_LOOPBACK + tristate "Network-device loopback driver" + depends on XEN_NETDEV_BACKEND + default y + help + A two-interface loopback device to emulate a local netfront-netback + connection. + config XEN_PCIDEV_BACKEND - tristate "PCI device backend driver" + tristate "PCI-device backend driver" depends on PCI && XEN_BACKEND default XEN_PRIVILEGED_GUEST help @@ -80,50 +136,6 @@ config XEN_PCIDEV_BE_DEBUG depends on XEN_PCIDEV_BACKEND default n -config XEN_BLKDEV_BACKEND - tristate "Block-device backend driver" - depends on XEN_BACKEND - default y - help - The block-device backend driver allows the kernel to export its - block devices to other guests via a high-performance shared-memory - interface. - -config XEN_XENBUS_DEV - bool - depends on PROC_FS - default y - -config XEN_NETDEV_BACKEND - tristate "Network-device backend driver" - depends on XEN_BACKEND && NET - default y - help - The network-device backend driver allows the kernel to export its - network devices to other guests via a high-performance shared-memory - interface. - -config XEN_NETDEV_PIPELINED_TRANSMITTER - bool "Pipelined transmitter (DANGEROUS)" - depends on XEN_NETDEV_BACKEND - default n - help - If the net backend is a dumb domain, such as a transparent Ethernet - bridge with no local IP interface, it is safe to say Y here to get - slightly lower network overhead. - If the backend has a local IP interface; or may be doing smart things - like reassembling packets to perform firewall filtering; or if you - are unsure; or if you experience network hangs when this option is - enabled; then you must say N here. - -config XEN_NETDEV_LOOPBACK - tristate "Network-device loopback driver" - depends on XEN_NETDEV_BACKEND - default y - help - A two-interface loopback device to emulate a local netfront-netback - connection. - config XEN_TPMDEV_BACKEND tristate "TPM-device backend driver" depends on XEN_BACKEND @@ -183,7 +195,7 @@ config XEN_SYSFS depends on SYSFS default y help - Xen hypervisor attributes will show up under /sys/hypervisor/. + Xen hypervisor attributes will show up under /sys/hypervisor/. choice prompt "Xen version compatibility" diff -r 2db50529223e -r f7b43e5c42b9 linux-2.6-xen-sparse/drivers/xen/Makefile --- a/linux-2.6-xen-sparse/drivers/xen/Makefile Tue Jul 25 09:51:50 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/Makefile Tue Jul 25 12:19:05 2006 -0600 @@ -8,6 +8,7 @@ obj-$(CONFIG_XEN_BALLOON) += balloon/ obj-$(CONFIG_XEN_BALLOON) += balloon/ obj-$(CONFIG_XEN_DEVMEM) += char/ obj-$(CONFIG_XEN_BLKDEV_BACKEND) += blkback/ +obj-$(CONFIG_XEN_BLKDEV_TAP) += blktap/ obj-$(CONFIG_XEN_NETDEV_BACKEND) += netback/ obj-$(CONFIG_XEN_TPMDEV_BACKEND) += tpmback/ obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += blkfront/ diff -r 2db50529223e -r f7b43e5c42b9 linux-2.6-xen-sparse/drivers/xen/console/console.c --- a/linux-2.6-xen-sparse/drivers/xen/console/console.c Tue Jul 25 09:51:50 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c Tue Jul 25 12:19:05 2006 -0600 @@ -536,18 +536,27 @@ static void xencons_close(struct tty_str if (DUMMY_TTY(tty)) return; - if (tty->count == 1) { - tty->closing = 1; - tty_wait_until_sent(tty, 0); - if (DRV(tty->driver)->flush_buffer != NULL) - DRV(tty->driver)->flush_buffer(tty); - if (tty->ldisc.flush_buffer != NULL) - tty->ldisc.flush_buffer(tty); - tty->closing = 0; - spin_lock_irqsave(&xencons_lock, flags); - xencons_tty = NULL; - spin_unlock_irqrestore(&xencons_lock, flags); - } + down(&tty_sem); + + if (tty->count != 1) { + up(&tty_sem); + return; + } + + /* Prevent other threads from re-opening this tty. */ + set_bit(TTY_CLOSING, &tty->flags); + up(&tty_sem); + + tty->closing = 1; + tty_wait_until_sent(tty, 0); + if (DRV(tty->driver)->flush_buffer != NULL) + DRV(tty->driver)->flush_buffer(tty); + if (tty->ldisc.flush_buffer != NULL) + tty->ldisc.flush_buffer(tty); + tty->closing = 0; + spin_lock_irqsave(&xencons_lock, flags); + xencons_tty = NULL; + spin_unlock_irqrestore(&xencons_lock, flags); } static struct tty_operations xencons_ops = { diff -r 2db50529223e -r f7b43e5c42b9 linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Tue Jul 25 09:51:50 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Tue Jul 25 12:19:05 2006 -0600 @@ -852,11 +852,11 @@ static void processing_timeout(unsigned */ if (pak == packet_find_packet(&dataex.pending_pak, pak) || pak == packet_find_packet(&dataex.current_pak, pak)) { - list_del(&pak->next); if ((pak->flags & PACKET_FLAG_DISCARD_RESPONSE) == 0) { tpm_send_fail_message(pak, pak->req_tag); } - packet_free(pak); + /* discard future responses */ + pak->flags |= PACKET_FLAG_DISCARD_RESPONSE; } write_unlock_irqrestore(&dataex.pak_lock, flags); diff -r 2db50529223e -r f7b43e5c42b9 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h Tue Jul 25 09:51:50 2006 -0600 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h Tue Jul 25 12:19:05 2006 -0600 @@ -120,7 +120,6 @@ dma_set_mask(struct device *dev, u64 mas return 0; } -#ifdef __i386__ static inline int dma_get_cache_alignment(void) { @@ -128,7 +127,6 @@ dma_get_cache_alignment(void) * maximum possible, to be safe */ return (1 << INTERNODE_CACHE_SHIFT); } -#endif #define dma_is_consistent(d) (1) diff -r 2db50529223e -r f7b43e5c42b9 linux-2.6-xen-sparse/include/linux/skbuff.h --- a/linux-2.6-xen-sparse/include/linux/skbuff.h Tue Jul 25 09:51:50 2006 -0600 +++ b/linux-2.6-xen-sparse/include/linux/skbuff.h Tue Jul 25 12:19:05 2006 -0600 @@ -1412,5 +1412,10 @@ static inline void nf_reset(struct sk_bu static inline void nf_reset(struct sk_buff *skb) {} #endif /* CONFIG_NETFILTER */ +static inline int skb_is_gso(const struct sk_buff *skb) +{ + return skb_shinfo(skb)->gso_size; +} + #endif /* __KERNEL__ */ #endif /* _LINUX_SKBUFF_H */ diff -r 2db50529223e -r f7b43e5c42b9 linux-2.6-xen-sparse/net/core/dev.c --- a/linux-2.6-xen-sparse/net/core/dev.c Tue Jul 25 09:51:50 2006 -0600 +++ b/linux-2.6-xen-sparse/net/core/dev.c Tue Jul 25 12:19:05 2006 -0600 @@ -1089,9 +1089,17 @@ int skb_checksum_help(struct sk_buff *sk unsigned int csum; int ret = 0, offset = skb->h.raw - skb->data; - if (inward) { - skb->ip_summed = CHECKSUM_NONE; - goto out; + if (inward) + goto out_set_summed; + + if (unlikely(skb_shinfo(skb)->gso_size)) { + static int warned; + + WARN_ON(!warned); + warned = 1; + + /* Let GSO fix up the checksum. */ + goto out_set_summed; } if (skb_cloned(skb)) { @@ -1108,6 +1116,8 @@ int skb_checksum_help(struct sk_buff *sk BUG_ON(skb->csum + 2 > offset); *(u16*)(skb->h.raw + skb->csum) = csum_fold(csum); + +out_set_summed: skb->ip_summed = CHECKSUM_NONE; out: return ret; @@ -1128,17 +1138,35 @@ struct sk_buff *skb_gso_segment(struct s struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT); struct packet_type *ptype; int type = skb->protocol; + int err; BUG_ON(skb_shinfo(skb)->frag_list); - BUG_ON(skb->ip_summed != CHECKSUM_HW); skb->mac.raw = skb->data; skb->mac_len = skb->nh.raw - skb->data; __skb_pull(skb, skb->mac_len); + if (unlikely(skb->ip_summed != CHECKSUM_HW)) { + static int warned; + + WARN_ON(!warned); + warned = 1; + + if (skb_header_cloned(skb) && + (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) + return ERR_PTR(err); + } + rcu_read_lock(); list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) { if (ptype->type == type && !ptype->dev && ptype->gso_segment) { + if (unlikely(skb->ip_summed != CHECKSUM_HW)) { + err = ptype->gso_send_check(skb); + segs = ERR_PTR(err); + if (err || skb_gso_ok(skb, features)) + break; + __skb_push(skb, skb->data - skb->nh.raw); + } segs = ptype->gso_segment(skb, features); break; } diff -r 2db50529223e -r f7b43e5c42b9 patches/linux-2.6.16.13/net-csum.patch --- a/patches/linux-2.6.16.13/net-csum.patch Tue Jul 25 09:51:50 2006 -0600 +++ b/patches/linux-2.6.16.13/net-csum.patch Tue Jul 25 12:19:05 2006 -0600 @@ -1,40 +1,39 @@ diff -pruN ../pristine-linux-2.6.16.13/n diff -pruN ../pristine-linux-2.6.16.13/net/ipv4/netfilter/ip_nat_proto_tcp.c ./net/ipv4/netfilter/ip_nat_proto_tcp.c --- ../pristine-linux-2.6.16.13/net/ipv4/netfilter/ip_nat_proto_tcp.c 2006-05-02 22:38:44.000000000 +0100 -+++ ./net/ipv4/netfilter/ip_nat_proto_tcp.c 2006-05-04 17:41:37.000000000 +0100 -@@ -129,10 +129,14 @@ tcp_manip_pkt(struct sk_buff **pskb, ++++ ./net/ipv4/netfilter/ip_nat_proto_tcp.c 2006-05-16 13:28:19.000000000 +0100 +@@ -129,7 +129,12 @@ tcp_manip_pkt(struct sk_buff **pskb, if (hdrsize < sizeof(*hdr)) return 1; - hdr->check = ip_nat_cheat_check(~oldip, newip, -+ if ((*pskb)->proto_csum_blank) { ++#ifdef CONFIG_XEN ++ if ((*pskb)->proto_csum_blank) + hdr->check = ip_nat_cheat_check(oldip, ~newip, hdr->check); -+ } else { ++ else ++#endif + hdr->check = ip_nat_cheat_check(~oldip, newip, ip_nat_cheat_check(oldport ^ 0xFFFF, newport, hdr->check)); -+ } - return 1; - } - diff -pruN ../pristine-linux-2.6.16.13/net/ipv4/netfilter/ip_nat_proto_udp.c ./net/ipv4/netfilter/ip_nat_proto_udp.c --- ../pristine-linux-2.6.16.13/net/ipv4/netfilter/ip_nat_proto_udp.c 2006-05-02 22:38:44.000000000 +0100 -+++ ./net/ipv4/netfilter/ip_nat_proto_udp.c 2006-05-04 17:41:37.000000000 +0100 -@@ -113,11 +113,16 @@ udp_manip_pkt(struct sk_buff **pskb, ++++ ./net/ipv4/netfilter/ip_nat_proto_udp.c 2006-05-16 13:30:14.000000000 +0100 +@@ -113,11 +113,17 @@ udp_manip_pkt(struct sk_buff **pskb, newport = tuple->dst.u.udp.port; portptr = &hdr->dest; } - if (hdr->check) /* 0 is a special case meaning no checksum */ - hdr->check = ip_nat_cheat_check(~oldip, newip, + if (hdr->check) { /* 0 is a special case meaning no checksum */ -+ if ((*pskb)->proto_csum_blank) { ++#ifdef CONFIG_XEN ++ if ((*pskb)->proto_csum_blank) + hdr->check = ip_nat_cheat_check(oldip, ~newip, hdr->check); -+ } else { ++ else ++#endif + hdr->check = ip_nat_cheat_check(~oldip, newip, ip_nat_cheat_check(*portptr ^ 0xFFFF, newport, hdr->check)); -+ } + } *portptr = newport; return 1; diff -r 2db50529223e -r f7b43e5c42b9 patches/linux-2.6.16.13/xenoprof-generic.patch --- a/patches/linux-2.6.16.13/xenoprof-generic.patch Tue Jul 25 09:51:50 2006 -0600 +++ b/patches/linux-2.6.16.13/xenoprof-generic.patch Tue Jul 25 12:19:05 2006 -0600 @@ -1,6 +1,6 @@ diff -pru ../pristine-linux-2.6.16.13/dr -diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.c ./drivers/oprofile/buffer_sync.c ---- ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.c 2006-05-03 05:38:44.000000000 +0800 -+++ ./drivers/oprofile/buffer_sync.c 2006-06-27 12:14:53.000000000 +0800 +diff -Naur orig/drivers/oprofile/buffer_sync.c new/drivers/oprofile/buffer_sync.c +--- orig/drivers/oprofile/buffer_sync.c 2006-05-02 14:38:44.000000000 -0700 ++++ new/drivers/oprofile/buffer_sync.c 2006-07-06 18:19:05.000000000 -0700 @@ -6,6 +6,10 @@ * * @author John Levon <levon@xxxxxxxxxxxxxxxxx> @@ -12,7 +12,7 @@ diff -pru ../pristine-linux-2.6.16.13/dr * This is the core of the buffer management. Each * CPU buffer is processed and entered into the * global event buffer. Such processing is necessary -@@ -275,15 +279,30 @@ static void add_cpu_switch(int i) +@@ -275,15 +279,31 @@ last_cookie = INVALID_COOKIE; } @@ -34,22 +34,23 @@ diff -pru ../pristine-linux-2.6.16.13/dr + case CPU_MODE_XEN: + add_event_entry(XEN_ENTER_SWITCH_CODE); + break; -+ case CPU_MODE_PASSIVE_START: -+ add_event_entry(PASSIVE_START_CODE); -+ break; -+ case CPU_MODE_PASSIVE_STOP: -+ add_event_entry(PASSIVE_STOP_CODE); -+ break; + default: + break; + } } - + ++static void add_domain_switch(unsigned long domain_id) ++{ ++ add_event_entry(ESCAPE_CODE); ++ add_event_entry(DOMAIN_SWITCH_CODE); ++ add_event_entry(domain_id); ++} ++ static void add_user_ctx_switch(struct task_struct const * task, unsigned long cookie) { -@@ -348,9 +367,9 @@ static int add_us_sample(struct mm_struc +@@ -348,9 +368,9 @@ * for later lookup from userspace. */ static int @@ -61,7 +62,7 @@ diff -pru ../pristine-linux-2.6.16.13/dr add_sample_entry(s->eip, s->event); return 1; } else if (mm) { -@@ -496,10 +515,11 @@ void sync_buffer(int cpu) +@@ -496,10 +516,11 @@ struct mm_struct *mm = NULL; struct task_struct * new; unsigned long cookie = 0; @@ -70,34 +71,35 @@ diff -pru ../pristine-linux-2.6.16.13/dr unsigned int i; sync_buffer_state state = sb_buffer_start; unsigned long available; -+ int domain_switch = NO_DOMAIN_SWITCH; ++ int domain_switch = 0; down(&buffer_sem); -@@ -513,12 +533,19 @@ void sync_buffer(int cpu) +@@ -512,16 +533,18 @@ + for (i = 0; i < available; ++i) { struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos]; - if (is_code(s->eip)) { +- if (is_code(s->eip)) { - if (s->event <= CPU_IS_KERNEL) { -+ if (s->event < CPU_TRACE_BEGIN) { - /* kernel/userspace switch */ +- /* kernel/userspace switch */ - in_kernel = s->event; ++ if (is_code(s->eip) && !domain_switch) { ++ if (s->event <= CPU_MODE_XEN) { ++ /* xen/kernel/userspace switch */ + cpu_mode = s->event; if (state == sb_buffer_start) state = sb_sample_start; - add_kernel_ctx_switch(s->event); -+ -+ if (s->event == CPU_MODE_PASSIVE_START) -+ domain_switch = DOMAIN_SWITCH_START_EVENT1; -+ else if (s->event == CPU_MODE_PASSIVE_STOP) -+ domain_switch = DOMAIN_SWITCH_STOP_EVENT1; -+ -+ if (domain_switch != DOMAIN_SWITCH_START_EVENT2) -+ add_cpu_mode_switch(s->event); ++ add_cpu_mode_switch(s->event); } else if (s->event == CPU_TRACE_BEGIN) { state = sb_bt_start; add_trace_begin(); -@@ -535,11 +562,20 @@ void sync_buffer(int cpu) ++ } else if (s->event == CPU_DOMAIN_SWITCH) { ++ domain_switch = 1; + } else { + struct mm_struct * oldmm = mm; + +@@ -535,11 +558,16 @@ add_user_ctx_switch(new, cookie); } } else { @@ -106,13 +108,9 @@ diff -pru ../pristine-linux-2.6.16.13/dr - if (state == sb_bt_start) { - state = sb_bt_ignore; - atomic_inc(&oprofile_stats.bt_lost_no_mapping); -+ if (domain_switch == DOMAIN_SWITCH_START_EVENT1) { -+ add_event_entry(s->event); -+ domain_switch = DOMAIN_SWITCH_START_EVENT2; -+ } else if (domain_switch == DOMAIN_SWITCH_START_EVENT1) { -+ add_sample_entry(s->eip, s->event); -+ } else if (domain_switch == DOMAIN_SWITCH_STOP_EVENT1) { -+ domain_switch = NO_DOMAIN_SWITCH; ++ if (domain_switch) { ++ add_domain_switch(s->eip); ++ domain_switch = 0; + } else { + if (state >= sb_bt_start && + !add_sample(mm, s, cpu_mode)) { @@ -123,24 +121,9 @@ diff -pru ../pristine-linux-2.6.16.13/dr } } } -diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.h ./drivers/oprofile/buffer_sync.h ---- ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.h 2006-05-03 05:38:44.000000000 +0800 -+++ ./drivers/oprofile/buffer_sync.h 2006-06-27 12:12:09.000000000 +0800 -@@ -9,6 +9,11 @@ - - #ifndef OPROFILE_BUFFER_SYNC_H - #define OPROFILE_BUFFER_SYNC_H -+ -+#define NO_DOMAIN_SWITCH -1 -+#define DOMAIN_SWITCH_START_EVENT1 0 -+#define DOMAIN_SWITCH_START_EVENT2 1 -+#define DOMAIN_SWITCH_STOP_EVENT1 2 - - /* add the necessary profiling hooks */ - int sync_start(void); -diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c ./drivers/oprofile/cpu_buffer.c ---- ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c 2006-05-03 05:38:44.000000000 +0800 -+++ ./drivers/oprofile/cpu_buffer.c 2006-06-19 22:43:53.000000000 +0800 +diff -Naur orig/drivers/oprofile/cpu_buffer.c new/drivers/oprofile/cpu_buffer.c +--- orig/drivers/oprofile/cpu_buffer.c 2006-05-02 14:38:44.000000000 -0700 ++++ new/drivers/oprofile/cpu_buffer.c 2006-07-06 18:19:05.000000000 -0700 @@ -6,6 +6,10 @@ * * @author John Levon <levon@xxxxxxxxxxxxxxxxx> @@ -152,7 +135,16 @@ diff -pru ../pristine-linux-2.6.16.13/dr * Each CPU has a local buffer that stores PC value/event * pairs. We also log context switches when we notice them. * Eventually each CPU's buffer is processed into the global -@@ -58,7 +62,7 @@ int alloc_cpu_buffers(void) +@@ -34,6 +38,8 @@ + #define DEFAULT_TIMER_EXPIRE (HZ / 10) + static int work_enabled; + ++static int32_t current_domain = COORDINATOR_DOMAIN; ++ + void free_cpu_buffers(void) + { + int i; +@@ -58,7 +64,7 @@ goto fail; b->last_task = NULL; @@ -161,7 +153,7 @@ diff -pru ../pristine-linux-2.6.16.13/dr b->tracing = 0; b->buffer_size = buffer_size; b->tail_pos = 0; -@@ -114,7 +118,7 @@ void cpu_buffer_reset(struct oprofile_cp +@@ -114,7 +120,7 @@ * collected will populate the buffer with proper * values to initialize the buffer */ @@ -170,7 +162,7 @@ diff -pru ../pristine-linux-2.6.16.13/dr cpu_buf->last_task = NULL; } -@@ -164,13 +168,13 @@ add_code(struct oprofile_cpu_buffer * bu +@@ -164,13 +170,13 @@ * because of the head/tail separation of the writer and reader * of the CPU buffer. * @@ -188,7 +180,7 @@ diff -pru ../pristine-linux-2.6.16.13/dr { struct task_struct * task; -@@ -181,16 +185,14 @@ static int log_sample(struct oprofile_cp +@@ -181,18 +187,18 @@ return 0; } @@ -207,12 +199,43 @@ diff -pru ../pristine-linux-2.6.16.13/dr - + /* notice a task switch */ - if (cpu_buf->last_task != task) { +- if (cpu_buf->last_task != task) { ++ /* if not processing other domain samples */ ++ if ((cpu_buf->last_task != task) && ++ (current_domain == COORDINATOR_DOMAIN)) { cpu_buf->last_task = task; -diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.h ./drivers/oprofile/cpu_buffer.h ---- ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.h 2006-05-03 05:38:44.000000000 +0800 -+++ ./drivers/oprofile/cpu_buffer.h 2006-06-27 10:38:08.000000000 +0800 -@@ -36,7 +36,7 @@ struct oprofile_cpu_buffer { + add_code(cpu_buf, (unsigned long)task); + } +@@ -269,6 +275,25 @@ + add_sample(cpu_buf, pc, 0); + } + ++int oprofile_add_domain_switch(int32_t domain_id) ++{ ++ struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()]; ++ ++ /* should have space for switching into and out of domain ++ (2 slots each) plus one sample and one cpu mode switch */ ++ if (((nr_available_slots(cpu_buf) < 6) && ++ (domain_id != COORDINATOR_DOMAIN)) || ++ (nr_available_slots(cpu_buf) < 2)) ++ return 0; ++ ++ add_code(cpu_buf, CPU_DOMAIN_SWITCH); ++ add_sample(cpu_buf, domain_id, 0); ++ ++ current_domain = domain_id; ++ ++ return 1; ++} ++ + /* + * This serves to avoid cpu buffer overflow, and makes sure + * the task mortuary progresses +diff -Naur orig/drivers/oprofile/cpu_buffer.h new/drivers/oprofile/cpu_buffer.h +--- orig/drivers/oprofile/cpu_buffer.h 2006-05-02 14:38:44.000000000 -0700 ++++ new/drivers/oprofile/cpu_buffer.h 2006-07-06 18:19:05.000000000 -0700 +@@ -36,7 +36,7 @@ volatile unsigned long tail_pos; unsigned long buffer_size; struct task_struct * last_task; @@ -221,7 +244,7 @@ diff -pru ../pristine-linux-2.6.16.13/dr int tracing; struct op_sample * buffer; unsigned long sample_received; -@@ -51,7 +51,13 @@ extern struct oprofile_cpu_buffer cpu_bu +@@ -51,7 +51,10 @@ void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf); /* transient events for the CPU buffer -> event buffer */ @@ -230,17 +253,14 @@ diff -pru ../pristine-linux-2.6.16.13/dr +#define CPU_MODE_USER 0 +#define CPU_MODE_KERNEL 1 +#define CPU_MODE_XEN 2 -+#define CPU_MODE_PASSIVE_START 3 -+#define CPU_MODE_PASSIVE_STOP 4 -+#define CPU_TRACE_BEGIN 5 -+ -+#define IGNORED_PC 0 ++#define CPU_TRACE_BEGIN 3 ++#define CPU_DOMAIN_SWITCH 4 #endif /* OPROFILE_CPU_BUFFER_H */ -diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/event_buffer.h ./drivers/oprofile/event_buffer.h ---- ../pristine-linux-2.6.16.13/drivers/oprofile/event_buffer.h 2006-05-03 05:38:44.000000000 +0800 -+++ ./drivers/oprofile/event_buffer.h 2006-06-19 22:43:53.000000000 +0800 -@@ -29,11 +29,14 @@ void wake_up_buffer_waiter(void); +diff -Naur orig/drivers/oprofile/event_buffer.h new/drivers/oprofile/event_buffer.h +--- orig/drivers/oprofile/event_buffer.h 2006-05-02 14:38:44.000000000 -0700 ++++ new/drivers/oprofile/event_buffer.h 2006-07-06 18:19:05.000000000 -0700 +@@ -29,15 +29,20 @@ #define CPU_SWITCH_CODE 2 #define COOKIE_SWITCH_CODE 3 #define KERNEL_ENTER_SWITCH_CODE 4 @@ -251,14 +271,20 @@ diff -pru ../pristine-linux-2.6.16.13/dr #define TRACE_BEGIN_CODE 8 #define TRACE_END_CODE 9 +#define XEN_ENTER_SWITCH_CODE 10 -+#define PASSIVE_START_CODE 11 -+#define PASSIVE_STOP_CODE 12 ++#define DOMAIN_SWITCH_CODE 11 #define INVALID_COOKIE ~0UL #define NO_COOKIE 0UL -diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.c ./drivers/oprofile/oprof.c ---- ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.c 2006-05-03 05:38:44.000000000 +0800 -+++ ./drivers/oprofile/oprof.c 2006-06-19 23:45:17.000000000 +0800 + ++/* Constant used to refer to coordinator domain (Xen) */ ++#define COORDINATOR_DOMAIN -1 ++ + /* add data to the event buffer */ + void add_event_entry(unsigned long data); + +diff -Naur orig/drivers/oprofile/oprof.c new/drivers/oprofile/oprof.c +--- orig/drivers/oprofile/oprof.c 2006-05-02 14:38:44.000000000 -0700 ++++ new/drivers/oprofile/oprof.c 2006-07-06 18:19:05.000000000 -0700 @@ -5,6 +5,10 @@ * @remark Read the file COPYING * @@ -279,7 +305,7 @@ diff -pru ../pristine-linux-2.6.16.13/dr struct oprofile_operations oprofile_ops; unsigned long oprofile_started; -@@ -33,6 +37,32 @@ static DECLARE_MUTEX(start_sem); +@@ -33,6 +37,32 @@ */ static int timer = 0; @@ -312,10 +338,10 @@ diff -pru ../pristine-linux-2.6.16.13/dr int oprofile_setup(void) { int err; -diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.h ./drivers/oprofile/oprof.h ---- ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.h 2006-05-03 05:38:44.000000000 +0800 -+++ ./drivers/oprofile/oprof.h 2006-06-19 23:42:36.000000000 +0800 -@@ -35,5 +35,8 @@ void oprofile_create_files(struct super_ +diff -Naur orig/drivers/oprofile/oprof.h new/drivers/oprofile/oprof.h +--- orig/drivers/oprofile/oprof.h 2006-05-02 14:38:44.000000000 -0700 ++++ new/drivers/oprofile/oprof.h 2006-07-06 18:19:05.000000000 -0700 +@@ -35,5 +35,8 @@ void oprofile_timer_init(struct oprofile_operations * ops); int oprofile_set_backtrace(unsigned long depth); @@ -324,9 +350,9 @@ diff -pru ../pristine-linux-2.6.16.13/dr +int oprofile_set_passive(int passive_domains[], unsigned int pdomains); #endif /* OPROF_H */ -diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/oprofile_files.c ./drivers/oprofile/oprofile_files.c ---- ../pristine-linux-2.6.16.13/drivers/oprofile/oprofile_files.c 2006-05-03 05:38:44.000000000 +0800 -+++ ./drivers/oprofile/oprofile_files.c 2006-06-19 23:29:07.000000000 +0800 +diff -Naur orig/drivers/oprofile/oprofile_files.c new/drivers/oprofile/oprofile_files.c +--- orig/drivers/oprofile/oprofile_files.c 2006-05-02 14:38:44.000000000 -0700 ++++ new/drivers/oprofile/oprofile_files.c 2006-07-06 18:19:05.000000000 -0700 @@ -5,15 +5,21 @@ * @remark Read the file COPYING * @@ -350,7 +376,7 @@ diff -pru ../pristine-linux-2.6.16.13/dr unsigned long fs_buffer_size = 131072; unsigned long fs_cpu_buffer_size = 8192; unsigned long fs_buffer_watershed = 32768; /* FIXME: tune */ -@@ -117,11 +123,202 @@ static ssize_t dump_write(struct file * +@@ -117,11 +123,202 @@ static struct file_operations dump_fops = { .write = dump_write, }; @@ -554,8 +580,9 @@ diff -pru ../pristine-linux-2.6.16.13/dr oprofilefs_create_file(sb, root, "buffer", &event_buffer_fops); oprofilefs_create_ulong(sb, root, "buffer_size", &fs_buffer_size); oprofilefs_create_ulong(sb, root, "buffer_watershed", &fs_buffer_watershed); ---- ../pristine-linux-2.6.16.13/include/linux/oprofile.h 2006-05-03 05:38:44.000000000 +0800 -+++ ./include/linux/oprofile.h 2006-06-19 23:52:00.000000000 +0800 +diff -Naur orig/include/linux/oprofile.h new/include/linux/oprofile.h +--- orig/include/linux/oprofile.h 2006-05-02 14:38:44.000000000 -0700 ++++ new/include/linux/oprofile.h 2006-07-06 18:19:31.000000000 -0700 @@ -16,6 +16,8 @@ #include <linux/types.h> #include <linux/spinlock.h> @@ -565,7 +592,7 @@ diff -pru ../pristine-linux-2.6.16.13/dr struct super_block; struct dentry; -@@ -27,6 +29,11 @@ struct oprofile_operations { +@@ -27,6 +29,11 @@ /* create any necessary configuration files in the oprofile fs. * Optional. */ int (*create_files)(struct super_block * sb, struct dentry * root); @@ -577,3 +604,12 @@ diff -pru ../pristine-linux-2.6.16.13/dr /* Do any necessary interrupt setup. Optional. */ int (*setup)(void); /* Do any necessary interrupt shutdown. Optional. */ +@@ -68,6 +75,8 @@ + /* add a backtrace entry, to be called from the ->backtrace callback */ + void oprofile_add_trace(unsigned long eip); + ++/* add a domain switch entry */ ++int oprofile_add_domain_switch(int32_t domain_id); + + /** + * Create a file of the given name as a child of the given root, with diff -r 2db50529223e -r f7b43e5c42b9 tools/Makefile --- a/tools/Makefile Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/Makefile Tue Jul 25 12:19:05 2006 -0600 @@ -7,7 +7,7 @@ SUBDIRS-y += misc SUBDIRS-y += misc SUBDIRS-y += examples SUBDIRS-y += xentrace -SUBDIRS-$(CONFIG_X86) += xcutils +SUBDIRS-$(CONFIG_XCUTILS) += xcutils SUBDIRS-y += firmware SUBDIRS-y += security SUBDIRS-y += console @@ -16,6 +16,8 @@ SUBDIRS-$(VTPM_TOOLS) += vtpm_manager SUBDIRS-$(VTPM_TOOLS) += vtpm_manager SUBDIRS-$(VTPM_TOOLS) += vtpm SUBDIRS-y += xenstat +SUBDIRS-y += libaio +SUBDIRS-y += blktap # These don't cross-compile ifeq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH)) @@ -58,10 +60,13 @@ check_clean: .PHONY: ioemu ioemuinstall ioemuclean ifdef CONFIG_IOEMU -ioemu ioemuinstall ioemuclean: - [ -f ioemu/config-host.h ] || \ - (cd ioemu; sh ./configure --prefix=usr) - $(MAKE) -C ioemu $(patsubst ioemu%,%,$@) +export IOEMU_DIR ?= ioemu +ioemu ioemuinstall: + [ -f $(IOEMU_DIR)/config-host.mak ] || \ + (cd $(IOEMU_DIR) && sh configure --prefix=/usr) + $(MAKE) -C $(IOEMU_DIR) $(patsubst ioemu%,%,$@) +ioemuclean: + $(MAKE) -C $(IOEMU_DIR) distclean else ioemu ioemuinstall ioemuclean: endif diff -r 2db50529223e -r f7b43e5c42b9 tools/examples/Makefile --- a/tools/examples/Makefile Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/examples/Makefile Tue Jul 25 12:19:05 2006 -0600 @@ -26,7 +26,8 @@ XEN_SCRIPTS += network-nat vif-nat XEN_SCRIPTS += network-nat vif-nat XEN_SCRIPTS += block XEN_SCRIPTS += block-enbd block-nbd -XEN_SCRIPTS += vtpm vtpm-delete vtpm-addtodb +XEN_SCRIPTS += blktap +XEN_SCRIPTS += vtpm vtpm-delete XEN_SCRIPTS += xen-hotplug-cleanup XEN_SCRIPTS += external-device-migrate XEN_SCRIPT_DATA = xen-script-common.sh locking.sh logging.sh diff -r 2db50529223e -r f7b43e5c42b9 tools/examples/README --- a/tools/examples/README Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/examples/README Tue Jul 25 12:19:05 2006 -0600 @@ -25,7 +25,6 @@ vif-nat - xen virtual networ vif-nat - xen virtual network start/stop script in NAT mode vif-route - xen virtual network start/stop script in routed mode vtpm - called by xen-backend.agent to bind/unbind vTPM devices -vtpm-addtodb - script for adding a vTPM instance to the vTPM table vtpm-common.sh - common code for vTPM handling vtpm-delete - remove an entry from the vTPM table given the domain's name diff -r 2db50529223e -r f7b43e5c42b9 tools/examples/vtpm-common.sh --- a/tools/examples/vtpm-common.sh Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/examples/vtpm-common.sh Tue Jul 25 12:19:05 2006 -0600 @@ -24,12 +24,9 @@ VTPMDB="/etc/xen/vtpm.db" #In the vtpm-impl file some commands should be defined: # vtpm_create, vtpm_setup, vtpm_start, etc. (see below) -#This should be indicated by setting VTPM_IMPL_DEFINED. if [ -r "$dir/vtpm-impl" ]; then . "$dir/vtpm-impl" -fi - -if [ -z "$VTPM_IMPL_DEFINED" ]; then +else function vtpm_create () { true } @@ -245,6 +242,12 @@ function vtpm_create_instance () { claim_lock vtpmdb instance=$(vtpmdb_find_instance $domname) + + if [ "$instance" == "0" -a "$reason" != "create" ]; then + release_lock vtpmdb + return + fi + if [ "$instance" == "0" ]; then #Try to give the preferred instance to the domain instance=$(xenstore_read "$XENBUS_PATH"/pref_instance) @@ -317,7 +320,7 @@ function vtpm_delete_instance () { # "-1" : the given machine name is invalid # "0" : this is not an address of this machine # "1" : this is an address local to this machine -function isLocalAddress() { +function vtpm_isLocalAddress() { local addr res addr=$(ping $1 -c 1 | \ gawk '{ print substr($3,2,length($3)-2); exit }') @@ -347,7 +350,7 @@ function isLocalAddress() { # 2nd: name of the domain to migrate # 3rd: the migration step to perform function vtpm_migration_step() { - local res=$(isLocalAddress $1) + local res=$(vtpm_isLocalAddress $1) if [ "$res" == "0" ]; then vtpm_migrate $1 $2 $3 fi @@ -361,8 +364,39 @@ function vtpm_migration_step() { # 3rd: the last successful migration step that was done function vtpm_recover() { local res - res=$(isLocalAddress $1) + res=$(vtpm_isLocalAddress $1) if [ "$res" == "0" ]; then vtpm_migrate_recover $1 $2 $3 fi } + + +#Determine the domain id given a domain's name. +#1st parameter: name of the domain +#return value: domain id or -1 if domain id could not be determined +function vtpm_domid_from_name () { + local id name ids + ids=$(xenstore-list /local/domain) + for id in $ids; do + name=$(xenstore-read /local/domain/$id/name) + if [ "$name" == "$1" ]; then + echo "$id" + return + fi + done + echo "-1" +} + + +#Add a virtual TPM instance number and its associated domain name +#to the VTPMDB file and activate usage of this virtual TPM instance +#by writing the instance number into the xenstore +#1st parm: name of virtual machine +#2nd parm: instance of assoicate virtual TPM +function vtpm_add_and_activate() { + local domid=$(vtpm_domid_from_name $1) + if [ "$domid" != "-1" ]; then + vtpmdb_add_instance $1 $2 + xenstore-write backend/vtpm/$domid/0/instance $2 + fi +} diff -r 2db50529223e -r f7b43e5c42b9 tools/examples/vtpm-impl --- a/tools/examples/vtpm-impl Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/examples/vtpm-impl Tue Jul 25 12:19:05 2006 -0600 @@ -32,8 +32,6 @@ # OF THE POSSIBILITY OF SUCH DAMAGE. # =================================================================== -VTPM_IMPL_DEFINED=1 - # | SRC | TAG | CMD SIZE | ORD | type| mode TPM_CMD_OPEN=\\x00\\x00\\x00\\x00\\x01\\xc1\\x00\\x00\\x00\\x10\\x01\\x00\\x00\\x01\\x01\\x01 TPM_CMD_RESM=\\x00\\x00\\x00\\x00\\x01\\xc1\\x00\\x00\\x00\\x10\\x01\\x00\\x00\\x01\\x01\\x02 @@ -44,6 +42,8 @@ TPM_SUCCESS=00000000 TX_VTPM_MANAGER=/var/vtpm/fifos/from_console.fifo RX_VTPM_MANAGER=/var/vtpm/fifos/to_console.fifo + +VTPM_MIG=/usr/bin/vtpm_migrator # -------------------- Helpers for binary streams ----------- @@ -67,11 +67,17 @@ function vtpm_manager_cmd() { local inst=$2; local inst_bin=$(hex32_to_bin $inst); + claim_lock vtpm_mgr + #send cmd to vtpm_manager printf "$cmd$inst_bin" > $TX_VTPM_MANAGER #recv response + set +e local resp_hex=`dd skip=10 bs=1 count=4 if=$RX_VTPM_MANAGER 2> /dev/null | xxd -ps` + set -e + + release_lock vtpm_mgr #return whether the command was successful if [ $resp_hex != $TPM_SUCCESS ]; then @@ -126,11 +132,55 @@ function vtpm_delete() { fi } +# Perform a migration step. This function differentiates between migration +# to the local host or to a remote machine. +# Parameters: +# 1st: destination host to migrate to +# 2nd: name of the domain to migrate +# 3rd: the migration step to perform function vtpm_migrate() { - echo "Error: vTPM migration accross machines not implemented." + local instance res + + instance=$(vtpmdb_find_instance $2) + if [ "$instance" == "" ]; then + log err "VTPM Migratoin failed. Unable to translation of domain name" + echo "Error: VTPM Migration failed while looking up instance number" + fi + + case "$3" in + 0) + #Incicate migration supported + echo "0" + ;; + + 1) + # Get Public Key from Destination + # Call vtpm_manager's migration part 1 + claim_lock vtpm_mgr + $VTPM_MIG $1 $2 $instance $3 + release_lock vtpm_mgr + ;; + + 2) + # Call manager's migration step 2 and send result to destination + # If successful remove from db + claim_lock vtpm_mgr + $VTPM_MIG $1 $2 $instance $3 + release_lock vtpm_mgr + ;; + + 3) + if `ps x | grep "$VTPM_MIG $1"`; then + log err "VTPM Migration failed to complete." + echo "Error: VTPM Migration failed to complete." + fi + ;; + esac + } + function vtpm_migrate_recover() { - true + echo "Error: Recovery not supported yet" } diff -r 2db50529223e -r f7b43e5c42b9 tools/examples/xen-backend.agent --- a/tools/examples/xen-backend.agent Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/examples/xen-backend.agent Tue Jul 25 12:19:05 2006 -0600 @@ -7,6 +7,9 @@ claim_lock xenbus_hotplug_global claim_lock xenbus_hotplug_global case "$XENBUS_TYPE" in + tap) + /etc/xen/scripts/blktap "$ACTION" + ;; vbd) /etc/xen/scripts/block "$ACTION" ;; diff -r 2db50529223e -r f7b43e5c42b9 tools/examples/xen-backend.rules --- a/tools/examples/xen-backend.rules Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/examples/xen-backend.rules Tue Jul 25 12:19:05 2006 -0600 @@ -1,3 +1,4 @@ SUBSYSTEM=="xen-backend", KERNEL=="vbd*" +SUBSYSTEM=="xen-backend", KERNEL=="tap*", RUN+="/etc/xen/scripts/blktap $env{ACTION}" SUBSYSTEM=="xen-backend", KERNEL=="vbd*", RUN+="/etc/xen/scripts/block $env{ACTION}" SUBSYSTEM=="xen-backend", KERNEL=="vtpm*", RUN+="/etc/xen/scripts/vtpm $env{ACTION}" SUBSYSTEM=="xen-backend", KERNEL=="vif*", ACTION=="online", RUN+="$env{script} online" diff -r 2db50529223e -r f7b43e5c42b9 tools/examples/xmexample.hvm --- a/tools/examples/xmexample.hvm Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/examples/xmexample.hvm Tue Jul 25 12:19:05 2006 -0600 @@ -54,7 +54,7 @@ name = "ExampleHVMDomain" # Optionally define mac and/or bridge for the network interfaces. # Random MACs are assigned if not given. -#vif = [ 'type=ioemu, mac=00:16:3e:00:00:11, bridge=xenbr0' ] +#vif = [ 'type=ioemu, mac=00:16:3e:00:00:11, bridge=xenbr0, model=ne2k_pci' ] # type=ioemu specify the NIC is an ioemu device not netfront vif = [ 'type=ioemu, bridge=xenbr0' ] @@ -130,8 +130,13 @@ vnc=1 vnc=1 #---------------------------------------------------------------------------- -# enable spawning vncviewer(only valid when vnc=1), default = 1 -vncviewer=1 +# set VNC display number, default = domid +#vncdisplay=1 + +#---------------------------------------------------------------------------- +# enable spawning vncviewer for domain's console +# (only valid when vnc=1), default = 0 +#vncconsole=0 #---------------------------------------------------------------------------- # no graphics, use serial port @@ -146,10 +151,6 @@ stdvga=0 # then xm console or minicom can connect serial='pty' -#---------------------------------------------------------------------------- -# enable ne2000, default = 0(use pcnet) -ne2000=0 - #----------------------------------------------------------------------------- # enable audio support diff -r 2db50529223e -r f7b43e5c42b9 tools/firmware/vmxassist/vmxassist.ld --- a/tools/firmware/vmxassist/vmxassist.ld Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/firmware/vmxassist/vmxassist.ld Tue Jul 25 12:19:05 2006 -0600 @@ -11,8 +11,7 @@ SECTIONS _btext = .; *(.text) *(.rodata) - *(.rodata.str1.1) - *(.rodata.str1.4) + *(.rodata.*) _etext = .; } diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/Changelog --- a/tools/ioemu/Changelog Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/Changelog Tue Jul 25 12:19:05 2006 -0600 @@ -1,3 +1,84 @@ version 0.6.1: +version 0.8.1: + + - USB tablet support (Brad Campbell, Anthony Liguori) + - win32 host serial support (Kazu) + - PC speaker support (Joachim Henke) + - IDE LBA48 support (Jens Axboe) + - SSE3 support + - Solaris port (Ben Taylor) + - Preliminary SH4 target (Samuel Tardieu) + - VNC server (Anthony Liguori) + - slirp fixes (Ed Swierk et al.) + - USB fixes + - ARM Versatile Platform Baseboard emulation (Paul Brook) + +version 0.8.0: + + - ARM system emulation: Arm Integrator/CP board with an arm1026ej-s + cpu (Paul Brook) + - SMP support + - Mac OS X cocoa improvements (Mike Kronenberg) + - Mac OS X CoreAudio driver (Mike Kronenberg) + - DirectSound driver (malc) + - ALSA audio driver (malc) + - new audio options: '-soundhw' and '-audio-help' (malc) + - ES1370 PCI audio device (malc) + - Initial USB support + - Linux host serial port access + - Linux host low level parallel port access + - New network emulation code supporting VLANs. + - MIPS and MIPSel User Linux emulation + - MIPS fixes to boot Linux (Daniel Jacobowitz) + - NX bit support + - Initial SPARC SMP support (Blue Swirl) + - Major overhaul of the virtual FAT driver for read/write support + (Johannes Schindelin) + +version 0.7.2: + + - x86_64 fixes (Win2000 and Linux 2.6 boot in 32 bit) + - merge self modifying code handling in dirty ram page mecanism. + - MIPS fixes (Ralf Baechle) + - better user net performances + +version 0.7.1: + + - read-only Virtual FAT support (Johannes Schindelin) + - Windows 2000 install disk full hack (original idea from Vladimir + N. Oleynik) + - VMDK disk image creation (Filip Navara) + - SPARC64 progress (Blue Swirl) + - initial MIPS support (Jocelyn mayer) + - MIPS improvements (Ralf Baechle) + - 64 bit fixes in user networking (initial patch by Gwenole Beauchesne) + - IOAPIC support (Filip Navara) + +version 0.7.0: + + - better BIOS translation and HDD geometry auto-detection + - user mode networking bug fix + - undocumented FPU ops support + - Cirrus VGA: support for 1280x1024x[8,15,16] modes + - 'pidfile' option + - .dmg disk image format support (Johannes Schindelin) + - keymaps support (initial patch by Johannes Schindelin) + - big endian ARM support (Lennert Buytenhek) + - added generic 64 bit target support + - x86_64 target support + - initial APIC support + - MMX/SSE/SSE2/PNI support + - PC parallel port support (Mark Jonckheere) + - initial SPARC64 support (Blue Swirl) + - SPARC target boots Linux (Blue Swirl) + - armv5te user mode support (Paul Brook) + - ARM VFP support (Paul Brook) + - ARM "Angel" semihosting syscalls (Paul Brook) + - user mode gdb stub support (Paul Brook) + - Samba 3 support + - initial Cocoa support (Pierre d'Herbemont) + - generic FPU emulation code + - Virtual PC read-only disk image support (Alex Beregszaszi) + version 0.6.1: - Mac OS X port (Pierre d'Herbemont) diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/Makefile --- a/tools/ioemu/Makefile Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/Makefile Tue Jul 25 12:19:05 2006 -0600 @@ -3,89 +3,112 @@ include $(XEN_ROOT)/tools/Rules.mk -include config-host.mak -CFLAGS+=-g -fno-strict-aliasing +CFLAGS+=-Wall -O2 -g -fno-strict-aliasing -I. ifdef CONFIG_DARWIN CFLAGS+= -mdynamic-no-pic -endif -ifdef CONFIG_WIN32 -CFLAGS+=-fpack-struct endif LDFLAGS=-g LIBS= DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -TOOLS=qemu-img +TOOLS=qemu-img$(EXESUF) ifdef CONFIG_STATIC LDFLAGS+=-static endif -#DOCS=qemu-doc.html qemu-tech.html qemu.1 +ifdef BUILD_DOCS +DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 +else +DOCS= +endif -.PHONY: all -all: $(DOCS) HEADERS +all: $(DOCS) for d in $(TARGET_DIRS); do \ $(MAKE) -C $$d $@ || exit 1 ; \ done -qemu-img: qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c +qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c $(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS) dyngen$(EXESUF): dyngen.c $(HOST_CC) $(CFLAGS) $(DEFINES) -o $@ $^ -.PHONY: clean clean: # avoid old build problems by removing potentially incorrect old files rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h - rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS qemu.pod *~ */*~ - #$(MAKE) -C tests clean + rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS *.pod *~ */*~ + $(MAKE) -C tests clean for d in $(TARGET_DIRS); do \ - $(MAKE) -C $$d $@ || exit 1 ; \ + [ -d $$d ] && $(MAKE) -C $$d $@ || exit 0 ; \ done - rm -f config-host.mak config-host.h - rm -f keysym_adapter_sdl.h keysym_adapter_vnc.h -.PHONY: distclean distclean: clean - rm -f config-host.mak config-host.h - rm -f keysym_adapter_sdl.h keysym_adapter_vnc.h + rm -f config-host.mak config-host.h $(DOCS) for d in $(TARGET_DIRS); do \ - $(MAKE) -C $$d $@ || exit 1 ; \ + rm -rf $$d || exit 1 ; \ done KEYMAPS=da en-gb et fr fr-ch is lt modifiers no pt-br sv \ ar de en-us fi fr-be hr it lv nl pl ru th \ common de-ch es fo fr-ca hu ja mk nl-be pt sl tr -.PHONY: install -install: all - mkdir -p "$(bindir)" - mkdir -p "$(DESTDIR)/$(datadir)" - mkdir -p "$(DESTDIR)/$(datadir)/keymaps" - install -m 644 $(addprefix keymaps/,$(KEYMAPS)) "$(DESTDIR)/$(datadir)/keymaps" +install-doc: $(DOCS) + mkdir -p "$(DESTDIR)$(docdir)" + $(INSTALL) -m 644 qemu-doc.html qemu-tech.html "$(DESTDIR)$(docdir)" +ifndef CONFIG_WIN32 + mkdir -p "$(DESTDIR)$(mandir)/man1" + $(INSTALL) qemu.1 qemu-img.1 "$(DESTDIR)$(mandir)/man1" +endif + +install: all $(if $(BUILD_DOCS),install-doc) + mkdir -p "$(DESTDIR)$(bindir)" +# $(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)" +# mkdir -p "$(DESTDIR)$(datadir)" +# for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \ +# video.x proll.elf linux_boot.bin; do \ +# $(INSTALL) -m 644 $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \ +# done +ifndef CONFIG_WIN32 + mkdir -p "$(DESTDIR)$(datadir)/keymaps" + for x in $(KEYMAPS); do \ + $(INSTALL) -m 644 $(SRC_PATH)/keymaps/$$x "$(DESTDIR)$(datadir)/keymaps"; \ + done +endif for d in $(TARGET_DIRS); do \ $(MAKE) -C $$d $@ || exit 1 ; \ done # various test targets -.PHONY: test speed test2 test speed test2: all $(MAKE) -C tests $@ -.PHONY: TAGS TAGS: etags *.[ch] tests/*.[ch] + +cscope: + rm -f ./cscope.* + find . -name "*.[ch]" -print > ./cscope.files + cscope -b # documentation %.html: %.texi texi2html -monolithic -number $< +%.info: %.texi + makeinfo $< -o $@ + +%.dvi: %.texi + texi2dvi $< + qemu.1: qemu-doc.texi - ./texi2pod.pl $< qemu.pod + perl -w $(SRC_PATH)/texi2pod.pl $< qemu.pod pod2man --section=1 --center=" " --release=" " qemu.pod > $@ + +qemu-img.1: qemu-img.texi + perl -w $(SRC_PATH)/texi2pod.pl $< qemu-img.pod + pod2man --section=1 --center=" " --release=" " qemu-img.pod > $@ FILE=qemu-$(shell cat VERSION) # tar release (use 'make -k tar' on a checkouted tree) -.PHONY: tar tar: rm -rf /tmp/$(FILE) cp -r . /tmp/$(FILE) @@ -93,36 +116,34 @@ tar: rm -rf /tmp/$(FILE) # generate a binary distribution -.PHONY: tarbin tarbin: - ( cd $(DESTDIR) ; tar zcvf ~/qemu-$(VERSION)-i386.tar.gz \ - $(DESTDIR)/$(bindir)/qemu $(DESTDIR)/$(bindir)/qemu-fast \ - $(DESTDIR)/$(bindir)/qemu-system-ppc \ - $(DESTDIR)/$(bindir)/qemu-i386 \ - $(DESTDIR)/$(bindir)/qemu-arm \ - $(DESTDIR)/$(bindir)/qemu-sparc \ - $(DESTDIR)/$(bindir)/qemu-ppc \ - $(DESTDIR)/$(mandir)/man1/qemu.1 $(DESTDIR)/$(mandir)/man1/qemu-mkcow.1 ) + ( cd / ; tar zcvf ~/qemu-$(VERSION)-i386.tar.gz \ + $(bindir)/qemu \ + $(bindir)/qemu-system-ppc \ + $(bindir)/qemu-system-sparc \ + $(bindir)/qemu-system-x86_64 \ + $(bindir)/qemu-system-mips \ + $(bindir)/qemu-system-mipsel \ + $(bindir)/qemu-system-arm \ + $(bindir)/qemu-i386 \ + $(bindir)/qemu-arm \ + $(bindir)/qemu-armeb \ + $(bindir)/qemu-sparc \ + $(bindir)/qemu-ppc \ + $(bindir)/qemu-mips \ + $(bindir)/qemu-mipsel \ + $(bindir)/qemu-img \ + $(datadir)/bios.bin \ + $(datadir)/vgabios.bin \ + $(datadir)/vgabios-cirrus.bin \ + $(datadir)/ppc_rom.bin \ + $(datadir)/video.x \ + $(datadir)/proll.elf \ + $(datadir)/linux_boot.bin \ + $(docdir)/qemu-doc.html \ + $(docdir)/qemu-tech.html \ + $(mandir)/man1/qemu.1 $(mandir)/man1/qemu-img.1 ) ifneq ($(wildcard .depend),) include .depend endif - -.PHONY: HEADERS -HEADERS: - -ifdef CONFIG_SDL -HEADERS: keysym_adapter_sdl.h -endif - -ifdef CONFIG_VNC -HEADERS: keysym_adapter_vnc.h -endif - -keysym_adapter_sdl.h: Makefile create_keysym_header.sh - sh create_keysym_header.sh sdl "$(SDL_CFLAGS)" - -keysym_adapter_vnc.h: Makefile create_keysym_header.sh - sh create_keysym_header.sh vnc "$(VNC_CFLAGS)" - - diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/README --- a/tools/ioemu/README Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/README Tue Jul 25 12:19:05 2006 -0600 @@ -1,61 +1,3 @@ The QEMU x86 emulator -The QEMU x86 emulator ---------------------- - -INSTALLATION ------------- - -Type - - ./configure - make - -to build qemu, qemu-CPU and libqemu.a (CPU is the name of the various -supported target CPUs). - -Type - - make install - -to install QEMU in /usr/local - -Tested tool versions --------------------- - -In order to compile QEMU succesfully, it is very important that you -have the right tools. The most important one is gcc. I cannot guaranty -that QEMU works if you do not use a tested gcc version. Look at -'configure' and 'Makefile' if you want to make a different gcc -version work. - -host gcc binutils glibc linux distribution ----------------------------------------------------------------------- -x86 2.95.2 2.13.2 2.1.3 2.4.18 - 3.2 2.13.2 2.1.3 2.4.18 - 2.96 2.11.93.0.2 2.2.5 2.4.18 Red Hat 7.3 - 3.2.2 2.13.90.0.18 2.3.2 2.4.20 Red Hat 9 - -PowerPC 3.3 [4] 2.13.90.0.18 2.3.1 2.4.20briq - 3.2 - -Alpha 3.3 [1] 2.14.90.0.4 2.2.5 2.2.20 [2] Debian 3.0 - -Sparc32 2.95.4 2.12.90.0.1 2.2.5 2.4.18 Debian 3.0 - -ARM 2.95.4 2.12.90.0.1 2.2.5 2.4.9 [3] Debian 3.0 - -[1] On Alpha, QEMU needs the gcc 'visibility' attribute only available - for gcc version >= 3.3. -[2] Linux >= 2.4.20 is necessary for precise exception support - (untested). -[3] 2.4.9-ac10-rmk2-np1-cerf2 - -[4] gcc 2.95.x generates invalid code when using too many register -variables. You must use gcc 3.x on PowerPC. - -Documentation -------------- - Read the documentation in qemu-doc.html. - Fabrice Bellard. \ No newline at end of file diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/TODO --- a/tools/ioemu/TODO Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/TODO Tue Jul 25 12:19:05 2006 -0600 @@ -1,20 +1,19 @@ short term: short term: ---------- +- support variable tsc freq +- cpu_interrupt() win32/SMP fix +- USB host async +- IDE async - debug option in 'configure' script + disable -fomit-frame-pointer -- Solaris display error with Cirrus VGA - (http://lists.gnu.org/archive/html/qemu-devel/2004-10/msg00390.html). - Precise VGA timings for old games/demos (malc patch) - merge PIC spurious interrupt patch -- merge VNC keyboard patch - merge Solaris patch -- merge ARM patches + self modifying code patch (Paul Brook) -- warning for OS/2: must not use 128 MB memory +- warning for OS/2: must not use 128 MB memory (merge bochs cmos patch ?) - config file (at least for windows/Mac OS X) - commit message if execution of code in IO memory - update doc: PCI infos. - VNC patch + Synaptic patch. - basic VGA optimizations -- test sysenter/sysexit and fxsr for L4 pistachio 686 - physical memory cache (reduce qemu-fast address space size to about 32 MB) - better code fetch (different exception handling + CS.limit support) - do not resize vga if invalid size. @@ -33,34 +32,30 @@ short term: - fix all remaining thread lock issues (must put TBs in a specific invalid state, find a solution for tb_flush()). - fix arm fpu rounding (at least for float->integer conversions) -- SMP support ppc specific: ------------ - TLB invalidate not needed if msr_pr changes -- endianness bugs in do_load_fpscr and do_store_fpscr - SPR_ENCODE() not useful - enable shift optimizations ? -lower priority: --------------- -- more friendly BIOS (logo) -- int15 ah=86: use better timing -- HDD geometry in CMOS (not used except for very old DOS programs) -- suppress shift_mem ops -- fix some 16 bit sp push/pop overflow (pusha/popa, lcall lret) -- sysenter/sysexit emulation -- optimize FPU operations (evaluate x87 stack pointer statically) +linux-user specific: +------------------- - add IPC syscalls -- use -msoft-float on ARM -- use kernel traps for unaligned accesses on ARM ? - handle rare page fault cases (in particular if page fault in helpers or in syscall emulation code). -- fix thread stack freeing (use kernel 2.5.x CLONE_CHILD_CLEARTID) - more syscalls (in particular all 64 bit ones, IPCs, fix 64 bit issues, fix 16 bit uid issues) - use page_unprotect_range in every suitable syscall to handle all cases of self modifying code. -- use gcc as a backend to generate better code (easy to do by using - op-i386.c operations as local inline functions). -- add SSE2/MMX operations +- fix thread stack freeing (use kernel 2.5.x CLONE_CHILD_CLEARTID) +- use kernel traps for unaligned accesses on ARM ? + + +lower priority: +-------------- +- int15 ah=86: use better timing +- suppress shift_mem ops +- fix some 16 bit sp push/pop overflow (pusha/popa, lcall lret) +- optimize FPU operations (evaluate x87 stack pointer statically) +- use -msoft-float on ARM diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/VERSION --- a/tools/ioemu/VERSION Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/VERSION Tue Jul 25 12:19:05 2006 -0600 @@ -1,1 +1,1 @@ 0.6.1 -0.6.1 \ No newline at end of file +0.8.1 \ No newline at end of file diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/audio/audio.c --- a/tools/ioemu/audio/audio.c Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/audio/audio.c Tue Jul 25 12:19:05 2006 -0600 @@ -1,8 +1,8 @@ /* * QEMU Audio subsystem - * - * Copyright (c) 2003-2004 Vassili Karpov (malc) - * + * + * Copyright (c) 2003-2005 Vassili Karpov (malc) + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -21,34 +21,95 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include <assert.h> #include "vl.h" -#define USE_WAV_AUDIO - -#include "audio/audio_int.h" - -#define dolog(...) AUD_log ("audio", __VA_ARGS__) -#ifdef DEBUG -#define ldebug(...) dolog (__VA_ARGS__) +#define AUDIO_CAP "audio" +#include "audio_int.h" + +/* #define DEBUG_PLIVE */ +/* #define DEBUG_LIVE */ +/* #define DEBUG_OUT */ + +#define SW_NAME(sw) (sw)->name ? (sw)->name : "unknown" + +static struct audio_driver *drvtab[] = { +#ifdef CONFIG_OSS + &oss_audio_driver, +#endif +#ifdef CONFIG_ALSA + &alsa_audio_driver, +#endif +#ifdef CONFIG_COREAUDIO + &coreaudio_audio_driver, +#endif +#ifdef CONFIG_DSOUND + &dsound_audio_driver, +#endif +#ifdef CONFIG_FMOD + &fmod_audio_driver, +#endif +#ifdef CONFIG_SDL + &sdl_audio_driver, +#endif + &no_audio_driver, + &wav_audio_driver +}; + +struct fixed_settings { + int enabled; + int nb_voices; + int greedy; + audsettings_t settings; +}; + +static struct { + struct fixed_settings fixed_out; + struct fixed_settings fixed_in; + union { + int hz; + int64_t ticks; + } period; + int plive; + int log_to_monitor; +} conf = { + { /* DAC fixed settings */ + 1, /* enabled */ + 1, /* nb_voices */ + 1, /* greedy */ + { + 44100, /* freq */ + 2, /* nchannels */ + AUD_FMT_S16 /* fmt */ + } + }, + + { /* ADC fixed settings */ + 1, /* enabled */ + 1, /* nb_voices */ + 1, /* greedy */ + { + 44100, /* freq */ + 2, /* nchannels */ + AUD_FMT_S16 /* fmt */ + } + }, + + { 0 }, /* period */ + 0, /* plive */ + 0 /* log_to_monitor */ +}; + +static AudioState glob_audio_state; + +volume_t nominal_volume = { + 0, +#ifdef FLOAT_MIXENG + 1.0, + 1.0 #else -#define ldebug(...) -#endif - -#define QC_AUDIO_DRV "QEMU_AUDIO_DRV" -#define QC_VOICES "QEMU_VOICES" -#define QC_FIXED_FORMAT "QEMU_FIXED_FORMAT" -#define QC_FIXED_FREQ "QEMU_FIXED_FREQ" - -static HWVoice *hw_voices; - -AudioState audio_state = { - 1, /* use fixed settings */ - 44100, /* fixed frequency */ - 2, /* fixed channels */ - AUD_FMT_S16, /* fixed format */ - 1, /* number of hw voices */ - -1 /* voice size */ + UINT_MAX, + UINT_MAX +#endif }; /* http://www.df.lth.se/~john_e/gems/gem002d.html */ @@ -68,74 +129,419 @@ inline uint32_t lsbindex (uint32_t u) return popcount ((u&-u)-1); } -int audio_get_conf_int (const char *key, int defval) -{ - int val = defval; +#ifdef AUDIO_IS_FLAWLESS_AND_NO_CHECKS_ARE_REQURIED +#error No its not +#else +int audio_bug (const char *funcname, int cond) +{ + if (cond) { + static int shown; + + AUD_log (NULL, "Error a bug that was just triggered in %s\n", funcname); + if (!shown) { + shown = 1; + AUD_log (NULL, "Save all your work and restart without audio\n"); + AUD_log (NULL, "Please send bug report to malc@xxxxxxxxxxxxx\n"); + AUD_log (NULL, "I am sorry\n"); + } + AUD_log (NULL, "Context:\n"); + +#if defined AUDIO_BREAKPOINT_ON_BUG +# if defined HOST_I386 +# if defined __GNUC__ + __asm__ ("int3"); +# elif defined _MSC_VER + _asm _emit 0xcc; +# else + abort (); +# endif +# else + abort (); +# endif +#endif + } + + return cond; +} +#endif + +void *audio_calloc (const char *funcname, int nmemb, size_t size) +{ + int cond; + size_t len; + + len = nmemb * size; + cond = !nmemb || !size; + cond |= nmemb < 0; + cond |= len < size; + + if (audio_bug ("audio_calloc", cond)) { + AUD_log (NULL, "%s passed invalid arguments to audio_calloc\n", + funcname); + AUD_log (NULL, "nmemb=%d size=%zu (len=%zu)\n", nmemb, size, len); + return NULL; + } + + return qemu_mallocz (len); +} + +static char *audio_alloc_prefix (const char *s) +{ + const char qemu_prefix[] = "QEMU_"; + size_t len; + char *r; + + if (!s) { + return NULL; + } + + len = strlen (s); + r = qemu_malloc (len + sizeof (qemu_prefix)); + + if (r) { + size_t i; + char *u = r + sizeof (qemu_prefix) - 1; + + strcpy (r, qemu_prefix); + strcat (r, s); + + for (i = 0; i < len; ++i) { + u[i] = toupper (u[i]); + } + } + return r; +} + +const char *audio_audfmt_to_string (audfmt_e fmt) +{ + switch (fmt) { + case AUD_FMT_U8: + return "U8"; + + case AUD_FMT_U16: + return "U16"; + + case AUD_FMT_S8: + return "S8"; + + case AUD_FMT_S16: + return "S16"; + } + + dolog ("Bogus audfmt %d returning S16\n", fmt); + return "S16"; +} + +audfmt_e audio_string_to_audfmt (const char *s, audfmt_e defval, int *defaultp) +{ + if (!strcasecmp (s, "u8")) { + *defaultp = 0; + return AUD_FMT_U8; + } + else if (!strcasecmp (s, "u16")) { + *defaultp = 0; + return AUD_FMT_U16; + } + else if (!strcasecmp (s, "s8")) { + *defaultp = 0; + return AUD_FMT_S8; + } + else if (!strcasecmp (s, "s16")) { + *defaultp = 0; + return AUD_FMT_S16; + } + else { + dolog ("Bogus audio format `%s' using %s\n", + s, audio_audfmt_to_string (defval)); + *defaultp = 1; + return defval; + } +} + +static audfmt_e audio_get_conf_fmt (const char *envname, + audfmt_e defval, + int *defaultp) +{ + const char *var = getenv (envname); + if (!var) { + *defaultp = 1; + return defval; + } + return audio_string_to_audfmt (var, defval, defaultp); +} + +static int audio_get_conf_int (const char *key, int defval, int *defaultp) +{ + int val; char *strval; strval = getenv (key); if (strval) { + *defaultp = 0; val = atoi (strval); - } - - return val; -} - -const char *audio_get_conf_str (const char *key, const char *defval) + return val; + } + else { + *defaultp = 1; + return defval; + } +} + +static const char *audio_get_conf_str (const char *key, + const char *defval, + int *defaultp) { const char *val = getenv (key); - if (!val) + if (!val) { + *defaultp = 1; return defval; - else + } + else { + *defaultp = 0; return val; + } +} + +void AUD_vlog (const char *cap, const char *fmt, va_list ap) +{ + if (conf.log_to_monitor) { + if (cap) { + term_printf ("%s: ", cap); + } + + term_vprintf (fmt, ap); + } + else { + if (cap) { + fprintf (stderr, "%s: ", cap); + } + + vfprintf (stderr, fmt, ap); + } } void AUD_log (const char *cap, const char *fmt, ...) { va_list ap; - fprintf (stderr, "%s: ", cap); + va_start (ap, fmt); - vfprintf (stderr, fmt, ap); + AUD_vlog (cap, fmt, ap); va_end (ap); } -/* - * Soft Voice - */ -void pcm_sw_free_resources (SWVoice *sw) -{ - if (sw->buf) qemu_free (sw->buf); - if (sw->rate) st_rate_stop (sw->rate); - sw->buf = NULL; - sw->rate = NULL; -} - -int pcm_sw_alloc_resources (SWVoice *sw) -{ - sw->buf = qemu_mallocz (sw->hw->samples * sizeof (st_sample_t)); - if (!sw->buf) +static void audio_print_options (const char *prefix, + struct audio_option *opt) +{ + char *uprefix; + + if (!prefix) { + dolog ("No prefix specified\n"); + return; + } + + if (!opt) { + dolog ("No options\n"); + return; + } + + uprefix = audio_alloc_prefix (prefix); + + for (; opt->name; opt++) { + const char *state = "default"; + printf (" %s_%s: ", uprefix, opt->name); + + if (opt->overridenp && *opt->overridenp) { + state = "current"; + } + + switch (opt->tag) { + case AUD_OPT_BOOL: + { + int *intp = opt->valp; + printf ("boolean, %s = %d\n", state, *intp ? 1 : 0); + } + break; + + case AUD_OPT_INT: + { + int *intp = opt->valp; + printf ("integer, %s = %d\n", state, *intp); + } + break; + + case AUD_OPT_FMT: + { + audfmt_e *fmtp = opt->valp; + printf ( + "format, %s = %s, (one of: U8 S8 U16 S16)\n", + state, + audio_audfmt_to_string (*fmtp) + ); + } + break; + + case AUD_OPT_STR: + { + const char **strp = opt->valp; + printf ("string, %s = %s\n", + state, + *strp ? *strp : "(not set)"); + } + break; + + default: + printf ("???\n"); + dolog ("Bad value tag for option %s_%s %d\n", + uprefix, opt->name, opt->tag); + break; + } + printf (" %s\n", opt->descr); + } + + qemu_free (uprefix); +} + +static void audio_process_options (const char *prefix, + struct audio_option *opt) +{ + char *optname; + const char qemu_prefix[] = "QEMU_"; + size_t preflen; + + if (audio_bug (AUDIO_FUNC, !prefix)) { + dolog ("prefix = NULL\n"); + return; + } + + if (audio_bug (AUDIO_FUNC, !opt)) { + dolog ("opt = NULL\n"); + return; + } + + preflen = strlen (prefix); + + for (; opt->name; opt++) { + size_t len, i; + int def; + + if (!opt->valp) { + dolog ("Option value pointer for `%s' is not set\n", + opt->name); + continue; + } + + len = strlen (opt->name); + /* len of opt->name + len of prefix + size of qemu_prefix + * (includes trailing zero) + zero + underscore (on behalf of + * sizeof) */ + optname = qemu_malloc (len + preflen + sizeof (qemu_prefix) + 1); + if (!optname) { + dolog ("Could not allocate memory for option name `%s'\n", + opt->name); + continue; + } + + strcpy (optname, qemu_prefix); + + /* copy while upper-casing, including trailing zero */ + for (i = 0; i <= preflen; ++i) { + optname[i + sizeof (qemu_prefix) - 1] = toupper (prefix[i]); + } + strcat (optname, "_"); + strcat (optname, opt->name); + + def = 1; + switch (opt->tag) { + case AUD_OPT_BOOL: + case AUD_OPT_INT: + { + int *intp = opt->valp; + *intp = audio_get_conf_int (optname, *intp, &def); + } + break; + + case AUD_OPT_FMT: + { + audfmt_e *fmtp = opt->valp; + *fmtp = audio_get_conf_fmt (optname, *fmtp, &def); + } + break; + + case AUD_OPT_STR: + { + const char **strp = opt->valp; + *strp = audio_get_conf_str (optname, *strp, &def); + } + break; + + default: + dolog ("Bad value tag for option `%s' - %d\n", + optname, opt->tag); + break; + } + + if (!opt->overridenp) { + opt->overridenp = &opt->overriden; + } + *opt->overridenp = !def; + qemu_free (optname); + } +} + +static void audio_print_settings (audsettings_t *as) +{ + dolog ("frequency=%d nchannels=%d fmt=", as->freq, as->nchannels); + + switch (as->fmt) { + case AUD_FMT_S8: + AUD_log (NULL, "S8"); + break; + case AUD_FMT_U8: + AUD_log (NULL, "U8"); + break; + case AUD_FMT_S16: + AUD_log (NULL, "S16"); + break; + case AUD_FMT_U16: + AUD_log (NULL, "U16"); + break; + default: + AUD_log (NULL, "invalid(%d)", as->fmt); + break; + } + AUD_log (NULL, "\n"); +} + +static int audio_validate_settigs (audsettings_t *as) +{ + int invalid; + + invalid = as->nchannels != 1 && as->nchannels != 2; + + switch (as->fmt) { + case AUD_FMT_S8: + case AUD_FMT_U8: + case AUD_FMT_S16: + case AUD_FMT_U16: + break; + default: + invalid = 1; + break; + } + + invalid |= as->freq <= 0; + + if (invalid) { return -1; - - sw->rate = st_rate_start (sw->freq, sw->hw->freq); - if (!sw->rate) { - qemu_free (sw->buf); - sw->buf = NULL; - return -1; } return 0; } -void pcm_sw_fini (SWVoice *sw) -{ - pcm_sw_free_resources (sw); -} - -int pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq, - int nchannels, audfmt_e fmt) +static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as) { int bits = 8, sign = 0; - switch (fmt) { + switch (as->fmt) { case AUD_FMT_S8: sign = 1; case AUD_FMT_U8: @@ -147,626 +553,428 @@ int pcm_sw_init (SWVoice *sw, HWVoice *h bits = 16; break; } - - sw->hw = hw; - sw->freq = freq; - sw->fmt = fmt; - sw->nchannels = nchannels; - sw->shift = (nchannels == 2) + (bits == 16); - sw->align = (1 << sw->shift) - 1; - sw->left = 0; - sw->pos = 0; - sw->wpos = 0; - sw->live = 0; - sw->ratio = (sw->hw->freq * ((int64_t) INT_MAX)) / sw->freq; - sw->bytes_per_second = sw->freq << sw->shift; - sw->conv = mixeng_conv[nchannels == 2][sign][bits == 16]; - - pcm_sw_free_resources (sw); - return pcm_sw_alloc_resources (sw); -} - -/* Hard voice */ -void pcm_hw_free_resources (HWVoice *hw) -{ - if (hw->mix_buf) - qemu_free (hw->mix_buf); - hw->mix_buf = NULL; -} - -int pcm_hw_alloc_resources (HWVoice *hw) -{ - hw->mix_buf = qemu_mallocz (hw->samples * sizeof (st_sample_t)); - if (!hw->mix_buf) - return -1; - return 0; -} - -void pcm_hw_fini (HWVoice *hw) -{ - if (hw->active) { - ldebug ("pcm_hw_fini: %d %d %d\n", hw->freq, hw->nchannels, hw->fmt); - pcm_hw_free_resources (hw); - hw->pcm_ops->fini (hw); - memset (hw, 0, audio_state.drv->voice_size); - } -} - -void pcm_hw_gc (HWVoice *hw) -{ - if (hw->nb_voices) + return info->freq == as->freq + && info->nchannels == as->nchannels + && info->sign == sign + && info->bits == bits; +} + +void audio_pcm_init_info ( + struct audio_pcm_info *info, + audsettings_t *as, + int swap_endian + ) +{ + int bits = 8, sign = 0; + + switch (as->fmt) { + case AUD_FMT_S8: + sign = 1; + case AUD_FMT_U8: + break; + + case AUD_FMT_S16: + sign = 1; + case AUD_FMT_U16: + bits = 16; + break; + } + + info->freq = as->freq; + info->bits = bits; + info->sign = sign; + info->nchannels = as->nchannels; + info->shift = (as->nchannels == 2) + (bits == 16); + info->align = (1 << info->shift) - 1; + info->bytes_per_second = info->freq << info->shift; + info->swap_endian = swap_endian; +} + +void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len) +{ + if (!len) { return; - - pcm_hw_fini (hw); -} - -int pcm_hw_get_live (HWVoice *hw) -{ - int i, alive = 0, live = hw->samples; - - for (i = 0; i < hw->nb_voices; i++) { - if (hw->pvoice[i]->live) { - live = audio_MIN (hw->pvoice[i]->live, live); - alive += 1; - } - } - - if (alive) + } + + if (info->sign) { + memset (buf, len << info->shift, 0x00); + } + else { + if (info->bits == 8) { + memset (buf, len << info->shift, 0x80); + } + else { + int i; + uint16_t *p = buf; + int shift = info->nchannels - 1; + short s = INT16_MAX; + + if (info->swap_endian) { + s = bswap16 (s); + } + + for (i = 0; i < len << shift; i++) { + p[i] = s; + } + } + } +} + +/* + * Hard voice (capture) + */ +static int audio_pcm_hw_find_min_in (HWVoiceIn *hw) +{ + SWVoiceIn *sw; + int m = hw->total_samples_captured; + + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { + if (sw->active) { + m = audio_MIN (m, sw->total_hw_samples_acquired); + } + } + return m; +} + +int audio_pcm_hw_get_live_in (HWVoiceIn *hw) +{ + int live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw); + if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) { + dolog ("live=%d hw->samples=%d\n", live, hw->samples); + return 0; + } + return live; +} + +/* + * Soft voice (capture) + */ +static int audio_pcm_sw_get_rpos_in (SWVoiceIn *sw) +{ + HWVoiceIn *hw = sw->hw; + int live = hw->total_samples_captured - sw->total_hw_samples_acquired; + int rpos; + + if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) { + dolog ("live=%d hw->samples=%d\n", live, hw->samples); + return 0; + } + + rpos = hw->wpos - live; + if (rpos >= 0) { + return rpos; + } + else { + return hw->samples + rpos; + } +} + +int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int size) +{ + HWVoiceIn *hw = sw->hw; + int samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0; + st_sample_t *src, *dst = sw->buf; + + rpos = audio_pcm_sw_get_rpos_in (sw) % hw->samples; + + live = hw->total_samples_captured - sw->total_hw_samples_acquired; + if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) { + dolog ("live_in=%d hw->samples=%d\n", live, hw->samples); + return 0; + } + + samples = size >> sw->info.shift; + if (!live) { + return 0; + } + + swlim = (live * sw->ratio) >> 32; + swlim = audio_MIN (swlim, samples); + + while (swlim) { + src = hw->conv_buf + rpos; + isamp = hw->wpos - rpos; + /* XXX: <= ? */ + if (isamp <= 0) { + isamp = hw->samples - rpos; + } + + if (!isamp) { + break; + } + osamp = swlim; + + if (audio_bug (AUDIO_FUNC, osamp < 0)) { + dolog ("osamp=%d\n", osamp); + return 0; + } + + st_rate_flow (sw->rate, src, dst, &isamp, &osamp); + swlim -= osamp; + rpos = (rpos + isamp) % hw->samples; + dst += osamp; + ret += osamp; + total += isamp; + } + + sw->clip (buf, sw->buf, ret); + sw->total_hw_samples_acquired += total; + return ret << sw->info.shift; +} + +/* + * Hard voice (playback) + */ +static int audio_pcm_hw_find_min_out (HWVoiceOut *hw, int *nb_livep) +{ + SWVoiceOut *sw; + int m = INT_MAX; + int nb_live = 0; + + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { + if (sw->active || !sw->empty) { + m = audio_MIN (m, sw->total_hw_samples_mixed); + nb_live += 1; + } + } + + *nb_livep = nb_live; + return m; +} + +int audio_pcm_hw_get_live_out2 (HWVoiceOut *hw, int *nb_live) +{ + int smin; + + smin = audio_pcm_hw_find_min_out (hw, nb_live); + + if (!*nb_live) { + return 0; + } + else { + int live = smin; + + if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) { + dolog ("live=%d hw->samples=%d\n", live, hw->samples); + return 0; + } return live; - else - return -1; -} - -int pcm_hw_get_live2 (HWVoice *hw, int *nb_active) -{ - int i, alive = 0, live = hw->samples; - - *nb_active = 0; - for (i = 0; i < hw->nb_voices; i++) { - if (hw->pvoice[i]->live) { - if (hw->pvoice[i]->live < live) { - *nb_active = hw->pvoice[i]->active != 0; - live = hw->pvoice[i]->live; - } - alive += 1; - } - } - - if (alive) - return live; - else - return -1; -} - -void pcm_hw_dec_live (HWVoice *hw, int decr) -{ - int i; - - for (i = 0; i < hw->nb_voices; i++) { - if (hw->pvoice[i]->live) { - hw->pvoice[i]->live -= decr; - } - } -} - -void pcm_hw_clear (HWVoice *hw, void *buf, int len) -{ - if (!len) - return; - - switch (hw->fmt) { - case AUD_FMT_S16: - case AUD_FMT_S8: - memset (buf, 0x00, len << hw->shift); - break; - - case AUD_FMT_U8: - memset (buf, 0x80, len << hw->shift); - break; - - case AUD_FMT_U16: - { - unsigned int i; - uint16_t *p = buf; - int shift = hw->nchannels - 1; - - for (i = 0; i < len << shift; i++) { - p[i] = INT16_MAX; - } - } - break; - } -} - -int pcm_hw_write (SWVoice *sw, void *buf, int size) + } +} + +int audio_pcm_hw_get_live_out (HWVoiceOut *hw) +{ + int nb_live; + int live; + + live = audio_pcm_hw_get_live_out2 (hw, &nb_live); + if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) { + dolog ("live=%d hw->samples=%d\n", live, hw->samples); + return 0; + } + return live; +} + +/* + * Soft voice (playback) + */ +int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size) { int hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck; - int ret = 0, pos = 0; - if (!sw) + int ret = 0, pos = 0, total = 0; + + if (!sw) { return size; + } hwsamples = sw->hw->samples; - samples = size >> sw->shift; - - if (!sw->live) { - sw->wpos = sw->hw->rpos; - } - wpos = sw->wpos; - live = sw->live; + + live = sw->total_hw_samples_mixed; + if (audio_bug (AUDIO_FUNC, live < 0 || live > hwsamples)){ + dolog ("live=%d hw->samples=%d\n", live, hwsamples); + return 0; + } + + if (live == hwsamples) { + return 0; + } + + wpos = (sw->hw->rpos + live) % hwsamples; + samples = size >> sw->info.shift; + dead = hwsamples - live; - swlim = (dead * ((int64_t) INT_MAX)) / sw->ratio; + swlim = ((int64_t) dead << 32) / sw->ratio; swlim = audio_MIN (swlim, samples); - - ldebug ("size=%d live=%d dead=%d swlim=%d wpos=%d\n", - size, live, dead, swlim, wpos); - if (swlim) - sw->conv (sw->buf, buf, swlim); + if (swlim) { + sw->conv (sw->buf, buf, swlim, &sw->vol); + } while (swlim) { dead = hwsamples - live; left = hwsamples - wpos; blck = audio_MIN (dead, left); if (!blck) { - /* dolog ("swlim=%d\n", swlim); */ break; } isamp = swlim; osamp = blck; - st_rate_flow (sw->rate, sw->buf + pos, sw->hw->mix_buf + wpos, &isamp, &osamp); + st_rate_flow_mix ( + sw->rate, + sw->buf + pos, + sw->hw->mix_buf + wpos, + &isamp, + &osamp + ); ret += isamp; swlim -= isamp; pos += isamp; live += osamp; wpos = (wpos + osamp) % hwsamples; - } - - sw->wpos = wpos; - sw->live = live; - return ret << sw->shift; -} - -int pcm_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt) -{ - int sign = 0, bits = 8; - - pcm_hw_fini (hw); - ldebug ("pcm_hw_init: %d %d %d\n", freq, nchannels, fmt); - if (hw->pcm_ops->init (hw, freq, nchannels, fmt)) { - memset (hw, 0, audio_state.drv->voice_size); - return -1; - } - - switch (hw->fmt) { - case AUD_FMT_S8: - sign = 1; - case AUD_FMT_U8: - break; - - case AUD_FMT_S16: - sign = 1; - case AUD_FMT_U16: - bits = 16; - break; - } - - hw->nb_voices = 0; - hw->active = 1; - hw->shift = (hw->nchannels == 2) + (bits == 16); - hw->bytes_per_second = hw->freq << hw->shift; - hw->align = (1 << hw->shift) - 1; - hw->samples = hw->bufsize >> hw->shift; - hw->clip = mixeng_clip[hw->nchannels == 2][sign][bits == 16]; - if (pcm_hw_alloc_resources (hw)) { - pcm_hw_fini (hw); - return -1; - } - return 0; -} - -static int dist (void *hw) -{ - if (hw) { - return (((uint8_t *) hw - (uint8_t *) hw_voices) - / audio_state.voice_size) + 1; - } - else { - return 0; - } -} - -#define ADVANCE(hw) hw ? advance (hw, audio_state.voice_size) : hw_voices - -HWVoice *pcm_hw_find_any (HWVoice *hw) -{ - int i = dist (hw); - for (; i < audio_state.nb_hw_voices; i++) { - hw = ADVANCE (hw); - return hw; - } - return NULL; -} - -HWVoice *pcm_hw_find_any_active (HWVoice *hw) -{ - int i = dist (hw); - for (; i < audio_state.nb_hw_voices; i++) { - hw = ADVANCE (hw); - if (hw->active) - return hw; - } - return NULL; -} - -HWVoice *pcm_hw_find_any_active_enabled (HWVoice *hw) -{ - int i = dist (hw); - for (; i < audio_state.nb_hw_voices; i++) { - hw = ADVANCE (hw); - if (hw->active && hw->enabled) - return hw; - } - return NULL; -} - -HWVoice *pcm_hw_find_any_passive (HWVoice *hw) -{ - int i = dist (hw); - for (; i < audio_state.nb_hw_voices; i++) { - hw = ADVANCE (hw); - if (!hw->active) - return hw; - } - return NULL; -} - -HWVoice *pcm_hw_find_specific (HWVoice *hw, int freq, - int nchannels, audfmt_e fmt) -{ - while ((hw = pcm_hw_find_any_active (hw))) { - if (hw->freq == freq && - hw->nchannels == nchannels && - hw->fmt == fmt) - return hw; - } - return NULL; -} - -HWVoice *pcm_hw_add (int freq, int nchannels, audfmt_e fmt) -{ - HWVoice *hw; - - if (audio_state.fixed_format) { - freq = audio_state.fixed_freq; - nchannels = audio_state.fixed_channels; - fmt = audio_state.fixed_fmt; - } - - hw = pcm_hw_find_specific (NULL, freq, nchannels, fmt); - - if (hw) - return hw; - - hw = pcm_hw_find_any_passive (NULL); - if (hw) { - hw->pcm_ops = audio_state.drv->pcm_ops; - if (!hw->pcm_ops) - return NULL; - - if (pcm_hw_init (hw, freq, nchannels, fmt)) { - pcm_hw_gc (hw); - return NULL; - } - else - return hw; - } - - return pcm_hw_find_any (NULL); -} - -int pcm_hw_add_sw (HWVoice *hw, SWVoice *sw) -{ - SWVoice **pvoice = qemu_mallocz ((hw->nb_voices + 1) * sizeof (sw)); - if (!pvoice) - return -1; - - memcpy (pvoice, hw->pvoice, hw->nb_voices * sizeof (sw)); - qemu_free (hw->pvoice); - hw->pvoice = pvoice; - hw->pvoice[hw->nb_voices++] = sw; - return 0; -} - -int pcm_hw_del_sw (HWVoice *hw, SWVoice *sw) -{ - int i, j; - if (hw->nb_voices > 1) { - SWVoice **pvoice = qemu_mallocz ((hw->nb_voices - 1) * sizeof (sw)); - - if (!pvoice) { - dolog ("Can not maintain consistent state (not enough memory)\n"); - return -1; - } - - for (i = 0, j = 0; i < hw->nb_voices; i++) { - if (j >= hw->nb_voices - 1) { - dolog ("Can not maintain consistent state " - "(invariant violated)\n"); - return -1; - } - if (hw->pvoice[i] != sw) - pvoice[j++] = hw->pvoice[i]; - } - qemu_free (hw->pvoice); - hw->pvoice = pvoice; - hw->nb_voices -= 1; - } - else { - qemu_free (hw->pvoice); - hw->pvoice = NULL; - hw->nb_voices = 0; - } - return 0; -} - -SWVoice *pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt) -{ - SWVoice *sw; - HWVoice *hw; - - sw = qemu_mallocz (sizeof (*sw)); - if (!sw) - goto err1; - - hw = pcm_hw_add (freq, nchannels, fmt); - if (!hw) - goto err2; - - if (pcm_hw_add_sw (hw, sw)) - goto err3; - - if (pcm_sw_init (sw, hw, freq, nchannels, fmt)) - goto err4; - - return sw; - -err4: - pcm_hw_del_sw (hw, sw); -err3: - pcm_hw_gc (hw); -err2: - qemu_free (sw); -err1: - return NULL; -} - -SWVoice *AUD_open (SWVoice *sw, const char *name, - int freq, int nchannels, audfmt_e fmt) -{ - if (!audio_state.drv) { - return NULL; - } - - if (sw && freq == sw->freq && sw->nchannels == nchannels && sw->fmt == fmt) { - return sw; - } - - if (sw) { - ldebug ("Different format %s %d %d %d\n", - name, - sw->freq == freq, - sw->nchannels == nchannels, - sw->fmt == fmt); - } - - if (nchannels != 1 && nchannels != 2) { - dolog ("Bogus channel count %d for voice %s\n", nchannels, name); - return NULL; - } - - if (!audio_state.fixed_format && sw) { - pcm_sw_fini (sw); - pcm_hw_del_sw (sw->hw, sw); - pcm_hw_gc (sw->hw); - if (sw->name) { - qemu_free (sw->name); - sw->name = NULL; - } - qemu_free (sw); - sw = NULL; - } - - if (sw) { - HWVoice *hw = sw->hw; - if (!hw) { - dolog ("Internal logic error voice %s has no hardware store\n", - name); - return sw; - } - - if (pcm_sw_init (sw, hw, freq, nchannels, fmt)) { - pcm_sw_fini (sw); - pcm_hw_del_sw (hw, sw); - pcm_hw_gc (hw); - if (sw->name) { - qemu_free (sw->name); - sw->name = NULL; - } - qemu_free (sw); - return NULL; - } - } - else { - sw = pcm_create_voice_pair (freq, nchannels, fmt); - if (!sw) { - dolog ("Failed to create voice %s\n", name); - return NULL; - } - } - - if (sw->name) { - qemu_free (sw->name); - sw->name = NULL; - } - sw->name = qemu_strdup (name); - return sw; -} - -void AUD_close (SWVoice *sw) -{ - if (!sw) - return; - - pcm_sw_fini (sw); - pcm_hw_del_sw (sw->hw, sw); - pcm_hw_gc (sw->hw); - if (sw->name) { - qemu_free (sw->name); - sw->name = NULL; - } - qemu_free (sw); -} - -int AUD_write (SWVoice *sw, void *buf, int size) + total += osamp; + } + + sw->total_hw_samples_mixed += total; + sw->empty = sw->total_hw_samples_mixed == 0; + +#ifdef DEBUG_OUT + dolog ( + "%s: write size %d ret %d total sw %d\n", + SW_NAME (sw), + size >> sw->info.shift, + ret, + sw->total_hw_samples_mixed + ); +#endif + + return ret << sw->info.shift; +} + +#ifdef DEBUG_AUDIO +static void audio_pcm_print_info (const char *cap, struct audio_pcm_info *info) +{ + dolog ("%s: bits %d, sign %d, freq %d, nchan %d\n", + cap, info->bits, info->sign, info->freq, info->nchannels); +} +#endif + +#define DAC +#include "audio_template.h" +#undef DAC +#include "audio_template.h" + +int AUD_write (SWVoiceOut *sw, void *buf, int size) { int bytes; - if (!sw->hw->enabled) - dolog ("Writing to disabled voice %s\n", sw->name); + if (!sw) { + /* XXX: Consider options */ + return size; + } + + if (!sw->hw->enabled) { + dolog ("Writing to disabled voice %s\n", SW_NAME (sw)); + return 0; + } + bytes = sw->hw->pcm_ops->write (sw, buf, size); return bytes; } -void AUD_run (void) -{ - HWVoice *hw = NULL; - - while ((hw = pcm_hw_find_any_active_enabled (hw))) { - int i; - if (hw->pending_disable && pcm_hw_get_live (hw) <= 0) { - hw->enabled = 0; - hw->pcm_ops->ctl (hw, VOICE_DISABLE); - for (i = 0; i < hw->nb_voices; i++) { - hw->pvoice[i]->live = 0; - /* hw->pvoice[i]->old_ticks = 0; */ - } - continue; - } - - hw->pcm_ops->run (hw); - assert (hw->rpos < hw->samples); - for (i = 0; i < hw->nb_voices; i++) { - SWVoice *sw = hw->pvoice[i]; - if (!sw->active && !sw->live && sw->old_ticks) { - int64_t delta = qemu_get_clock (vm_clock) - sw->old_ticks; - if (delta > audio_state.ticks_threshold) { - ldebug ("resetting old_ticks for %s\n", sw->name); - sw->old_ticks = 0; - } - } - } - } -} - -int AUD_get_free (SWVoice *sw) -{ - int free; - - if (!sw) - return 4096; - - free = ((sw->hw->samples - sw->live) << sw->hw->shift) * sw->ratio - / INT_MAX; - - free &= ~sw->hw->align; - if (!free) return 0; - - return free; -} - -int AUD_get_buffer_size (SWVoice *sw) -{ - return sw->hw->bufsize; -} - -void AUD_adjust (SWVoice *sw, int bytes) -{ - if (!sw) +int AUD_read (SWVoiceIn *sw, void *buf, int size) +{ + int bytes; + + if (!sw) { + /* XXX: Consider options */ + return size; + } + + if (!sw->hw->enabled) { + dolog ("Reading from disabled voice %s\n", SW_NAME (sw)); + return 0; + } + + bytes = sw->hw->pcm_ops->read (sw, buf, size); + return bytes; +} + +int AUD_get_buffer_size_out (SWVoiceOut *sw) +{ + return sw->hw->samples << sw->hw->info.shift; +} + +void AUD_set_active_out (SWVoiceOut *sw, int on) +{ + HWVoiceOut *hw; + + if (!sw) { return; - sw->old_ticks += (ticks_per_sec * (int64_t) bytes) / sw->bytes_per_second; -} - -void AUD_reset (SWVoice *sw) -{ - sw->active = 0; - sw->old_ticks = 0; -} - -int AUD_calc_elapsed (SWVoice *sw) -{ - int64_t now, delta, bytes; - int dead, swlim; - - if (!sw) - return 0; - - now = qemu_get_clock (vm_clock); - delta = now - sw->old_ticks; - bytes = (delta * sw->bytes_per_second) / ticks_per_sec; - if (delta < 0) { - dolog ("whoops delta(<0)=%"PRId64"\n", delta); - return 0; - } - - dead = sw->hw->samples - sw->live; - swlim = ((dead * (int64_t) INT_MAX) / sw->ratio); - - if (bytes > swlim) { - return swlim; - } - else { - return bytes; - } -} - -void AUD_enable (SWVoice *sw, int on) -{ - int i; - HWVoice *hw; - - if (!sw) - return; + } hw = sw->hw; - if (on) { - if (!sw->live) - sw->wpos = sw->hw->rpos; - if (!sw->old_ticks) { - sw->old_ticks = qemu_get_clock (vm_clock); - } - } - if (sw->active != on) { + SWVoiceOut *temp_sw; + if (on) { + int total; + hw->pending_disable = 0; if (!hw->enabled) { hw->enabled = 1; - for (i = 0; i < hw->nb_voices; i++) { - ldebug ("resetting voice\n"); - sw = hw->pvoice[i]; - sw->old_ticks = qemu_get_clock (vm_clock); + hw->pcm_ops->ctl_out (hw, VOICE_ENABLE); + } + + if (sw->empty) { + total = 0; + } + } + else { + if (hw->enabled) { + int nb_active = 0; + + for (temp_sw = hw->sw_head.lh_first; temp_sw; + temp_sw = temp_sw->entries.le_next) { + nb_active += temp_sw->active != 0; } - hw->pcm_ops->ctl (hw, VOICE_ENABLE); - } + + hw->pending_disable = nb_active == 1; + } + } + sw->active = on; + } +} + +void AUD_set_active_in (SWVoiceIn *sw, int on) +{ + HWVoiceIn *hw; + + if (!sw) { + return; + } + + hw = sw->hw; + if (sw->active != on) { + SWVoiceIn *temp_sw; + + if (on) { + if (!hw->enabled) { + hw->enabled = 1; + hw->pcm_ops->ctl_in (hw, VOICE_ENABLE); + } + sw->total_hw_samples_acquired = hw->total_samples_captured; } else { - if (hw->enabled && !hw->pending_disable) { + if (hw->enabled) { int nb_active = 0; - for (i = 0; i < hw->nb_voices; i++) { - nb_active += hw->pvoice[i]->active != 0; + + for (temp_sw = hw->sw_head.lh_first; temp_sw; + temp_sw = temp_sw->entries.le_next) { + nb_active += temp_sw->active != 0; } if (nb_active == 1) { - hw->pending_disable = 1; + hw->enabled = 0; + hw->pcm_ops->ctl_in (hw, VOICE_DISABLE); } } } @@ -774,137 +982,500 @@ void AUD_enable (SWVoice *sw, int on) } } -static struct audio_output_driver *drvtab[] = { -#ifdef CONFIG_OSS - &oss_output_driver, -#endif -#ifdef CONFIG_FMOD - &fmod_output_driver, -#endif -#ifdef CONFIG_SDL - &sdl_output_driver, -#endif - &no_output_driver, -#ifdef USE_WAV_AUDIO - &wav_output_driver, -#endif +static int audio_get_avail (SWVoiceIn *sw) +{ + int live; + + if (!sw) { + return 0; + } + + live = sw->hw->total_samples_captured - sw->total_hw_samples_acquired; + if (audio_bug (AUDIO_FUNC, live < 0 || live > sw->hw->samples)) { + dolog ("live=%d sw->hw->samples=%d\n", live, sw->hw->samples); + return 0; + } + + ldebug ( + "%s: get_avail live %d ret %lld\n", + SW_NAME (sw), + live, (((int64_t) live << 32) / sw->ratio) << sw->info.shift + ); + + return (((int64_t) live << 32) / sw->ratio) << sw->info.shift; +} + +static int audio_get_free (SWVoiceOut *sw) +{ + int live, dead; + + if (!sw) { + return 0; + } + + live = sw->total_hw_samples_mixed; + + if (audio_bug (AUDIO_FUNC, live < 0 || live > sw->hw->samples)) { + dolog ("live=%d sw->hw->samples=%d\n", live, sw->hw->samples); + return 0; + } + + dead = sw->hw->samples - live; + +#ifdef DEBUG_OUT + dolog ("%s: get_free live %d dead %d ret %lld\n", + SW_NAME (sw), + live, dead, (((int64_t) dead << 32) / sw->ratio) << sw->info.shift); +#endif + + return (((int64_t) dead << 32) / sw->ratio) << sw->info.shift; +} + +static void audio_run_out (AudioState *s) +{ + HWVoiceOut *hw = NULL; + SWVoiceOut *sw; + + while ((hw = audio_pcm_hw_find_any_enabled_out (s, hw))) { + int played; + int live, free, nb_live, cleanup_required; + + live = audio_pcm_hw_get_live_out2 (hw, &nb_live); + if (!nb_live) { + live = 0; + } + + if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) { + dolog ("live=%d hw->samples=%d\n", live, hw->samples); + continue; + } + + if (hw->pending_disable && !nb_live) { +#ifdef DEBUG_OUT + dolog ("Disabling voice\n"); +#endif + hw->enabled = 0; + hw->pending_disable = 0; + hw->pcm_ops->ctl_out (hw, VOICE_DISABLE); + continue; + } + + if (!live) { + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { + if (sw->active) { + free = audio_get_free (sw); + if (free > 0) { + sw->callback.fn (sw->callback.opaque, free); + } + } + } + continue; + } + + played = hw->pcm_ops->run_out (hw); + if (audio_bug (AUDIO_FUNC, hw->rpos >= hw->samples)) { + dolog ("hw->rpos=%d hw->samples=%d played=%d\n", + hw->rpos, hw->samples, played); + hw->rpos = 0; + } + +#ifdef DEBUG_OUT + dolog ("played=%d\n", played); +#endif + + if (played) { + hw->ts_helper += played; + } + + cleanup_required = 0; + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { + if (!sw->active && sw->empty) { + continue; + } + + if (audio_bug (AUDIO_FUNC, played > sw->total_hw_samples_mixed)) { + dolog ("played=%d sw->total_hw_samples_mixed=%d\n", + played, sw->total_hw_samples_mixed); + played = sw->total_hw_samples_mixed; + } + + sw->total_hw_samples_mixed -= played; + + if (!sw->total_hw_samples_mixed) { + sw->empty = 1; + cleanup_required |= !sw->active && !sw->callback.fn; + } + + if (sw->active) { + free = audio_get_free (sw); + if (free > 0) { + sw->callback.fn (sw->callback.opaque, free); + } + } + } + + if (cleanup_required) { + restart: + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { + if (!sw->active && !sw->callback.fn) { +#ifdef DEBUG_PLIVE + dolog ("Finishing with old voice\n"); +#endif + audio_close_out (s, sw); + goto restart; /* play it safe */ + } + } + } + } +} + +static void audio_run_in (AudioState *s) +{ + HWVoiceIn *hw = NULL; + + while ((hw = audio_pcm_hw_find_any_enabled_in (s, hw))) { + SWVoiceIn *sw; + int captured, min; + + captured = hw->pcm_ops->run_in (hw); + + min = audio_pcm_hw_find_min_in (hw); + hw->total_samples_captured += captured - min; + hw->ts_helper += captured; + + for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { + sw->total_hw_samples_acquired -= min; + + if (sw->active) { + int avail; + + avail = audio_get_avail (sw); + if (avail > 0) { + sw->callback.fn (sw->callback.opaque, avail); + } + } + } + } +} + +static void audio_timer (void *opaque) +{ + AudioState *s = opaque; + + audio_run_out (s); + audio_run_in (s); + + qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks); +} + +static struct audio_option audio_options[] = { + /* DAC */ + {"DAC_FIXED_SETTINGS", AUD_OPT_BOOL, &conf.fixed_out.enabled, + "Use fixed settings for host DAC", NULL, 0}, + + {"DAC_FIXED_FREQ", AUD_OPT_INT, &conf.fixed_out.settings.freq, + "Frequency for fixed host DAC", NULL, 0}, + + {"DAC_FIXED_FMT", AUD_OPT_FMT, &conf.fixed_out.settings.fmt, + "Format for fixed host DAC", NULL, 0}, + + {"DAC_FIXED_CHANNELS", AUD_OPT_INT, &conf.fixed_out.settings.nchannels, + "Number of channels for fixed DAC (1 - mono, 2 - stereo)", NULL, 0}, + + {"DAC_VOICES", AUD_OPT_INT, &conf.fixed_out.nb_voices, + "Number of voices for DAC", NULL, 0}, + + /* ADC */ + {"ADC_FIXED_SETTINGS", AUD_OPT_BOOL, &conf.fixed_in.enabled, + "Use fixed settings for host ADC", NULL, 0}, + + {"ADC_FIXED_FREQ", AUD_OPT_INT, &conf.fixed_in.settings.freq, + "Frequency for fixed host ADC", NULL, 0}, + + {"ADC_FIXED_FMT", AUD_OPT_FMT, &conf.fixed_in.settings.fmt, + "Format for fixed host ADC", NULL, 0}, + + {"ADC_FIXED_CHANNELS", AUD_OPT_INT, &conf.fixed_in.settings.nchannels, + "Number of channels for fixed ADC (1 - mono, 2 - stereo)", NULL, 0}, + + {"ADC_VOICES", AUD_OPT_INT, &conf.fixed_in.nb_voices, + "Number of voices for ADC", NULL, 0}, + + /* Misc */ + {"TIMER_PERIOD", AUD_OPT_INT, &conf.period.hz, + "Timer period in HZ (0 - use lowest possible)", NULL, 0}, + + {"PLIVE", AUD_OPT_BOOL, &conf.plive, + "(undocumented)", NULL, 0}, + + {"LOG_TO_MONITOR", AUD_OPT_BOOL, &conf.log_to_monitor, + "print logging messages to montior instead of stderr", NULL, 0}, + + {NULL, 0, NULL, NULL, NULL, 0} }; -static int voice_init (struct audio_output_driver *drv) -{ - audio_state.opaque = drv->init (); - if (audio_state.opaque) { - if (audio_state.nb_hw_voices > drv->max_voices) { - dolog ("`%s' does not support %d multiple hardware channels\n" - "Resetting to %d\n", - drv->name, audio_state.nb_hw_voices, drv->max_voices); - audio_state.nb_hw_voices = drv->max_voices; - } - hw_voices = qemu_mallocz (audio_state.nb_hw_voices * drv->voice_size); - if (hw_voices) { - audio_state.drv = drv; - return 1; +static void audio_pp_nb_voices (const char *typ, int nb) +{ + switch (nb) { + case 0: + printf ("Does not support %s\n", typ); + break; + case 1: + printf ("One %s voice\n", typ); + break; + case INT_MAX: + printf ("Theoretically supports many %s voices\n", typ); + break; + default: + printf ("Theoretically supports upto %d %s voices\n", nb, typ); + break; + } + +} + +void AUD_help (void) +{ + size_t i; + + audio_process_options ("AUDIO", audio_options); + for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) { + struct audio_driver *d = drvtab[i]; + if (d->options) { + audio_process_options (d->name, d->options); + } + } + + printf ("Audio options:\n"); + audio_print_options ("AUDIO", audio_options); + printf ("\n"); + + printf ("Available drivers:\n"); + + for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) { + struct audio_driver *d = drvtab[i]; + + printf ("Name: %s\n", d->name); + printf ("Description: %s\n", d->descr); + + audio_pp_nb_voices ("playback", d->max_voices_out); + audio_pp_nb_voices ("capture", d->max_voices_in); + + if (d->options) { + printf ("Options:\n"); + audio_print_options (d->name, d->options); } else { - dolog ("Not enough memory for %d `%s' voices (each %d bytes)\n", - audio_state.nb_hw_voices, drv->name, drv->voice_size); - drv->fini (audio_state.opaque); - return 0; - } + printf ("No options\n"); + } + printf ("\n"); + } + + printf ( + "Options are settable through environment variables.\n" + "Example:\n" +#ifdef _WIN32 + " set QEMU_AUDIO_DRV=wav\n" + " set QEMU_WAV_PATH=c:\\tune.wav\n" +#else + " export QEMU_AUDIO_DRV=wav\n" + " export QEMU_WAV_PATH=$HOME/tune.wav\n" + "(for csh replace export with setenv in the above)\n" +#endif + " qemu ...\n\n" + ); +} + +static int audio_driver_init (AudioState *s, struct audio_driver *drv) +{ + if (drv->options) { + audio_process_options (drv->name, drv->options); + } + s->drv_opaque = drv->init (); + + if (s->drv_opaque) { + audio_init_nb_voices_out (s, drv); + audio_init_nb_voices_in (s, drv); + s->drv = drv; + return 0; } else { - dolog ("Could not init `%s' audio\n", drv->name); - return 0; - } -} - -static void audio_vm_stop_handler (void *opaque, int reason) -{ - HWVoice *hw = NULL; - - while ((hw = pcm_hw_find_any (hw))) { - if (!hw->pcm_ops) - continue; - - hw->pcm_ops->ctl (hw, reason ? VOICE_ENABLE : VOICE_DISABLE); + dolog ("Could not init `%s' audio driver\n", drv->name); + return -1; + } +} + +static void audio_vm_change_state_handler (void *opaque, int running) +{ + AudioState *s = opaque; + HWVoiceOut *hwo = NULL; + HWVoiceIn *hwi = NULL; + int op = running ? VOICE_ENABLE : VOICE_DISABLE; + + while ((hwo = audio_pcm_hw_find_any_enabled_out (s, hwo))) { + hwo->pcm_ops->ctl_out (hwo, op); + } + + while ((hwi = audio_pcm_hw_find_any_enabled_in (s, hwi))) { + hwi->pcm_ops->ctl_in (hwi, op); } } static void audio_atexit (void) { - HWVoice *hw = NULL; - - while ((hw = pcm_hw_find_any (hw))) { - if (!hw->pcm_ops) - continue; - - hw->pcm_ops->ctl (hw, VOICE_DISABLE); - hw->pcm_ops->fini (hw); - } - audio_state.drv->fini (audio_state.opaque); + AudioState *s = &glob_audio_state; + HWVoiceOut *hwo = NULL; + HWVoiceIn *hwi = NULL; + + while ((hwo = audio_pcm_hw_find_any_enabled_out (s, hwo))) { + hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE); + hwo->pcm_ops->fini_out (hwo); + } + + while ((hwi = audio_pcm_hw_find_any_enabled_in (s, hwi))) { + hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE); + hwi->pcm_ops->fini_in (hwi); + } + + if (s->drv) { + s->drv->fini (s->drv_opaque); + } } static void audio_save (QEMUFile *f, void *opaque) { + (void) f; + (void) opaque; } static int audio_load (QEMUFile *f, void *opaque, int version_id) { - if (version_id != 1) + (void) f; + (void) opaque; + + if (version_id != 1) { return -EINVAL; + } return 0; } -void AUD_init (void) -{ - int i; +void AUD_register_card (AudioState *s, const char *name, QEMUSoundCard *card) +{ + card->audio = s; + card->name = qemu_strdup (name); + memset (&card->entries, 0, sizeof (card->entries)); + LIST_INSERT_HEAD (&s->card_head, card, entries); +} + +void AUD_remove_card (QEMUSoundCard *card) +{ + LIST_REMOVE (card, entries); + card->audio = NULL; + qemu_free (card->name); +} + +AudioState *AUD_init (void) +{ + size_t i; int done = 0; const char *drvname; - - audio_state.fixed_format = - !!audio_get_conf_int (QC_FIXED_FORMAT, audio_state.fixed_format); - audio_state.fixed_freq = - audio_get_conf_int (QC_FIXED_FREQ, audio_state.fixed_freq); - audio_state.nb_hw_voices = - audio_get_conf_int (QC_VOICES, audio_state.nb_hw_voices); - - if (audio_state.nb_hw_voices <= 0) { - dolog ("Bogus number of voices %d, resetting to 1\n", - audio_state.nb_hw_voices); - } - - drvname = audio_get_conf_str (QC_AUDIO_DRV, NULL); + AudioState *s = &glob_audio_state; + + LIST_INIT (&s->hw_head_out); + LIST_INIT (&s->hw_head_in); + atexit (audio_atexit); + + s->ts = qemu_new_timer (vm_clock, audio_timer, s); + if (!s->ts) { + dolog ("Could not create audio timer\n"); + return NULL; + } + + audio_process_options ("AUDIO", audio_options); + + s->nb_hw_voices_out = conf.fixed_out.nb_voices; + s->nb_hw_voices_in = conf.fixed_in.nb_voices; + + if (s->nb_hw_voices_out <= 0) { + dolog ("Bogus number of playback voices %d, setting to 1\n", + s->nb_hw_voices_out); + s->nb_hw_voices_out = 1; + } + + if (s->nb_hw_voices_in <= 0) { + dolog ("Bogus number of capture voices %d, setting to 0\n", + s->nb_hw_voices_in); + s->nb_hw_voices_in = 0; + } + + { + int def; + drvname = audio_get_conf_str ("QEMU_AUDIO_DRV", NULL, &def); + } + if (drvname) { int found = 0; + for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) { if (!strcmp (drvname, drvtab[i]->name)) { - done = voice_init (drvtab[i]); + done = !audio_driver_init (s, drvtab[i]); found = 1; break; } } + if (!found) { dolog ("Unknown audio driver `%s'\n", drvname); - } - } - - qemu_add_vm_stop_handler (audio_vm_stop_handler, NULL); - atexit (audio_atexit); + dolog ("Run with -audio-help to list available drivers\n"); + } + } if (!done) { for (i = 0; !done && i < sizeof (drvtab) / sizeof (drvtab[0]); i++) { - if (drvtab[i]->can_be_default) - done = voice_init (drvtab[i]); - } - } - - audio_state.ticks_threshold = ticks_per_sec / 50; - audio_state.freq_threshold = 100; - - register_savevm ("audio", 0, 1, audio_save, audio_load, NULL); + if (drvtab[i]->can_be_default) { + done = !audio_driver_init (s, drvtab[i]); + } + } + } + if (!done) { - dolog ("Can not initialize audio subsystem\n"); - voice_init (&no_output_driver); - } -} + done = !audio_driver_init (s, &no_audio_driver); + if (!done) { + dolog ("Could not initialize audio subsystem\n"); + } + else { + dolog ("warning: Using timer based audio emulation\n"); + } + } + + if (done) { + VMChangeStateEntry *e; + + if (conf.period.hz <= 0) { + if (conf.period.hz < 0) { + dolog ("warning: Timer period is negative - %d " + "treating as zero\n", + conf.period.hz); + } + conf.period.ticks = 1; + } + else { + conf.period.ticks = ticks_per_sec / conf.period.hz; + } + + e = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s); + if (!e) { + dolog ("warning: Could not register change state handler\n" + "(Audio can continue looping even after stopping the VM)\n"); + } + } + else { + qemu_del_timer (s->ts); + return NULL; + } + + LIST_INIT (&s->card_head); + register_savevm ("audio", 0, 1, audio_save, audio_load, s); + qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks); + return s; +} diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/audio/audio.h --- a/tools/ioemu/audio/audio.h Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/audio/audio.h Tue Jul 25 12:19:05 2006 -0600 @@ -1,8 +1,8 @@ /* * QEMU Audio subsystem header - * - * Copyright (c) 2003-2004 Vassili Karpov (malc) - * + * + * Copyright (c) 2003-2005 Vassili Karpov (malc) + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -24,31 +24,85 @@ #ifndef QEMU_AUDIO_H #define QEMU_AUDIO_H -#include "mixeng.h" +#include "sys-queue.h" + +typedef void (*audio_callback_fn_t) (void *opaque, int avail); typedef enum { - AUD_FMT_U8, - AUD_FMT_S8, - AUD_FMT_U16, - AUD_FMT_S16 + AUD_FMT_U8, + AUD_FMT_S8, + AUD_FMT_U16, + AUD_FMT_S16 } audfmt_e; -typedef struct SWVoice SWVoice; +typedef struct { + int freq; + int nchannels; + audfmt_e fmt; +} audsettings_t; -SWVoice * AUD_open (SWVoice *sw, const char *name, int freq, - int nchannels, audfmt_e fmt); -void AUD_init (void); -void AUD_log (const char *cap, const char *fmt, ...) - __attribute__ ((__format__ (__printf__, 2, 3)));; -void AUD_close (SWVoice *sw); -int AUD_write (SWVoice *sw, void *pcm_buf, int size); -void AUD_adjust (SWVoice *sw, int leftover); -void AUD_reset (SWVoice *sw); -int AUD_get_free (SWVoice *sw); -int AUD_get_buffer_size (SWVoice *sw); -void AUD_run (void); -void AUD_enable (SWVoice *sw, int on); -int AUD_calc_elapsed (SWVoice *sw); +typedef struct AudioState AudioState; +typedef struct SWVoiceOut SWVoiceOut; +typedef struct SWVoiceIn SWVoiceIn; + +typedef struct QEMUSoundCard { + AudioState *audio; + char *name; + LIST_ENTRY (QEMUSoundCard) entries; +} QEMUSoundCard; + +typedef struct QEMUAudioTimeStamp { + uint64_t old_ts; +} QEMUAudioTimeStamp; + +void AUD_vlog (const char *cap, const char *fmt, va_list ap); +void AUD_log (const char *cap, const char *fmt, ...) +#ifdef __GNUC__ + __attribute__ ((__format__ (__printf__, 2, 3))) +#endif + ; + +AudioState *AUD_init (void); +void AUD_help (void); +void AUD_register_card (AudioState *s, const char *name, QEMUSoundCard *card); +void AUD_remove_card (QEMUSoundCard *card); + +SWVoiceOut *AUD_open_out ( + QEMUSoundCard *card, + SWVoiceOut *sw, + const char *name, + void *callback_opaque, + audio_callback_fn_t callback_fn, + audsettings_t *settings, + int sw_endian + ); + +void AUD_close_out (QEMUSoundCard *card, SWVoiceOut *sw); +int AUD_write (SWVoiceOut *sw, void *pcm_buf, int size); +int AUD_get_buffer_size_out (SWVoiceOut *sw); +void AUD_set_active_out (SWVoiceOut *sw, int on); +int AUD_is_active_out (SWVoiceOut *sw); + +void AUD_init_time_stamp_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts); +uint64_t AUD_get_elapsed_usec_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts); + +SWVoiceIn *AUD_open_in ( + QEMUSoundCard *card, + SWVoiceIn *sw, + const char *name, + void *callback_opaque, + audio_callback_fn_t callback_fn, + audsettings_t *settings, + int sw_endian + ); + +void AUD_close_in (QEMUSoundCard *card, SWVoiceIn *sw); +int AUD_read (SWVoiceIn *sw, void *pcm_buf, int size); +void AUD_set_active_in (SWVoiceIn *sw, int on); +int AUD_is_active_in (SWVoiceIn *sw); + +void AUD_init_time_stamp_in (SWVoiceIn *sw, QEMUAudioTimeStamp *ts); +uint64_t AUD_get_elapsed_usec_in (SWVoiceIn *sw, QEMUAudioTimeStamp *ts); static inline void *advance (void *p, int incr) { @@ -59,7 +113,21 @@ uint32_t popcount (uint32_t u); uint32_t popcount (uint32_t u); inline uint32_t lsbindex (uint32_t u); +#ifdef __GNUC__ +#define audio_MIN(a, b) ( __extension__ ({ \ + __typeof (a) ta = a; \ + __typeof (b) tb = b; \ + ((ta)>(tb)?(tb):(ta)); \ +})) + +#define audio_MAX(a, b) ( __extension__ ({ \ + __typeof (a) ta = a; \ + __typeof (b) tb = b; \ + ((ta)<(tb)?(tb):(ta)); \ +})) +#else #define audio_MIN(a, b) ((a)>(b)?(b):(a)) #define audio_MAX(a, b) ((a)<(b)?(b):(a)) +#endif #endif /* audio.h */ diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/audio/audio_int.h --- a/tools/ioemu/audio/audio_int.h Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/audio/audio_int.h Tue Jul 25 12:19:05 2006 -0600 @@ -1,8 +1,8 @@ /* * QEMU Audio subsystem header - * - * Copyright (c) 2003-2004 Vassili Karpov (malc) - * + * + * Copyright (c) 2003-2005 Vassili Karpov (malc) + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -24,141 +24,245 @@ #ifndef QEMU_AUDIO_INT_H #define QEMU_AUDIO_INT_H -#include "vl.h" - -struct pcm_ops; - -typedef struct HWVoice { - int active; +#ifdef CONFIG_COREAUDIO +#define FLOAT_MIXENG +/* #define RECIPROCAL */ +#endif +#include "mixeng.h" + +struct audio_pcm_ops; + +typedef enum { + AUD_OPT_INT, + AUD_OPT_FMT, + AUD_OPT_STR, + AUD_OPT_BOOL +} audio_option_tag_e; + +struct audio_option { + const char *name; + audio_option_tag_e tag; + void *valp; + const char *descr; + int *overridenp; + int overriden; +}; + +struct audio_callback { + void *opaque; + audio_callback_fn_t fn; +}; + +struct audio_pcm_info { + int bits; + int sign; + int freq; + int nchannels; + int align; + int shift; + int bytes_per_second; + int swap_endian; +}; + +typedef struct HWVoiceOut { int enabled; int pending_disable; int valid; - int freq; + struct audio_pcm_info info; f_sample *clip; - audfmt_e fmt; - int nchannels; - - int align; - int shift; int rpos; - int bufsize; - - int bytes_per_second; + uint64_t ts_helper; + st_sample_t *mix_buf; int samples; - int64_t old_ticks; - int nb_voices; - struct SWVoice **pvoice; - struct pcm_ops *pcm_ops; -} HWVoice; - -extern struct pcm_ops no_pcm_ops; -extern struct audio_output_driver no_output_driver; - -extern struct pcm_ops oss_pcm_ops; -extern struct audio_output_driver oss_output_driver; - -extern struct pcm_ops sdl_pcm_ops; -extern struct audio_output_driver sdl_output_driver; - -extern struct pcm_ops wav_pcm_ops; -extern struct audio_output_driver wav_output_driver; - -extern struct pcm_ops fmod_pcm_ops; -extern struct audio_output_driver fmod_output_driver; - -struct audio_output_driver { - const char *name; - void *(*init) (void); - void (*fini) (void *); - struct pcm_ops *pcm_ops; - int can_be_default; - int max_voices; - int voice_size; -}; - -typedef struct AudioState { - int fixed_format; - int fixed_freq; - int fixed_channels; - int fixed_fmt; - int nb_hw_voices; - int voice_size; - int64_t ticks_threshold; - int freq_threshold; - void *opaque; - struct audio_output_driver *drv; -} AudioState; -extern AudioState audio_state; - -struct SWVoice { - int freq; - audfmt_e fmt; - int nchannels; - - int shift; - int align; + LIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head; + struct audio_pcm_ops *pcm_ops; + LIST_ENTRY (HWVoiceOut) entries; +} HWVoiceOut; + +typedef struct HWVoiceIn { + int enabled; + struct audio_pcm_info info; t_sample *conv; - int left; - int pos; - int bytes_per_second; + int wpos; + int total_samples_captured; + uint64_t ts_helper; + + st_sample_t *conv_buf; + + int samples; + LIST_HEAD (sw_in_listhead, SWVoiceIn) sw_head; + struct audio_pcm_ops *pcm_ops; + LIST_ENTRY (HWVoiceIn) entries; +} HWVoiceIn; + +struct SWVoiceOut { + struct audio_pcm_info info; + t_sample *conv; int64_t ratio; st_sample_t *buf; void *rate; - - int wpos; - int live; + int total_hw_samples_mixed; int active; - int64_t old_ticks; - HWVoice *hw; + int empty; + HWVoiceOut *hw; char *name; -}; - -struct pcm_ops { - int (*init) (HWVoice *hw, int freq, int nchannels, audfmt_e fmt); - void (*fini) (HWVoice *hw); - void (*run) (HWVoice *hw); - int (*write) (SWVoice *sw, void *buf, int size); - int (*ctl) (HWVoice *hw, int cmd, ...); -}; - -void pcm_sw_free_resources (SWVoice *sw); -int pcm_sw_alloc_resources (SWVoice *sw); -void pcm_sw_fini (SWVoice *sw); -int pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq, - int nchannels, audfmt_e fmt); - -void pcm_hw_clear (HWVoice *hw, void *buf, int len); -HWVoice * pcm_hw_find_any (HWVoice *hw); -HWVoice * pcm_hw_find_any_active (HWVoice *hw); -HWVoice * pcm_hw_find_any_passive (HWVoice *hw); -HWVoice * pcm_hw_find_specific (HWVoice *hw, int freq, - int nchannels, audfmt_e fmt); -HWVoice * pcm_hw_add (int freq, int nchannels, audfmt_e fmt); -int pcm_hw_add_sw (HWVoice *hw, SWVoice *sw); -int pcm_hw_del_sw (HWVoice *hw, SWVoice *sw); -SWVoice * pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt); - -void pcm_hw_free_resources (HWVoice *hw); -int pcm_hw_alloc_resources (HWVoice *hw); -void pcm_hw_fini (HWVoice *hw); -void pcm_hw_gc (HWVoice *hw); -int pcm_hw_get_live (HWVoice *hw); -int pcm_hw_get_live2 (HWVoice *hw, int *nb_active); -void pcm_hw_dec_live (HWVoice *hw, int decr); -int pcm_hw_write (SWVoice *sw, void *buf, int len); - -int audio_get_conf_int (const char *key, int defval); -const char *audio_get_conf_str (const char *key, const char *defval); - -struct audio_output_driver; + volume_t vol; + struct audio_callback callback; + LIST_ENTRY (SWVoiceOut) entries; +}; + +struct SWVoiceIn { + int active; + struct audio_pcm_info info; + int64_t ratio; + void *rate; + int total_hw_samples_acquired; + st_sample_t *buf; + f_sample *clip; + HWVoiceIn *hw; + char *name; + volume_t vol; + struct audio_callback callback; + LIST_ENTRY (SWVoiceIn) entries; +}; + +struct audio_driver { + const char *name; + const char *descr; + struct audio_option *options; + void *(*init) (void); + void (*fini) (void *); + struct audio_pcm_ops *pcm_ops; + int can_be_default; + int max_voices_out; + int max_voices_in; + int voice_size_out; + int voice_size_in; +}; + +struct audio_pcm_ops { + int (*init_out)(HWVoiceOut *hw, audsettings_t *as); + void (*fini_out)(HWVoiceOut *hw); + int (*run_out) (HWVoiceOut *hw); + int (*write) (SWVoiceOut *sw, void *buf, int size); + int (*ctl_out) (HWVoiceOut *hw, int cmd, ...); + + int (*init_in) (HWVoiceIn *hw, audsettings_t *as); + void (*fini_in) (HWVoiceIn *hw); + int (*run_in) (HWVoiceIn *hw); + int (*read) (SWVoiceIn *sw, void *buf, int size); + int (*ctl_in) (HWVoiceIn *hw, int cmd, ...); +}; + +struct AudioState { + struct audio_driver *drv; + void *drv_opaque; + + QEMUTimer *ts; + LIST_HEAD (card_head, QEMUSoundCard) card_head; + LIST_HEAD (hw_in_listhead, HWVoiceIn) hw_head_in; + LIST_HEAD (hw_out_listhead, HWVoiceOut) hw_head_out; + int nb_hw_voices_out; + int nb_hw_voices_in; +}; + +extern struct audio_driver no_audio_driver; +extern struct audio_driver oss_audio_driver; +extern struct audio_driver sdl_audio_driver; +extern struct audio_driver wav_audio_driver; +extern struct audio_driver fmod_audio_driver; +extern struct audio_driver alsa_audio_driver; +extern struct audio_driver coreaudio_audio_driver; +extern struct audio_driver dsound_audio_driver; +extern volume_t nominal_volume; + +void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as, + int swap_endian); +void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len); + +int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int len); +int audio_pcm_hw_get_live_in (HWVoiceIn *hw); + +int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int len); +int audio_pcm_hw_get_live_out (HWVoiceOut *hw); +int audio_pcm_hw_get_live_out2 (HWVoiceOut *hw, int *nb_live); + +int audio_bug (const char *funcname, int cond); +void *audio_calloc (const char *funcname, int nmemb, size_t size); #define VOICE_ENABLE 1 #define VOICE_DISABLE 2 +static inline int audio_ring_dist (int dst, int src, int len) +{ + return (dst >= src) ? (dst - src) : (len - src + dst); +} + +static inline int audio_need_to_swap_endian (int endianness) +{ +#ifdef WORDS_BIGENDIAN + return endianness != 1; +#else + return endianness != 0; +#endif +} + +#if defined __GNUC__ +#define GCC_ATTR __attribute__ ((__unused__, __format__ (__printf__, 1, 2))) +#define INIT_FIELD(f) . f +#define GCC_FMT_ATTR(n, m) __attribute__ ((__format__ (__printf__, n, m))) +#else +#define GCC_ATTR /**/ +#define INIT_FIELD(f) /**/ +#define GCC_FMT_ATTR(n, m) +#endif + +static void GCC_ATTR dolog (const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + AUD_vlog (AUDIO_CAP, fmt, ap); + va_end (ap); +} + +#ifdef DEBUG +static void GCC_ATTR ldebug (const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + AUD_vlog (AUDIO_CAP, fmt, ap); + va_end (ap); +} +#else +#if defined NDEBUG && defined __GNUC__ +#define ldebug(...) +#elif defined NDEBUG && defined _MSC_VER +#define ldebug __noop +#else +static void GCC_ATTR ldebug (const char *fmt, ...) +{ + (void) fmt; +} +#endif +#endif + +#undef GCC_ATTR + +#define AUDIO_STRINGIFY_(n) #n +#define AUDIO_STRINGIFY(n) AUDIO_STRINGIFY_(n) + +#if defined _MSC_VER || defined __GNUC__ +#define AUDIO_FUNC __FUNCTION__ +#else +#define AUDIO_FUNC __FILE__ ":" AUDIO_STRINGIFY (__LINE__) +#endif + #endif /* audio_int.h */ diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/audio/mixeng.c --- a/tools/ioemu/audio/mixeng.c Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/audio/mixeng.c Tue Jul 25 12:19:05 2006 -0600 @@ -1,7 +1,7 @@ /* * QEMU Mixing engine * - * Copyright (c) 2004 Vassili Karpov (malc) + * Copyright (c) 2004-2005 Vassili Karpov (malc) * Copyright (c) 1998 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -23,87 +23,174 @@ * THE SOFTWARE. */ #include "vl.h" -//#define DEBUG_FP -#include "audio/mixeng.h" - + +#define AUDIO_CAP "mixeng" +#include "audio_int.h" + +#define NOVOL + +/* 8 bit */ +#define ENDIAN_CONVERSION natural +#define ENDIAN_CONVERT(v) (v) + +/* Signed 8 bit */ #define IN_T int8_t -#define IN_MIN CHAR_MIN -#define IN_MAX CHAR_MAX +#define IN_MIN SCHAR_MIN +#define IN_MAX SCHAR_MAX #define SIGNED +#define SHIFT 8 #include "mixeng_template.h" #undef SIGNED #undef IN_MAX #undef IN_MIN #undef IN_T - +#undef SHIFT + +/* Unsigned 8 bit */ #define IN_T uint8_t #define IN_MIN 0 #define IN_MAX UCHAR_MAX -#include "mixeng_template.h" -#undef IN_MAX -#undef IN_MIN -#undef IN_T - +#define SHIFT 8 +#include "mixeng_template.h" +#undef IN_MAX +#undef IN_MIN +#undef IN_T +#undef SHIFT + +#undef ENDIAN_CONVERT +#undef ENDIAN_CONVERSION + +/* Signed 16 bit */ #define IN_T int16_t #define IN_MIN SHRT_MIN #define IN_MAX SHRT_MAX #define SIGNED -#include "mixeng_template.h" +#define SHIFT 16 +#define ENDIAN_CONVERSION natural +#define ENDIAN_CONVERT(v) (v) +#include "mixeng_template.h" +#undef ENDIAN_CONVERT +#undef ENDIAN_CONVERSION +#define ENDIAN_CONVERSION swap +#define ENDIAN_CONVERT(v) bswap16 (v) +#include "mixeng_template.h" +#undef ENDIAN_CONVERT +#undef ENDIAN_CONVERSION #undef SIGNED #undef IN_MAX #undef IN_MIN #undef IN_T +#undef SHIFT #define IN_T uint16_t #define IN_MIN 0 #define IN_MAX USHRT_MAX -#include "mixeng_template.h" -#undef IN_MAX -#undef IN_MIN -#undef IN_T - -t_sample *mixeng_conv[2][2][2] = { - { - { - conv_uint8_t_to_mono, - conv_uint16_t_to_mono - }, - { - conv_int8_t_to_mono, - conv_int16_t_to_mono +#define SHIFT 16 +#define ENDIAN_CONVERSION natural +#define ENDIAN_CONVERT(v) (v) +#include "mixeng_template.h" +#undef ENDIAN_CONVERT +#undef ENDIAN_CONVERSION +#define ENDIAN_CONVERSION swap +#define ENDIAN_CONVERT(v) bswap16 (v) +#include "mixeng_template.h" +#undef ENDIAN_CONVERT +#undef ENDIAN_CONVERSION +#undef IN_MAX +#undef IN_MIN +#undef IN_T +#undef SHIFT + +t_sample *mixeng_conv[2][2][2][2] = { + { + { + { + conv_natural_uint8_t_to_mono, + conv_natural_uint16_t_to_mono + }, + { + conv_natural_uint8_t_to_mono, + conv_swap_uint16_t_to_mono + } + }, + { + { + conv_natural_int8_t_to_mono, + conv_natural_int16_t_to_mono + }, + { + conv_natural_int8_t_to_mono, + conv_swap_int16_t_to_mono + } } }, { { - conv_uint8_t_to_stereo, - conv_uint16_t_to_stereo - }, - { - conv_int8_t_to_stereo, - conv_int16_t_to_stereo - } - } -}; - -f_sample *mixeng_clip[2][2][2] = { - { - { - clip_uint8_t_from_mono, - clip_uint16_t_from_mono - }, - { - clip_int8_t_from_mono, - clip_int16_t_from_mono + { + conv_natural_uint8_t_to_stereo, + conv_natural_uint16_t_to_stereo + }, + { + conv_natural_uint8_t_to_stereo, + conv_swap_uint16_t_to_stereo + } + }, + { + { + conv_natural_int8_t_to_stereo, + conv_natural_int16_t_to_stereo + }, + { + conv_natural_int8_t_to_stereo, + conv_swap_int16_t_to_stereo + } + } + } +}; + +f_sample *mixeng_clip[2][2][2][2] = { + { + { + { + clip_natural_uint8_t_from_mono, + clip_natural_uint16_t_from_mono + }, + { + clip_natural_uint8_t_from_mono, + clip_swap_uint16_t_from_mono + } + }, + { + { + clip_natural_int8_t_from_mono, + clip_natural_int16_t_from_mono + }, + { + clip_natural_int8_t_from_mono, + clip_swap_int16_t_from_mono + } } }, { { - clip_uint8_t_from_stereo, - clip_uint16_t_from_stereo - }, - { - clip_int8_t_from_stereo, - clip_int16_t_from_stereo + { + clip_natural_uint8_t_from_stereo, + clip_natural_uint16_t_from_stereo + }, + { + clip_natural_uint8_t_from_stereo, + clip_swap_uint16_t_from_stereo + } + }, + { + { + clip_natural_int8_t_from_stereo, + clip_natural_int16_t_from_stereo + }, + { + clip_natural_int8_t_from_stereo, + clip_swap_int16_t_from_stereo + } } } }; @@ -116,9 +203,9 @@ f_sample *mixeng_clip[2][2][2] = { * Contributors with a more efficient algorithm.] * * This source code is freely redistributable and may be used for - * any purpose. This copyright notice must be maintained. - * Lance Norskog And Sundry Contributors are not responsible for - * the consequences of using this software. + * any purpose. This copyright notice must be maintained. + * Lance Norskog And Sundry Contributors are not responsible for + * the consequences of using this software. */ /* @@ -141,36 +228,29 @@ f_sample *mixeng_clip[2][2][2] = { */ /* Private data */ -typedef struct ratestuff { +struct rate { uint64_t opos; uint64_t opos_inc; uint32_t ipos; /* position in the input stream (integer) */ st_sample_t ilast; /* last sample in the input stream */ -} *rate_t; +}; /* * Prepare processing. */ void *st_rate_start (int inrate, int outrate) { - rate_t rate = (rate_t) qemu_mallocz (sizeof (struct ratestuff)); + struct rate *rate = audio_calloc (AUDIO_FUNC, 1, sizeof (*rate)); if (!rate) { - exit (EXIT_FAILURE); - } - - if (inrate == outrate) { - // exit (EXIT_FAILURE); - } - - if (inrate >= 65535 || outrate >= 65535) { - // exit (EXIT_FAILURE); + dolog ("Could not allocate resampler (%zu bytes)\n", sizeof (*rate)); + return NULL; } rate->opos = 0; /* increment */ - rate->opos_inc = (inrate * ((int64_t) UINT_MAX)) / outrate; + rate->opos_inc = ((uint64_t) inrate << 32) / outrate; rate->ipos = 0; rate->ilast.l = 0; @@ -178,78 +258,20 @@ void *st_rate_start (int inrate, int out return rate; } -/* - * Processed signed long samples from ibuf to obuf. - * Return number of samples processed. - */ -void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf, - int *isamp, int *osamp) -{ - rate_t rate = (rate_t) opaque; - st_sample_t *istart, *iend; - st_sample_t *ostart, *oend; - st_sample_t ilast, icur, out; - int64_t t; - - ilast = rate->ilast; - - istart = ibuf; - iend = ibuf + *isamp; - - ostart = obuf; - oend = obuf + *osamp; - - if (rate->opos_inc == 1ULL << 32) { - int i, n = *isamp > *osamp ? *osamp : *isamp; - for (i = 0; i < n; i++) { - obuf[i].l += ibuf[i].r; - obuf[i].r += ibuf[i].r; - } - *isamp = n; - *osamp = n; - return; - } - - while (obuf < oend) { - - /* Safety catch to make sure we have input samples. */ - if (ibuf >= iend) - break; - - /* read as many input samples so that ipos > opos */ - - while (rate->ipos <= (rate->opos >> 32)) { - ilast = *ibuf++; - rate->ipos++; - /* See if we finished the input buffer yet */ - if (ibuf >= iend) goto the_end; - } - - icur = *ibuf; - - /* interpolate */ - t = rate->opos & 0xffffffff; - out.l = (ilast.l * (INT_MAX - t) + icur.l * t) / INT_MAX; - out.r = (ilast.r * (INT_MAX - t) + icur.r * t) / INT_MAX; - - /* output sample & increment position */ -#if 0 - *obuf++ = out; -#else - obuf->l += out.l; - obuf->r += out.r; - obuf += 1; -#endif - rate->opos += rate->opos_inc; - } - -the_end: - *isamp = ibuf - istart; - *osamp = obuf - ostart; - rate->ilast = ilast; -} +#define NAME st_rate_flow_mix +#define OP(a, b) a += b +#include "rate_template.h" + +#define NAME st_rate_flow +#define OP(a, b) a = b +#include "rate_template.h" void st_rate_stop (void *opaque) { qemu_free (opaque); } + +void mixeng_clear (st_sample_t *buf, int len) +{ + memset (buf, 0, len * sizeof (st_sample_t)); +} diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/audio/mixeng.h --- a/tools/ioemu/audio/mixeng.h Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/audio/mixeng.h Tue Jul 25 12:19:05 2006 -0600 @@ -1,8 +1,8 @@ /* * QEMU Mixing engine header - * - * Copyright (c) 2004 Vassili Karpov (malc) - * + * + * Copyright (c) 2004-2005 Vassili Karpov (malc) + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -24,16 +24,28 @@ #ifndef QEMU_MIXENG_H #define QEMU_MIXENG_H -typedef void (t_sample) (void *dst, const void *src, int samples); -typedef void (f_sample) (void *dst, const void *src, int samples); +#ifdef FLOAT_MIXENG +typedef float real_t; +typedef struct { int mute; real_t r; real_t l; } volume_t; +typedef struct { real_t l; real_t r; } st_sample_t; +#else +typedef struct { int mute; int64_t r; int64_t l; } volume_t; typedef struct { int64_t l; int64_t r; } st_sample_t; +#endif -extern t_sample *mixeng_conv[2][2][2]; -extern f_sample *mixeng_clip[2][2][2]; +typedef void (t_sample) (st_sample_t *dst, const void *src, + int samples, volume_t *vol); +typedef void (f_sample) (void *dst, const st_sample_t *src, int samples); + +extern t_sample *mixeng_conv[2][2][2][2]; +extern f_sample *mixeng_clip[2][2][2][2]; void *st_rate_start (int inrate, int outrate); void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf, int *isamp, int *osamp); +void st_rate_flow_mix (void *opaque, st_sample_t *ibuf, st_sample_t *obuf, + int *isamp, int *osamp); void st_rate_stop (void *opaque); +void mixeng_clear (st_sample_t *buf, int len); #endif /* mixeng.h */ diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/audio/mixeng_template.h --- a/tools/ioemu/audio/mixeng_template.h Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/audio/mixeng_template.h Tue Jul 25 12:19:05 2006 -0600 @@ -1,8 +1,8 @@ /* * QEMU Mixing engine - * - * Copyright (c) 2004 Vassili Karpov (malc) - * + * + * Copyright (c) 2004-2005 Vassili Karpov (malc) + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -27,85 +27,151 @@ * dec++'ified by Dscho */ -#ifdef SIGNED -#define HALFT IN_MAX -#define HALF IN_MAX -#else -#define HALFT ((IN_MAX)>>1) -#define HALF HALFT +#ifndef SIGNED +#define HALF (IN_MAX >> 1) #endif -static int64_t inline glue(conv_,IN_T) (IN_T v) +#ifdef NOVOL +#define VOL(a, b) a +#else +#ifdef FLOAT_MIXENG +#define VOL(a, b) ((a) * (b)) +#else +#define VOL(a, b) ((a) * (b)) >> 32 +#endif +#endif + +#define ET glue (ENDIAN_CONVERSION, glue (_, IN_T)) + +#ifdef FLOAT_MIXENG +static real_t inline glue (conv_, ET) (IN_T v) { + IN_T nv = ENDIAN_CONVERT (v); + +#ifdef RECIPROCAL #ifdef SIGNED - return (INT_MAX*(int64_t)v)/HALF; + return nv * (1.f / (real_t) (IN_MAX - IN_MIN)); #else - return (INT_MAX*((int64_t)v-HALFT))/HALF; + return (nv - HALF) * (1.f / (real_t) IN_MAX); +#endif +#else /* !RECIPROCAL */ +#ifdef SIGNED + return nv / (real_t) (IN_MAX - IN_MIN); +#else + return (nv - HALF) / (real_t) IN_MAX; +#endif #endif } -static IN_T inline glue(clip_,IN_T) (int64_t v) +static IN_T inline glue (clip_, ET) (real_t v) { - if (v >= INT_MAX) + if (v >= 0.5) { return IN_MAX; - else if (v < -INT_MAX) + } + else if (v < -0.5) { return IN_MIN; + } #ifdef SIGNED - return (IN_T) (v*HALF/INT_MAX); + return ENDIAN_CONVERT ((IN_T) (v * (IN_MAX - IN_MIN))); #else - return (IN_T) (v+INT_MAX/2)*HALF/INT_MAX; + return ENDIAN_CONVERT ((IN_T) ((v * IN_MAX) + HALF)); #endif } -static void glue(glue(conv_,IN_T),_to_stereo) (void *dst, const void *src, - int samples) +#else /* !FLOAT_MIXENG */ + +static inline int64_t glue (conv_, ET) (IN_T v) { - st_sample_t *out = (st_sample_t *) dst; + IN_T nv = ENDIAN_CONVERT (v); +#ifdef SIGNED + return ((int64_t) nv) << (32 - SHIFT); +#else + return ((int64_t) nv - HALF) << (32 - SHIFT); +#endif +} + +static inline IN_T glue (clip_, ET) (int64_t v) +{ + if (v >= 0x7f000000) { + return IN_MAX; + } + else if (v < -2147483648LL) { + return IN_MIN; + } + +#ifdef SIGNED + return ENDIAN_CONVERT ((IN_T) (v >> (32 - SHIFT))); +#else + return ENDIAN_CONVERT ((IN_T) ((v >> (32 - SHIFT)) + HALF)); +#endif +} +#endif + +static void glue (glue (conv_, ET), _to_stereo) + (st_sample_t *dst, const void *src, int samples, volume_t *vol) +{ + st_sample_t *out = dst; IN_T *in = (IN_T *) src; +#ifndef NOVOL + if (vol->mute) { + mixeng_clear (dst, samples); + return; + } +#else + (void) vol; +#endif while (samples--) { - out->l = glue(conv_,IN_T) (*in++); - out->r = glue(conv_,IN_T) (*in++); + out->l = VOL (glue (conv_, ET) (*in++), vol->l); + out->r = VOL (glue (conv_, ET) (*in++), vol->r); out += 1; } } -static void glue(glue(conv_,IN_T),_to_mono) (void *dst, const void *src, - int samples) +static void glue (glue (conv_, ET), _to_mono) + (st_sample_t *dst, const void *src, int samples, volume_t *vol) { - st_sample_t *out = (st_sample_t *) dst; + st_sample_t *out = dst; IN_T *in = (IN_T *) src; +#ifndef NOVOL + if (vol->mute) { + mixeng_clear (dst, samples); + return; + } +#else + (void) vol; +#endif while (samples--) { - out->l = glue(conv_,IN_T) (in[0]); + out->l = VOL (glue (conv_, ET) (in[0]), vol->l); out->r = out->l; out += 1; in += 1; } } -static void glue(glue(clip_,IN_T),_from_stereo) (void *dst, const void *src, - int samples) +static void glue (glue (clip_, ET), _from_stereo) + (void *dst, const st_sample_t *src, int samples) { - st_sample_t *in = (st_sample_t *) src; + const st_sample_t *in = src; IN_T *out = (IN_T *) dst; while (samples--) { - *out++ = glue(clip_,IN_T) (in->l); - *out++ = glue(clip_,IN_T) (in->r); + *out++ = glue (clip_, ET) (in->l); + *out++ = glue (clip_, ET) (in->r); in += 1; } } -static void glue(glue(clip_,IN_T),_from_mono) (void *dst, const void *src, - int samples) +static void glue (glue (clip_, ET), _from_mono) + (void *dst, const st_sample_t *src, int samples) { - st_sample_t *in = (st_sample_t *) src; + const st_sample_t *in = src; IN_T *out = (IN_T *) dst; while (samples--) { - *out++ = glue(clip_,IN_T) (in->l + in->r); + *out++ = glue (clip_, ET) (in->l + in->r); in += 1; } } +#undef ET #undef HALF -#undef HALFT - +#undef VOL diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/audio/noaudio.c --- a/tools/ioemu/audio/noaudio.c Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/audio/noaudio.c Tue Jul 25 12:19:05 2006 -0600 @@ -1,8 +1,8 @@ /* - * QEMU NULL audio output driver - * - * Copyright (c) 2004 Vassili Karpov (malc) - * + * QEMU Timer based audio emulation + * + * Copyright (c) 2004-2005 Vassili Karpov (malc) + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -23,77 +23,108 @@ */ #include "vl.h" -#include "audio/audio_int.h" +#define AUDIO_CAP "noaudio" +#include "audio_int.h" -typedef struct NoVoice { - HWVoice hw; +typedef struct NoVoiceOut { + HWVoiceOut hw; int64_t old_ticks; -} NoVoice; +} NoVoiceOut; -#define dolog(...) AUD_log ("noaudio", __VA_ARGS__) -#ifdef DEBUG -#define ldebug(...) dolog (__VA_ARGS__) -#else -#define ldebug(...) -#endif +typedef struct NoVoiceIn { + HWVoiceIn hw; + int64_t old_ticks; +} NoVoiceIn; -static void no_hw_run (HWVoice *hw) +static int no_run_out (HWVoiceOut *hw) { - NoVoice *no = (NoVoice *) hw; - int rpos, live, decr, samples; - st_sample_t *src; + NoVoiceOut *no = (NoVoiceOut *) hw; + int live, decr, samples; int64_t now = qemu_get_clock (vm_clock); int64_t ticks = now - no->old_ticks; - int64_t bytes = (ticks * hw->bytes_per_second) / ticks_per_sec; + int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec; - if (bytes > INT_MAX) - samples = INT_MAX >> hw->shift; - else - samples = bytes >> hw->shift; + if (bytes > INT_MAX) { + samples = INT_MAX >> hw->info.shift; + } + else { + samples = bytes >> hw->info.shift; + } - live = pcm_hw_get_live (hw); - if (live <= 0) - return; + live = audio_pcm_hw_get_live_out (&no->hw); + if (!live) { + return 0; + } no->old_ticks = now; decr = audio_MIN (live, samples); - samples = decr; - rpos = hw->rpos; - while (samples) { - int left_till_end_samples = hw->samples - rpos; - int convert_samples = audio_MIN (samples, left_till_end_samples); - - src = advance (hw->mix_buf, rpos * sizeof (st_sample_t)); - memset (src, 0, convert_samples * sizeof (st_sample_t)); - - rpos = (rpos + convert_samples) % hw->samples; - samples -= convert_samples; - } - - pcm_hw_dec_live (hw, decr); - hw->rpos = rpos; + hw->rpos = (hw->rpos + decr) % hw->samples; + return decr; } -static int no_hw_write (SWVoice *sw, void *buf, int len) +static int no_write (SWVoiceOut *sw, void *buf, int len) { - return pcm_hw_write (sw, buf, len); + return audio_pcm_sw_write (sw, buf, len); } -static int no_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt) +static int no_init_out (HWVoiceOut *hw, audsettings_t *as) { - hw->freq = freq; - hw->nchannels = nchannels; - hw->fmt = fmt; - hw->bufsize = 4096; + audio_pcm_init_info (&hw->info, as, 0); + hw->samples = 1024; return 0; } -static void no_hw_fini (HWVoice *hw) +static void no_fini_out (HWVoiceOut *hw) { (void) hw; } -static int no_hw_ctl (HWVoice *hw, int cmd, ...) +static int no_ctl_out (HWVoiceOut *hw, int cmd, ...) +{ + (void) hw; + (void) cmd; + return 0; +} + +static int no_init_in (HWVoiceIn *hw, audsettings_t *as) +{ + audio_pcm_init_info (&hw->info, as, 0); + hw->samples = 1024; + return 0; +} + +static void no_fini_in (HWVoiceIn *hw) +{ + (void) hw; +} + +static int no_run_in (HWVoiceIn *hw) +{ + NoVoiceIn *no = (NoVoiceIn *) hw; + int64_t now = qemu_get_clock (vm_clock); + int64_t ticks = now - no->old_ticks; + int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec; + int live = audio_pcm_hw_get_live_in (hw); + int dead = hw->samples - live; + int samples; + + bytes = audio_MIN (bytes, INT_MAX); + samples = bytes >> hw->info.shift; + samples = audio_MIN (samples, dead); + + return samples; +} + +static int no_read (SWVoiceIn *sw, void *buf, int size) +{ + int samples = size >> sw->info.shift; + int total = sw->hw->total_samples_captured - sw->total_hw_samples_acquired; + int to_clear = audio_MIN (samples, total); + audio_pcm_info_clear_buf (&sw->info, buf, to_clear); + return to_clear; +} + +static int no_ctl_in (HWVoiceIn *hw, int cmd, ...) { (void) hw; (void) cmd; @@ -107,22 +138,33 @@ static void *no_audio_init (void) static void no_audio_fini (void *opaque) { + (void) opaque; } -struct pcm_ops no_pcm_ops = { - no_hw_init, - no_hw_fini, - no_hw_run, - no_hw_write, - no_hw_ctl +static struct audio_pcm_ops no_pcm_ops = { + no_init_out, + no_fini_out, + no_run_out, + no_write, + no_ctl_out, + + no_init_in, + no_fini_in, + no_run_in, + no_read, + no_ctl_in }; -struct audio_output_driver no_output_driver = { - "none", - no_audio_init, - no_audio_fini, - &no_pcm_ops, - 1, - 1, - sizeof (NoVoice) +struct audio_driver no_audio_driver = { + INIT_FIELD (name = ) "none", + INIT_FIELD (descr = ) "Timer based audio emulation", + INIT_FIELD (options = ) NULL, + INIT_FIELD (init = ) no_audio_init, + INIT_FIELD (fini = ) no_audio_fini, + INIT_FIELD (pcm_ops = ) &no_pcm_ops, + INIT_FIELD (can_be_default = ) 1, + INIT_FIELD (max_voices_out = ) INT_MAX, + INIT_FIELD (max_voices_in = ) INT_MAX, + INIT_FIELD (voice_size_out = ) sizeof (NoVoiceOut), + INIT_FIELD (voice_size_in = ) sizeof (NoVoiceIn) }; diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/audio/ossaudio.c --- a/tools/ioemu/audio/ossaudio.c Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/audio/ossaudio.c Tue Jul 25 12:19:05 2006 -0600 @@ -1,8 +1,8 @@ /* - * QEMU OSS audio output driver - * - * Copyright (c) 2003-2004 Vassili Karpov (malc) - * + * QEMU OSS audio driver + * + * Copyright (c) 2003-2005 Vassili Karpov (malc) + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -25,45 +25,42 @@ #include <sys/types.h> #include <sys/ioctl.h> #include <sys/soundcard.h> -#include <assert.h> #include "vl.h" -#include "audio/audio_int.h" - -typedef struct OSSVoice { - HWVoice hw; +#define AUDIO_CAP "oss" +#include "audio_int.h" + +typedef struct OSSVoiceOut { + HWVoiceOut hw; void *pcm_buf; int fd; int nfrags; int fragsize; int mmapped; int old_optr; -} OSSVoice; - -#define dolog(...) AUD_log ("oss", __VA_ARGS__) -#ifdef DEBUG -#define ldebug(...) dolog (__VA_ARGS__) -#else -#define ldebug(...) -#endif - -#define QC_OSS_FRAGSIZE "QEMU_OSS_FRAGSIZE" -#define QC_OSS_NFRAGS "QEMU_OSS_NFRAGS" -#define QC_OSS_MMAP "QEMU_OSS_MMAP" -#define QC_OSS_DEV "QEMU_OSS_DEV" - -#define errstr() strerror (errno) +} OSSVoiceOut; + +typedef struct OSSVoiceIn { + HWVoiceIn hw; + void *pcm_buf; + int fd; + int nfrags; + int fragsize; + int old_optr; +} OSSVoiceIn; static struct { int try_mmap; int nfrags; int fragsize; - const char *dspname; + const char *devpath_out; + const char *devpath_in; } conf = { .try_mmap = 0, .nfrags = 4, .fragsize = 4096, - .dspname = "/dev/dsp" + .devpath_out = "/dev/dsp", + .devpath_in = "/dev/dsp" }; struct oss_params { @@ -74,65 +71,141 @@ struct oss_params { int fragsize; }; -static int oss_hw_write (SWVoice *sw, void *buf, int len) -{ - return pcm_hw_write (sw, buf, len); -} - -static int AUD_to_ossfmt (audfmt_e fmt) +static void GCC_FMT_ATTR (2, 3) oss_logerr (int err, const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + AUD_vlog (AUDIO_CAP, fmt, ap); + va_end (ap); + + AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err)); +} + +static void GCC_FMT_ATTR (3, 4) oss_logerr2 ( + int err, + const char *typ, + const char *fmt, + ... + ) +{ + va_list ap; + + AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ); + + va_start (ap, fmt); + AUD_vlog (AUDIO_CAP, fmt, ap); + va_end (ap); + + AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err)); +} + +static void oss_anal_close (int *fdp) +{ + int err = close (*fdp); + if (err) { + oss_logerr (errno, "Failed to close file(fd=%d)\n", *fdp); + } + *fdp = -1; +} + +static int oss_write (SWVoiceOut *sw, void *buf, int len) +{ + return audio_pcm_sw_write (sw, buf, len); +} + +static int aud_to_ossfmt (audfmt_e fmt) { switch (fmt) { - case AUD_FMT_S8: return AFMT_S8; - case AUD_FMT_U8: return AFMT_U8; - case AUD_FMT_S16: return AFMT_S16_LE; - case AUD_FMT_U16: return AFMT_U16_LE; + case AUD_FMT_S8: + return AFMT_S8; + + case AUD_FMT_U8: + return AFMT_U8; + + case AUD_FMT_S16: + return AFMT_S16_LE; + + case AUD_FMT_U16: + return AFMT_U16_LE; + default: - dolog ("Internal logic error: Bad audio format %d\nAborting\n", fmt); - exit (EXIT_FAILURE); - } -} - -static int oss_to_audfmt (int fmt) -{ - switch (fmt) { - case AFMT_S8: return AUD_FMT_S8; - case AFMT_U8: return AUD_FMT_U8; - case AFMT_S16_LE: return AUD_FMT_S16; - case AFMT_U16_LE: return AUD_FMT_U16; + dolog ("Internal logic error: Bad audio format %d\n", fmt); +#ifdef DEBUG_AUDIO + abort (); +#endif + return AFMT_U8; + } +} + +static int oss_to_audfmt (int ossfmt, audfmt_e *fmt, int *endianness) +{ + switch (ossfmt) { + case AFMT_S8: + *endianness =0; + *fmt = AUD_FMT_S8; + break; + + case AFMT_U8: + *endianness = 0; + *fmt = AUD_FMT_U8; + break; + + case AFMT_S16_LE: + *endianness = 0; + *fmt = AUD_FMT_S16; + break; + + case AFMT_U16_LE: + *endianness = 0; + *fmt = AUD_FMT_U16; + break; + + case AFMT_S16_BE: + *endianness = 1; + *fmt = AUD_FMT_S16; + break; + + case AFMT_U16_BE: + *endianness = 1; + *fmt = AUD_FMT_U16; + break; + default: - dolog ("Internal logic error: Unrecognized OSS audio format %d\n" - "Aborting\n", - fmt); - exit (EXIT_FAILURE); - } -} - -#ifdef DEBUG_PCM -static void oss_dump_pcm_info (struct oss_params *req, struct oss_params *obt) + dolog ("Unrecognized audio format %d\n", ossfmt); + return -1; + } + + return 0; +} + +#if defined DEBUG_MISMATCHES || defined DEBUG +static void oss_dump_info (struct oss_params *req, struct oss_params *obt) { dolog ("parameter | requested value | obtained value\n"); dolog ("format | %10d | %10d\n", req->fmt, obt->fmt); - dolog ("channels | %10d | %10d\n", req->nchannels, obt->nchannels); + dolog ("channels | %10d | %10d\n", + req->nchannels, obt->nchannels); dolog ("frequency | %10d | %10d\n", req->freq, obt->freq); dolog ("nfrags | %10d | %10d\n", req->nfrags, obt->nfrags); - dolog ("fragsize | %10d | %10d\n", req->fragsize, obt->fragsize); + dolog ("fragsize | %10d | %10d\n", + req->fragsize, obt->fragsize); } #endif -static int oss_open (struct oss_params *req, struct oss_params *obt, int *pfd) +static int oss_open (int in, struct oss_params *req, + struct oss_params *obt, int *pfd) { int fd; int mmmmssss; audio_buf_info abinfo; int fmt, freq, nchannels; - const char *dspname = conf.dspname; - - fd = open (dspname, O_RDWR | O_NONBLOCK); + const char *dspname = in ? conf.devpath_in : conf.devpath_out; + const char *typ = in ? "ADC" : "DAC"; + + fd = open (dspname, (in ? O_RDONLY : O_WRONLY) | O_NONBLOCK); if (-1 == fd) { - dolog ("Could not initialize audio hardware. Failed to open `%s':\n" - "Reason:%s\n", - dspname, - errstr ()); + oss_logerr2 (errno, typ, "Failed to open `%s'\n", dspname); return -1; } @@ -141,52 +214,35 @@ static int oss_open (struct oss_params * fmt = req->fmt; if (ioctl (fd, SNDCTL_DSP_SAMPLESIZE, &fmt)) { - dolog ("Could not initialize audio hardware\n" - "Failed to set sample size\n" - "Reason: %s\n", - errstr ()); + oss_logerr2 (errno, typ, "Failed to set sample size %d\n", req->fmt); goto err; } if (ioctl (fd, SNDCTL_DSP_CHANNELS, &nchannels)) { - dolog ("Could not initialize audio hardware\n" - "Failed to set number of channels\n" - "Reason: %s\n", - errstr ()); + oss_logerr2 (errno, typ, "Failed to set number of channels %d\n", + req->nchannels); goto err; } if (ioctl (fd, SNDCTL_DSP_SPEED, &freq)) { - dolog ("Could not initialize audio hardware\n" - "Failed to set frequency\n" - "Reason: %s\n", - errstr ()); + oss_logerr2 (errno, typ, "Failed to set frequency %d\n", req->freq); goto err; } if (ioctl (fd, SNDCTL_DSP_NONBLOCK)) { - dolog ("Could not initialize audio hardware\n" - "Failed to set non-blocking mode\n" - "Reason: %s\n", - errstr ()); + oss_logerr2 (errno, typ, "Failed to set non-blocking mode\n"); goto err; } mmmmssss = (req->nfrags << 16) | lsbindex (req->fragsize); if (ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss)) { - dolog ("Could not initialize audio hardware\n" - "Failed to set buffer length (%d, %d)\n" - "Reason:%s\n", - conf.nfrags, conf.fragsize, - errstr ()); + oss_logerr2 (errno, typ, "Failed to set buffer length (%d, %d)\n", + req->nfrags, req->fragsize); goto err; } - if (ioctl (fd, SNDCTL_DSP_GETOSPACE, &abinfo)) { - dolog ("Could not initialize audio hardware\n" - "Failed to get buffer length\n" - "Reason:%s\n", - errstr ()); + if (ioctl (fd, in ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE, &abinfo)) { + oss_logerr2 (errno, typ, "Failed to get buffer length\n"); goto err; } @@ -197,75 +253,87 @@ static int oss_open (struct oss_params * obt->fragsize = abinfo.fragsize; *pfd = fd; +#ifdef DEBUG_MISMATCHES if ((req->fmt != obt->fmt) || (req->nchannels != obt->nchannels) || (req->freq != obt->freq) || (req->fragsize != obt->fragsize) || (req->nfrags != obt->nfrags)) { -#ifdef DEBUG_PCM dolog ("Audio parameters mismatch\n"); - oss_dump_pcm_info (req, obt); + oss_dump_info (req, obt); + } #endif - } - -#ifdef DEBUG_PCM - oss_dump_pcm_info (req, obt); + +#ifdef DEBUG + oss_dump_info (req, obt); #endif return 0; -err: - close (fd); + err: + oss_anal_close (&fd); return -1; } -static void oss_hw_run (HWVoice *hw) -{ - OSSVoice *oss = (OSSVoice *) hw; +static int oss_run_out (HWVoiceOut *hw) +{ + OSSVoiceOut *oss = (OSSVoiceOut *) hw; int err, rpos, live, decr; int samples; uint8_t *dst; st_sample_t *src; struct audio_buf_info abinfo; struct count_info cntinfo; - - live = pcm_hw_get_live (hw); - if (live <= 0) - return; + int bufsize; + + live = audio_pcm_hw_get_live_out (hw); + if (!live) { + return 0; + } + + bufsize = hw->samples << hw->info.shift; if (oss->mmapped) { int bytes; err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo); if (err < 0) { - dolog ("SNDCTL_DSP_GETOPTR failed\nReason: %s\n", errstr ()); - return; + oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n"); + return 0; } if (cntinfo.ptr == oss->old_optr) { - if (abs (hw->samples - live) < 64) - dolog ("overrun\n"); - return; + if (abs (hw->samples - live) < 64) { + dolog ("warning: Overrun\n"); + } + return 0; } if (cntinfo.ptr > oss->old_optr) { bytes = cntinfo.ptr - oss->old_optr; } else { - bytes = hw->bufsize + cntinfo.ptr - oss->old_optr; - } - - decr = audio_MIN (bytes >> hw->shift, live); + bytes = bufsize + cntinfo.ptr - oss->old_optr; + } + + decr = audio_MIN (bytes >> hw->info.shift, live); } else { err = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &abinfo); if (err < 0) { - dolog ("SNDCTL_DSP_GETOSPACE failed\nReason: %s\n", errstr ()); - return; - } - - decr = audio_MIN (abinfo.bytes >> hw->shift, live); - if (decr <= 0) - return; + oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n"); + return 0; + } + + if (abinfo.bytes < 0 || abinfo.bytes > bufsize) { + ldebug ("warning: Invalid available size, size=%d bufsize=%d\n", + abinfo.bytes, bufsize); + return 0; + } + + decr = audio_MIN (abinfo.bytes >> hw->info.shift, live); + if (!decr) { + return 0; + } } samples = decr; @@ -274,33 +342,41 @@ static void oss_hw_run (HWVoice *hw) int left_till_end_samples = hw->samples - rpos; int convert_samples = audio_MIN (samples, left_till_end_samples); - src = advance (hw->mix_buf, rpos * sizeof (st_sample_t)); - dst = advance (oss->pcm_buf, rpos << hw->shift); + src = hw->mix_buf + rpos; + dst = advance (oss->pcm_buf, rpos << hw->info.shift); hw->clip (dst, src, convert_samples); if (!oss->mmapped) { int written; - written = write (oss->fd, dst, convert_samples << hw->shift); + written = write (oss->fd, dst, convert_samples << hw->info.shift); /* XXX: follow errno recommendations ? */ if (written == -1) { - dolog ("Failed to write audio\nReason: %s\n", errstr ()); + oss_logerr ( + errno, + "Failed to write %d bytes of audio data from %p\n", + convert_samples << hw->info.shift, + dst + ); continue; } - if (written != convert_samples << hw->shift) { - int wsamples = written >> hw->shift; - int wbytes = wsamples << hw->shift; + if (written != convert_samples << hw->info.shift) { + int wsamples = written >> hw->info.shift; + int wbytes = wsamples << hw->info.shift; if (wbytes != written) { - dolog ("Unaligned write %d, %d\n", wbytes, written); + dolog ("warning: Misaligned write %d (requested %d), " + "alignment %d\n", + wbytes, written, hw->info.align + 1); } - memset (src, 0, wbytes); - decr -= samples; + mixeng_clear (src, wsamples); + decr -= wsamples; rpos = (rpos + wsamples) % hw->samples; break; } } - memset (src, 0, convert_samples * sizeof (st_sample_t)); + + mixeng_clear (src, convert_samples); rpos = (rpos + convert_samples) % hw->samples; samples -= convert_samples; @@ -309,28 +385,24 @@ static void oss_hw_run (HWVoice *hw) oss->old_optr = cntinfo.ptr; } - pcm_hw_dec_live (hw, decr); hw->rpos = rpos; -} - -static void oss_hw_fini (HWVoice *hw) + return decr; +} + +static void oss_fini_out (HWVoiceOut *hw) { int err; - OSSVoice *oss = (OSSVoice *) hw; - - ldebug ("oss_hw_fini\n"); - err = close (oss->fd); - if (err) { - dolog ("Failed to close OSS descriptor\nReason: %s\n", errstr ()); - } - oss->fd = -1; + OSSVoiceOut *oss = (OSSVoiceOut *) hw; + + ldebug ("oss_fini\n"); + oss_anal_close (&oss->fd); if (oss->pcm_buf) { if (oss->mmapped) { - err = munmap (oss->pcm_buf, hw->bufsize); + err = munmap (oss->pcm_buf, hw->samples << hw->info.shift); if (err) { - dolog ("Failed to unmap OSS buffer\nReason: %s\n", - errstr ()); + oss_logerr (errno, "Failed to unmap buffer %p, size %d\n", + oss->pcm_buf, hw->samples << hw->info.shift); } } else { @@ -340,48 +412,79 @@ static void oss_hw_fini (HWVoice *hw) } } -static int oss_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt) -{ - OSSVoice *oss = (OSSVoice *) hw; +static int oss_init_out (HWVoiceOut *hw, audsettings_t *as) +{ + OSSVoiceOut *oss = (OSSVoiceOut *) hw; struct oss_params req, obt; - - assert (!oss->fd); - req.fmt = AUD_to_ossfmt (fmt); - req.freq = freq; - req.nchannels = nchannels; + int endianness; + int err; + int fd; + audfmt_e effective_fmt; + audsettings_t obt_as; + + oss->fd = -1; + + req.fmt = aud_to_ossfmt (as->fmt); + req.freq = as->freq; + req.nchannels = as->nchannels; req.fragsize = conf.fragsize; req.nfrags = conf.nfrags; - if (oss_open (&req, &obt, &oss->fd)) + if (oss_open (0, &req, &obt, &fd)) { return -1; - - hw->freq = obt.freq; - hw->fmt = oss_to_audfmt (obt.fmt); - hw->nchannels = obt.nchannels; - + } + + err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness); + if (err) { + oss_anal_close (&fd); + return -1; + } + + obt_as.freq = obt.freq; + obt_as.nchannels = obt.nchannels; + obt_as.fmt = effective_fmt; + + audio_pcm_init_info ( + &hw->info, + &obt_as, + audio_need_to_swap_endian (endianness) + ); oss->nfrags = obt.nfrags; oss->fragsize = obt.fragsize; - hw->bufsize = obt.nfrags * obt.fragsize; + + if (obt.nfrags * obt.fragsize & hw->info.align) { + dolog ("warning: Misaligned DAC buffer, size %d, alignment %d\n", + obt.nfrags * obt.fragsize, hw->info.align + 1); + } + + hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift; oss->mmapped = 0; if (conf.try_mmap) { - oss->pcm_buf = mmap (0, hw->bufsize, PROT_READ | PROT_WRITE, - MAP_SHARED, oss->fd, 0); + oss->pcm_buf = mmap ( + 0, + hw->samples << hw->info.shift, + PROT_READ | PROT_WRITE, + MAP_SHARED, + fd, + 0 + ); if (oss->pcm_buf == MAP_FAILED) { - dolog ("Failed to mmap OSS device\nReason: %s\n", - errstr ()); + oss_logerr (errno, "Failed to map %d bytes of DAC\n", + hw->samples << hw->info.shift); } else { int err; int trig = 0; - if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { - dolog ("SNDCTL_DSP_SETTRIGGER 0 failed\nReason: %s\n", - errstr ()); + if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { + oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n"); } else { trig = PCM_ENABLE_OUTPUT; - if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { - dolog ("SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n" - "Reason: %s\n", errstr ()); + if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { + oss_logerr ( + errno, + "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n" + ); } else { oss->mmapped = 1; @@ -389,43 +492,55 @@ static int oss_hw_init (HWVoice *hw, int } if (!oss->mmapped) { - err = munmap (oss->pcm_buf, hw->bufsize); + err = munmap (oss->pcm_buf, hw->samples << hw->info.shift); if (err) { - dolog ("Failed to unmap OSS device\nReason: %s\n", - errstr ()); + oss_logerr (errno, "Failed to unmap buffer %p size %d\n", + oss->pcm_buf, hw->samples << hw->info.shift); } } } } if (!oss->mmapped) { - oss->pcm_buf = qemu_mallocz (hw->bufsize); + oss->pcm_buf = audio_calloc ( + AUDIO_FUNC, + hw->samples, + 1 << hw->info.shift + ); if (!oss->pcm_buf) { - close (oss->fd); - oss->fd = -1; + dolog ( + "Could not allocate DAC buffer (%d samples, each %d bytes)\n", + hw->samples, + 1 << hw->info.shift + ); + oss_anal_close (&fd); return -1; } } + oss->fd = fd; return 0; } -static int oss_hw_ctl (HWVoice *hw, int cmd, ...) +static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...) { int trig; - OSSVoice *oss = (OSSVoice *) hw; - - if (!oss->mmapped) + OSSVoiceOut *oss = (OSSVoiceOut *) hw; + + if (!oss->mmapped) { return 0; + } switch (cmd) { case VOICE_ENABLE: ldebug ("enabling voice\n"); - pcm_hw_clear (hw, oss->pcm_buf, hw->samples); + audio_pcm_info_clear_buf (&hw->info, oss->pcm_buf, hw->samples); trig = PCM_ENABLE_OUTPUT; if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { - dolog ("SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n" - "Reason: %s\n", errstr ()); + oss_logerr ( + errno, + "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n" + ); return -1; } break; @@ -434,8 +549,7 @@ static int oss_hw_ctl (HWVoice *hw, int ldebug ("disabling voice\n"); trig = 0; if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { - dolog ("SNDCTL_DSP_SETTRIGGER 0 failed\nReason: %s\n", - errstr ()); + oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n"); return -1; } break; @@ -443,33 +557,206 @@ static int oss_hw_ctl (HWVoice *hw, int return 0; } +static int oss_init_in (HWVoiceIn *hw, audsettings_t *as) +{ + OSSVoiceIn *oss = (OSSVoiceIn *) hw; + struct oss_params req, obt; + int endianness; + int err; + int fd; + audfmt_e effective_fmt; + audsettings_t obt_as; + + oss->fd = -1; + + req.fmt = aud_to_ossfmt (as->fmt); + req.freq = as->freq; + req.nchannels = as->nchannels; + req.fragsize = conf.fragsize; + req.nfrags = conf.nfrags; + if (oss_open (1, &req, &obt, &fd)) { + return -1; + } + + err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness); + if (err) { + oss_anal_close (&fd); + return -1; + } + + obt_as.freq = obt.freq; + obt_as.nchannels = obt.nchannels; + obt_as.fmt = effective_fmt; + + audio_pcm_init_info ( + &hw->info, + &obt_as, + audio_need_to_swap_endian (endianness) + ); + oss->nfrags = obt.nfrags; + oss->fragsize = obt.fragsize; + + if (obt.nfrags * obt.fragsize & hw->info.align) { + dolog ("warning: Misaligned ADC buffer, size %d, alignment %d\n", + obt.nfrags * obt.fragsize, hw->info.align + 1); + } + + hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift; + oss->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift); + if (!oss->pcm_buf) { + dolog ("Could not allocate ADC buffer (%d samples, each %d bytes)\n", + hw->samples, 1 << hw->info.shift); + oss_anal_close (&fd); + return -1; + } + + oss->fd = fd; + return 0; +} + +static void oss_fini_in (HWVoiceIn *hw) +{ + OSSVoiceIn *oss = (OSSVoiceIn *) hw; + + oss_anal_close (&oss->fd); + + if (oss->pcm_buf) { + qemu_free (oss->pcm_buf); + oss->pcm_buf = NULL; + } +} + +static int oss_run_in (HWVoiceIn *hw) +{ + OSSVoiceIn *oss = (OSSVoiceIn *) hw; + int hwshift = hw->info.shift; + int i; + int live = audio_pcm_hw_get_live_in (hw); + int dead = hw->samples - live; + size_t read_samples = 0; + struct { + int add; + int len; + } bufs[2] = { + { hw->wpos, 0 }, + { 0, 0 } + }; + + if (!dead) { + return 0; + } + + if (hw->wpos + dead > hw->samples) { + bufs[0].len = (hw->samples - hw->wpos) << hwshift; + bufs[1].len = (dead - (hw->samples - hw->wpos)) << hwshift; + } + else { + bufs[0].len = dead << hwshift; + } + + + for (i = 0; i < 2; ++i) { + ssize_t nread; + + if (bufs[i].len) { + void *p = advance (oss->pcm_buf, bufs[i].add << hwshift); + nread = read (oss->fd, p, bufs[i].len); + + if (nread > 0) { + if (nread & hw->info.align) { + dolog ("warning: Misaligned read %zd (requested %d), " + "alignment %d\n", nread, bufs[i].add << hwshift, + hw->info.align + 1); + } + read_samples += nread >> hwshift; + hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift, + &nominal_volume); + } + + if (bufs[i].len - nread) { + if (nread == -1) { + switch (errno) { + case EINTR: + case EAGAIN: + break; + default: + oss_logerr ( + errno, + "Failed to read %d bytes of audio (to %p)\n", + bufs[i].len, p + ); + break; + } + } + break; + } + } + } + + hw->wpos = (hw->wpos + read_samples) % hw->samples; + return read_samples; +} + +static int oss_read (SWVoiceIn *sw, void *buf, int size) +{ + return audio_pcm_sw_read (sw, buf, size); +} + +static int oss_ctl_in (HWVoiceIn *hw, int cmd, ...) +{ + (void) hw; + (void) cmd; + return 0; +} + static void *oss_audio_init (void) { - conf.fragsize = audio_get_conf_int (QC_OSS_FRAGSIZE, conf.fragsize); - conf.nfrags = audio_get_conf_int (QC_OSS_NFRAGS, conf.nfrags); - conf.try_mmap = audio_get_conf_int (QC_OSS_MMAP, conf.try_mmap); - conf.dspname = audio_get_conf_str (QC_OSS_DEV, conf.dspname); return &conf; } static void oss_audio_fini (void *opaque) { -} - -struct pcm_ops oss_pcm_ops = { - oss_hw_init, - oss_hw_fini, - oss_hw_run, - oss_hw_write, - oss_hw_ctl + (void) opaque; +} + +static struct audio_option oss_options[] = { + {"FRAGSIZE", AUD_OPT_INT, &conf.fragsize, + "Fragment size in bytes", NULL, 0}, + {"NFRAGS", AUD_OPT_INT, &conf.nfrags, + "Number of fragments", NULL, 0}, + {"MMAP", AUD_OPT_BOOL, &conf.try_mmap, + "Try using memory mapped access", NULL, 0}, + {"DAC_DEV", AUD_OPT_STR, &conf.devpath_out, + "Path to DAC device", NULL, 0}, + {"ADC_DEV", AUD_OPT_STR, &conf.devpath_in, + "Path to ADC device", NULL, 0}, + {NULL, 0, NULL, NULL, NULL, 0} }; -struct audio_output_driver oss_output_driver = { - "oss", - oss_audio_init, - oss_audio_fini, - &oss_pcm_ops, - 1, - INT_MAX, - sizeof (OSSVoice) +static struct audio_pcm_ops oss_pcm_ops = { + oss_init_out, + oss_fini_out, + oss_run_out, + oss_write, + oss_ctl_out, + + oss_init_in, + oss_fini_in, + oss_run_in, + oss_read, + oss_ctl_in }; + +struct audio_driver oss_audio_driver = { + INIT_FIELD (name = ) "oss", + INIT_FIELD (descr = ) "OSS http://www.opensound.com", + INIT_FIELD (options = ) oss_options, + INIT_FIELD (init = ) oss_audio_init, + INIT_FIELD (fini = ) oss_audio_fini, + INIT_FIELD (pcm_ops = ) &oss_pcm_ops, + INIT_FIELD (can_be_default = ) 1, + INIT_FIELD (max_voices_out = ) INT_MAX, + INIT_FIELD (max_voices_in = ) INT_MAX, + INIT_FIELD (voice_size_out = ) sizeof (OSSVoiceOut), + INIT_FIELD (voice_size_in = ) sizeof (OSSVoiceIn) +}; diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/audio/sdlaudio.c --- a/tools/ioemu/audio/sdlaudio.c Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/audio/sdlaudio.c Tue Jul 25 12:19:05 2006 -0600 @@ -1,8 +1,8 @@ /* - * QEMU SDL audio output driver - * - * Copyright (c) 2004 Vassili Karpov (malc) - * + * QEMU SDL audio driver + * + * Copyright (c) 2004-2005 Vassili Karpov (malc) + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -25,22 +25,15 @@ #include <SDL_thread.h> #include "vl.h" -#include "audio/audio_int.h" - -typedef struct SDLVoice { - HWVoice hw; -} SDLVoice; - -#define dolog(...) AUD_log ("sdl", __VA_ARGS__) -#ifdef DEBUG -#define ldebug(...) dolog (__VA_ARGS__) -#else -#define ldebug(...) -#endif - -#define QC_SDL_SAMPLES "QEMU_SDL_SAMPLES" - -#define errstr() SDL_GetError () +#define AUDIO_CAP "sdl" +#include "audio_int.h" + +typedef struct SDLVoiceOut { + HWVoiceOut hw; + int live; + int rpos; + int decr; +} SDLVoiceOut; static struct { int nb_samples; @@ -56,91 +49,129 @@ struct SDLAudioState { } glob_sdl; typedef struct SDLAudioState SDLAudioState; -static void sdl_hw_run (HWVoice *hw) -{ - (void) hw; -} - -static int sdl_lock (SDLAudioState *s) +static void GCC_FMT_ATTR (1, 2) sdl_logerr (const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + AUD_vlog (AUDIO_CAP, fmt, ap); + va_end (ap); + + AUD_log (AUDIO_CAP, "Reason: %s\n", SDL_GetError ()); +} + +static int sdl_lock (SDLAudioState *s, const char *forfn) { if (SDL_LockMutex (s->mutex)) { - dolog ("SDL_LockMutex failed\nReason: %s\n", errstr ()); - return -1; - } - return 0; -} - -static int sdl_unlock (SDLAudioState *s) + sdl_logerr ("SDL_LockMutex for %s failed\n", forfn); + return -1; + } + return 0; +} + +static int sdl_unlock (SDLAudioState *s, const char *forfn) { if (SDL_UnlockMutex (s->mutex)) { - dolog ("SDL_UnlockMutex failed\nReason: %s\n", errstr ()); - return -1; - } - return 0; -} - -static int sdl_post (SDLAudioState *s) + sdl_logerr ("SDL_UnlockMutex for %s failed\n", forfn); + return -1; + } + return 0; +} + +static int sdl_post (SDLAudioState *s, const char *forfn) { if (SDL_SemPost (s->sem)) { - dolog ("SDL_SemPost failed\nReason: %s\n", errstr ()); - return -1; - } - return 0; -} - -static int sdl_wait (SDLAudioState *s) + sdl_logerr ("SDL_SemPost for %s failed\n", forfn); + return -1; + } + return 0; +} + +static int sdl_wait (SDLAudioState *s, const char *forfn) { if (SDL_SemWait (s->sem)) { - dolog ("SDL_SemWait failed\nReason: %s\n", errstr ()); - return -1; - } - return 0; -} - -static int sdl_unlock_and_post (SDLAudioState *s) -{ - if (sdl_unlock (s)) - return -1; - - return sdl_post (s); -} - -static int sdl_hw_write (SWVoice *sw, void *buf, int len) -{ - int ret; - SDLAudioState *s = &glob_sdl; - sdl_lock (s); - ret = pcm_hw_write (sw, buf, len); - sdl_unlock_and_post (s); - return ret; -} - -static int AUD_to_sdlfmt (audfmt_e fmt, int *shift) -{ - *shift = 0; + sdl_logerr ("SDL_SemWait for %s failed\n", forfn); + return -1; + } + return 0; +} + +static int sdl_unlock_and_post (SDLAudioState *s, const char *forfn) +{ + if (sdl_unlock (s, forfn)) { + return -1; + } + + return sdl_post (s, forfn); +} + +static int aud_to_sdlfmt (audfmt_e fmt, int *shift) +{ switch (fmt) { - case AUD_FMT_S8: return AUDIO_S8; - case AUD_FMT_U8: return AUDIO_U8; - case AUD_FMT_S16: *shift = 1; return AUDIO_S16LSB; - case AUD_FMT_U16: *shift = 1; return AUDIO_U16LSB; + case AUD_FMT_S8: + *shift = 0; + return AUDIO_S8; + + case AUD_FMT_U8: + *shift = 0; + return AUDIO_U8; + + case AUD_FMT_S16: + *shift = 1; + return AUDIO_S16LSB; + + case AUD_FMT_U16: + *shift = 1; + return AUDIO_U16LSB; + default: - dolog ("Internal logic error: Bad audio format %d\nAborting\n", fmt); - exit (EXIT_FAILURE); - } -} - -static int sdl_to_audfmt (int fmt) -{ - switch (fmt) { - case AUDIO_S8: return AUD_FMT_S8; - case AUDIO_U8: return AUD_FMT_U8; - case AUDIO_S16LSB: return AUD_FMT_S16; - case AUDIO_U16LSB: return AUD_FMT_U16; + dolog ("Internal logic error: Bad audio format %d\n", fmt); +#ifdef DEBUG_AUDIO + abort (); +#endif + return AUDIO_U8; + } +} + +static int sdl_to_audfmt (int sdlfmt, audfmt_e *fmt, int *endianess) +{ + switch (sdlfmt) { + case AUDIO_S8: + *endianess = 0; + *fmt = AUD_FMT_S8; + break; + + case AUDIO_U8: + *endianess = 0; + *fmt = AUD_FMT_U8; + break; + + case AUDIO_S16LSB: + *endianess = 0; + *fmt = AUD_FMT_S16; + break; + + case AUDIO_U16LSB: + *endianess = 0; + *fmt = AUD_FMT_U16; + break; + + case AUDIO_S16MSB: + *endianess = 1; + *fmt = AUD_FMT_S16; + break; + + case AUDIO_U16MSB: + *endianess = 1; + *fmt = AUD_FMT_U16; + break; + default: - dolog ("Internal logic error: Unrecognized SDL audio format %d\n" - "Aborting\n", fmt); - exit (EXIT_FAILURE); - } + dolog ("Unrecognized SDL audio format %d\n", sdlfmt); + return -1; + } + + return 0; } static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt) @@ -149,7 +180,7 @@ static int sdl_open (SDL_AudioSpec *req, status = SDL_OpenAudio (req, obt); if (status) { - dolog ("SDL_OpenAudio failed\nReason: %s\n", errstr ()); + sdl_logerr ("SDL_OpenAudio failed\n"); } return status; } @@ -157,9 +188,9 @@ static void sdl_close (SDLAudioState *s) static void sdl_close (SDLAudioState *s) { if (s->initialized) { - sdl_lock (s); + sdl_lock (s, "sdl_close"); s->exit = 1; - sdl_unlock_and_post (s); + sdl_unlock_and_post (s, "sdl_close"); SDL_PauseAudio (1); SDL_CloseAudio (); s->initialized = 0; @@ -168,31 +199,40 @@ static void sdl_close (SDLAudioState *s) static void sdl_callback (void *opaque, Uint8 *buf, int len) { - SDLVoice *sdl = opaque; + SDLVoiceOut *sdl = opaque; SDLAudioState *s = &glob_sdl; - HWVoice *hw = &sdl->hw; - int samples = len >> hw->shift; + HWVoiceOut *hw = &sdl->hw; + int samples = len >> hw->info.shift; if (s->exit) { return; } while (samples) { - int to_mix, live, decr; + int to_mix, decr; /* dolog ("in callback samples=%d\n", samples); */ - sdl_wait (s); + sdl_wait (s, "sdl_callback"); if (s->exit) { return; } - sdl_lock (s); - live = pcm_hw_get_live (hw); - if (live <= 0) + if (sdl_lock (s, "sdl_callback")) { + return; + } + + if (audio_bug (AUDIO_FUNC, sdl->live < 0 || sdl->live > hw->samples)) { + dolog ("sdl->live=%d hw->samples=%d\n", + sdl->live, hw->samples); + return; + } + + if (!sdl->live) { goto again; + } /* dolog ("in callback live=%d\n", live); */ - to_mix = audio_MIN (samples, live); + to_mix = audio_MIN (samples, sdl->live); decr = to_mix; while (to_mix) { int chunk = audio_MIN (to_mix, hw->samples - hw->rpos); @@ -200,58 +240,109 @@ static void sdl_callback (void *opaque, /* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */ hw->clip (buf, src, chunk); - memset (src, 0, chunk * sizeof (st_sample_t)); - hw->rpos = (hw->rpos + chunk) % hw->samples; + mixeng_clear (src, chunk); + sdl->rpos = (sdl->rpos + chunk) % hw->samples; to_mix -= chunk; - buf += chunk << hw->shift; + buf += chunk << hw->info.shift; } samples -= decr; - pcm_hw_dec_live (hw, decr); + sdl->live -= decr; + sdl->decr += decr; again: - sdl_unlock (s); + if (sdl_unlock (s, "sdl_callback")) { + return; + } } /* dolog ("done len=%d\n", len); */ } -static void sdl_hw_fini (HWVoice *hw) -{ - ldebug ("sdl_hw_fini %d fixed=%d\n", - glob_sdl.initialized, audio_conf.fixed_format); +static int sdl_write_out (SWVoiceOut *sw, void *buf, int len) +{ + return audio_pcm_sw_write (sw, buf, len); +} + +static int sdl_run_out (HWVoiceOut *hw) +{ + int decr, live; + SDLVoiceOut *sdl = (SDLVoiceOut *) hw; + SDLAudioState *s = &glob_sdl; + + if (sdl_lock (s, "sdl_callback")) { + return 0; + } + + live = audio_pcm_hw_get_live_out (hw); + + if (sdl->decr > live) { + ldebug ("sdl->decr %d live %d sdl->live %d\n", + sdl->decr, + live, + sdl->live); + } + + decr = audio_MIN (sdl->decr, live); + sdl->decr -= decr; + + sdl->live = live - decr; + hw->rpos = sdl->rpos; + + if (sdl->live > 0) { + sdl_unlock_and_post (s, "sdl_callback"); + } + else { + sdl_unlock (s, "sdl_callback"); + } + return decr; +} + +static void sdl_fini_out (HWVoiceOut *hw) +{ + (void) hw; + sdl_close (&glob_sdl); } -static int sdl_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt) -{ - SDLVoice *sdl = (SDLVoice *) hw; +static int sdl_init_out (HWVoiceOut *hw, audsettings_t *as) +{ + SDLVoiceOut *sdl = (SDLVoiceOut *) hw; SDLAudioState *s = &glob_sdl; SDL_AudioSpec req, obt; int shift; - - ldebug ("sdl_hw_init %d freq=%d fixed=%d\n", - s->initialized, freq, audio_conf.fixed_format); - - if (nchannels != 2) { - dolog ("Bogus channel count %d\n", nchannels); - return -1; - } - - req.freq = freq; - req.format = AUD_to_sdlfmt (fmt, &shift); - req.channels = nchannels; + int endianess; + int err; + audfmt_e effective_fmt; + audsettings_t obt_as; + + shift <<= as->nchannels == 2; + + req.freq = as->freq; + req.format = aud_to_sdlfmt (as->fmt, &shift); + req.channels = as->nchannels; req.samples = conf.nb_samples; - shift <<= nchannels == 2; - req.callback = sdl_callback; req.userdata = sdl; - if (sdl_open (&req, &obt)) - return -1; - - hw->freq = obt.freq; - hw->fmt = sdl_to_audfmt (obt.format); - hw->nchannels = obt.channels; - hw->bufsize = obt.samples << shift; + if (sdl_open (&req, &obt)) { + return -1; + } + + err = sdl_to_audfmt (obt.format, &effective_fmt, &endianess); + if (err) { + sdl_close (s); + return -1; + } + + obt_as.freq = obt.freq; + obt_as.nchannels = obt.channels; + obt_as.fmt = effective_fmt; + + audio_pcm_init_info ( + &hw->info, + &obt_as, + audio_need_to_swap_endian (endianess) + ); + hw->samples = obt.samples; s->initialized = 1; s->exit = 0; @@ -259,7 +350,7 @@ static int sdl_hw_init (HWVoice *hw, int return 0; } -static int sdl_hw_ctl (HWVoice *hw, int cmd, ...) +static int sdl_ctl_out (HWVoiceOut *hw, int cmd, ...) { (void) hw; @@ -278,24 +369,22 @@ static void *sdl_audio_init (void) static void *sdl_audio_init (void) { SDLAudioState *s = &glob_sdl; - conf.nb_samples = audio_get_conf_int (QC_SDL_SAMPLES, conf.nb_samples); if (SDL_InitSubSystem (SDL_INIT_AUDIO)) { - dolog ("SDL failed to initialize audio subsystem\nReason: %s\n", - errstr ()); + sdl_logerr ("SDL failed to initialize audio subsystem\n"); return NULL; } s->mutex = SDL_CreateMutex (); if (!s->mutex) { - dolog ("Failed to create SDL mutex\nReason: %s\n", errstr ()); + sdl_logerr ("Failed to create SDL mutex\n"); SDL_QuitSubSystem (SDL_INIT_AUDIO); return NULL; } s->sem = SDL_CreateSemaphore (0); if (!s->sem) { - dolog ("Failed to create SDL semaphore\nReason: %s\n", errstr ()); + sdl_logerr ("Failed to create SDL semaphore\n"); SDL_DestroyMutex (s->mutex); SDL_QuitSubSystem (SDL_INIT_AUDIO); return NULL; @@ -313,20 +402,36 @@ static void sdl_audio_fini (void *opaque SDL_QuitSubSystem (SDL_INIT_AUDIO); } -struct pcm_ops sdl_pcm_ops = { - sdl_hw_init, - sdl_hw_fini, - sdl_hw_run, - sdl_hw_write, - sdl_hw_ctl +static struct audio_option sdl_options[] = { + {"SAMPLES", AUD_OPT_INT, &conf.nb_samples, + "Size of SDL buffer in samples", NULL, 0}, + {NULL, 0, NULL, NULL, NULL, 0} }; -struct audio_output_driver sdl_output_driver = { - "sdl", - sdl_audio_init, - sdl_audio_fini, - &sdl_pcm_ops, - 1, - 1, - sizeof (SDLVoice) +static struct audio_pcm_ops sdl_pcm_ops = { + sdl_init_out, + sdl_fini_out, + sdl_run_out, + sdl_write_out, + sdl_ctl_out, + + NULL, + NULL, + NULL, + NULL, + NULL }; + +struct audio_driver sdl_audio_driver = { + INIT_FIELD (name = ) "sdl", + INIT_FIELD (descr = ) "SDL http://www.libsdl.org", + INIT_FIELD (options = ) sdl_options, + INIT_FIELD (init = ) sdl_audio_init, + INIT_FIELD (fini = ) sdl_audio_fini, + INIT_FIELD (pcm_ops = ) &sdl_pcm_ops, + INIT_FIELD (can_be_default = ) 1, + INIT_FIELD (max_voices_out = ) 1, + INIT_FIELD (max_voices_in = ) 0, + INIT_FIELD (voice_size_out = ) sizeof (SDLVoiceOut), + INIT_FIELD (voice_size_in = ) 0 +}; diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/audio/wavaudio.c --- a/tools/ioemu/audio/wavaudio.c Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/audio/wavaudio.c Tue Jul 25 12:19:05 2006 -0600 @@ -1,8 +1,8 @@ /* - * QEMU WAV audio output driver - * - * Copyright (c) 2004 Vassili Karpov (malc) - * + * QEMU WAV audio driver + * + * Copyright (c) 2004-2005 Vassili Karpov (malc) + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -23,47 +23,50 @@ */ #include "vl.h" -#include "audio/audio_int.h" - -typedef struct WAVVoice { - HWVoice hw; +#define AUDIO_CAP "wav" +#include "audio_int.h" + +typedef struct WAVVoiceOut { + HWVoiceOut hw; QEMUFile *f; int64_t old_ticks; void *pcm_buf; int total_samples; -} WAVVoice; - -#define dolog(...) AUD_log ("wav", __VA_ARGS__) -#ifdef DEBUG -#define ldebug(...) dolog (__VA_ARGS__) -#else -#define ldebug(...) -#endif +} WAVVoiceOut; static struct { + audsettings_t settings; const char *wav_path; } conf = { - .wav_path = "qemu.wav" -}; - -static void wav_hw_run (HWVoice *hw) -{ - WAVVoice *wav = (WAVVoice *) hw; + { + 44100, + 2, + AUD_FMT_S16 + }, + "qemu.wav" +}; + +static int wav_run_out (HWVoiceOut *hw) +{ + WAVVoiceOut *wav = (WAVVoiceOut *) hw; int rpos, live, decr, samples; uint8_t *dst; st_sample_t *src; int64_t now = qemu_get_clock (vm_clock); int64_t ticks = now - wav->old_ticks; - int64_t bytes = (ticks * hw->bytes_per_second) / ticks_per_sec; - - if (bytes > INT_MAX) - samples = INT_MAX >> hw->shift; - else - samples = bytes >> hw->shift; - - live = pcm_hw_get_live (hw); - if (live <= 0) - return; + int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec; + + if (bytes > INT_MAX) { + samples = INT_MAX >> hw->info.shift; + } + else { + samples = bytes >> hw->info.shift; + } + + live = audio_pcm_hw_get_live_out (hw); + if (!live) { + return 0; + } wav->old_ticks = now; decr = audio_MIN (live, samples); @@ -73,25 +76,25 @@ static void wav_hw_run (HWVoice *hw) int left_till_end_samples = hw->samples - rpos; int convert_samples = audio_MIN (samples, left_till_end_samples); - src = advance (hw->mix_buf, rpos * sizeof (st_sample_t)); - dst = advance (wav->pcm_buf, rpos << hw->shift); + src = hw->mix_buf + rpos; + dst = advance (wav->pcm_buf, rpos << hw->info.shift); hw->clip (dst, src, convert_samples); - qemu_put_buffer (wav->f, dst, convert_samples << hw->shift); - memset (src, 0, convert_samples * sizeof (st_sample_t)); + qemu_put_buffer (wav->f, dst, convert_samples << hw->info.shift); + mixeng_clear (src, convert_samples); rpos = (rpos + convert_samples) % hw->samples; samples -= convert_samples; wav->total_samples += convert_samples; } - pcm_hw_dec_live (hw, decr); hw->rpos = rpos; -} - -static int wav_hw_write (SWVoice *sw, void *buf, int len) -{ - return pcm_hw_write (sw, buf, len); + return decr; +} + +static int wav_write_out (SWVoiceOut *sw, void *buf, int len) +{ + return audio_pcm_sw_write (sw, buf, len); } /* VICE code: Store number as little endian. */ @@ -104,20 +107,25 @@ static void le_store (uint8_t *buf, uint } } -static int wav_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt) -{ - WAVVoice *wav = (WAVVoice *) hw; - int bits16 = 0, stereo = audio_state.fixed_channels == 2; +static int wav_init_out (HWVoiceOut *hw, audsettings_t *as) +{ + WAVVoiceOut *wav = (WAVVoiceOut *) hw; + int bits16 = 0, stereo = 0; uint8_t hdr[] = { 0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00 }; - - switch (audio_state.fixed_fmt) { + audsettings_t wav_as = conf.settings; + + (void) as; + + stereo = wav_as.nchannels == 2; + switch (wav_as.fmt) { case AUD_FMT_S8: case AUD_FMT_U8: + bits16 = 0; break; case AUD_FMT_S16: @@ -127,22 +135,25 @@ static int wav_hw_init (HWVoice *hw, int } hdr[34] = bits16 ? 0x10 : 0x08; - hw->freq = 44100; - hw->nchannels = stereo ? 2 : 1; - hw->fmt = bits16 ? AUD_FMT_S16 : AUD_FMT_U8; - hw->bufsize = 4096; - wav->pcm_buf = qemu_mallocz (hw->bufsize); - if (!wav->pcm_buf) + + audio_pcm_init_info (&hw->info, &wav_as, audio_need_to_swap_endian (0)); + + hw->samples = 1024; + wav->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift); + if (!wav->pcm_buf) { + dolog ("Could not allocate buffer (%d bytes)\n", + hw->samples << hw->info.shift); return -1; - - le_store (hdr + 22, hw->nchannels, 2); - le_store (hdr + 24, hw->freq, 4); - le_store (hdr + 28, hw->freq << (bits16 + stereo), 4); + } + + le_store (hdr + 22, hw->info.nchannels, 2); + le_store (hdr + 24, hw->info.freq, 4); + le_store (hdr + 28, hw->info.freq << (bits16 + stereo), 4); le_store (hdr + 32, 1 << (bits16 + stereo), 2); wav->f = fopen (conf.wav_path, "wb"); if (!wav->f) { - dolog ("failed to open wave file `%s'\nReason: %s\n", + dolog ("Failed to open wave file `%s'\nReason: %s\n", conf.wav_path, strerror (errno)); qemu_free (wav->pcm_buf); wav->pcm_buf = NULL; @@ -153,17 +164,17 @@ static int wav_hw_init (HWVoice *hw, int return 0; } -static void wav_hw_fini (HWVoice *hw) -{ - WAVVoice *wav = (WAVVoice *) hw; - int stereo = hw->nchannels == 2; +static void wav_fini_out (HWVoiceOut *hw) +{ + WAVVoiceOut *wav = (WAVVoiceOut *) hw; uint8_t rlen[4]; uint8_t dlen[4]; - uint32_t rifflen = (wav->total_samples << stereo) + 36; - uint32_t datalen = wav->total_samples << stereo; - - if (!wav->f || !hw->active) + uint32_t datalen = wav->total_samples << hw->info.shift; + uint32_t rifflen = datalen + 36; + + if (!wav->f) { return; + } le_store (rlen, rifflen, 4); le_store (dlen, datalen, 4); @@ -181,7 +192,7 @@ static void wav_hw_fini (HWVoice *hw) wav->pcm_buf = NULL; } -static int wav_hw_ctl (HWVoice *hw, int cmd, ...) +static int wav_ctl_out (HWVoiceOut *hw, int cmd, ...) { (void) hw; (void) cmd; @@ -195,23 +206,50 @@ static void *wav_audio_init (void) static void wav_audio_fini (void *opaque) { + (void) opaque; ldebug ("wav_fini"); } -struct pcm_ops wav_pcm_ops = { - wav_hw_init, - wav_hw_fini, - wav_hw_run, - wav_hw_write, - wav_hw_ctl -}; - -struct audio_output_driver wav_output_driver = { - "wav", - wav_audio_init, - wav_audio_fini, - &wav_pcm_ops, - 1, - 1, - sizeof (WAVVoice) -}; +struct audio_option wav_options[] = { + {"FREQUENCY", AUD_OPT_INT, &conf.settings.freq, + "Frequency", NULL, 0}, + + {"FORMAT", AUD_OPT_FMT, &conf.settings.fmt, + "Format", NULL, 0}, + + {"DAC_FIXED_CHANNELS", AUD_OPT_INT, &conf.settings.nchannels, + "Number of channels (1 - mono, 2 - stereo)", NULL, 0}, + + {"PATH", AUD_OPT_STR, &conf.wav_path, + "Path to wave file", NULL, 0}, + {NULL, 0, NULL, NULL, NULL, 0} +}; + +struct audio_pcm_ops wav_pcm_ops = { + wav_init_out, + wav_fini_out, + wav_run_out, + wav_write_out, + wav_ctl_out, + + NULL, + NULL, + NULL, + NULL, + NULL +}; + +struct audio_driver wav_audio_driver = { + INIT_FIELD (name = ) "wav", + INIT_FIELD (descr = ) + "WAV renderer http://wikipedia.org/wiki/WAV", + INIT_FIELD (options = ) wav_options, + INIT_FIELD (init = ) wav_audio_init, + INIT_FIELD (fini = ) wav_audio_fini, + INIT_FIELD (pcm_ops = ) &wav_pcm_ops, + INIT_FIELD (can_be_default = ) 0, + INIT_FIELD (max_voices_out = ) 1, + INIT_FIELD (max_voices_in = ) 0, + INIT_FIELD (voice_size_out = ) sizeof (WAVVoiceOut), + INIT_FIELD (voice_size_in = ) 0 +}; diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/block-cloop.c --- a/tools/ioemu/block-cloop.c Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/block-cloop.c Tue Jul 25 12:19:05 2006 -0600 @@ -1,5 +1,5 @@ /* - * QEMU System Emulator block driver + * QEMU Block driver for CLOOP images * * Copyright (c) 2004 Johannes E. Schindelin * @@ -32,8 +32,8 @@ typedef struct BDRVCloopState { uint64_t* offsets; uint32_t sectors_per_block; uint32_t current_block; - char* compressed_block; - char* uncompressed_block; + uint8_t *compressed_block; + uint8_t *uncompressed_block; z_stream zstream; } BDRVCloopState; @@ -89,9 +89,9 @@ cloop_close: } /* initialize zlib engine */ - if(!(s->compressed_block=(char*)malloc(max_compressed_block_size+1))) + if(!(s->compressed_block = malloc(max_compressed_block_size+1))) goto cloop_close; - if(!(s->uncompressed_block=(char*)malloc(s->block_size))) + if(!(s->uncompressed_block = malloc(s->block_size))) goto cloop_close; if(inflateInit(&s->zstream) != Z_OK) goto cloop_close; @@ -149,6 +149,8 @@ static void cloop_close(BlockDriverState { BDRVCloopState *s = bs->opaque; close(s->fd); + if(s->n_blocks>0) + free(s->offsets); free(s->compressed_block); free(s->uncompressed_block); inflateEnd(&s->zstream); diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/block-cow.c --- a/tools/ioemu/block-cow.c Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/block-cow.c Tue Jul 25 12:19:05 2006 -0600 @@ -54,7 +54,8 @@ static int cow_probe(const uint8_t *buf, { const struct cow_header_v2 *cow_header = (const void *)buf; - if (be32_to_cpu(cow_header->magic) == COW_MAGIC && + if (buf_size >= sizeof(struct cow_header_v2) && + be32_to_cpu(cow_header->magic) == COW_MAGIC && be32_to_cpu(cow_header->version) == COW_VERSION) return 100; else @@ -124,7 +125,7 @@ static int cow_open(BlockDriverState *bs return -1; } -static inline void set_bit(uint8_t *bitmap, int64_t bitnum) +static inline void cow_set_bit(uint8_t *bitmap, int64_t bitnum) { bitmap[bitnum / 8] |= (1 << (bitnum%8)); } @@ -198,7 +199,7 @@ static int cow_write(BlockDriverState *b if (ret != nb_sectors * 512) return -1; for (i = 0; i < nb_sectors; i++) - set_bit(s->cow_bitmap, sector_num + i); + cow_set_bit(s->cow_bitmap, sector_num + i); return 0; } diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/block-qcow.c --- a/tools/ioemu/block-qcow.c Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/block-qcow.c Tue Jul 25 12:19:05 2006 -0600 @@ -80,8 +80,9 @@ static int qcow_probe(const uint8_t *buf static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename) { const QCowHeader *cow_header = (const void *)buf; - - if (be32_to_cpu(cow_header->magic) == QCOW_MAGIC && + + if (buf_size >= sizeof(QCowHeader) && + be32_to_cpu(cow_header->magic) == QCOW_MAGIC && be32_to_cpu(cow_header->version) == QCOW_VERSION) return 100; else @@ -551,15 +552,28 @@ static int qcow_create(const char *filen header_size = sizeof(header); backing_filename_len = 0; if (backing_file) { - realpath(backing_file, backing_filename); - if (stat(backing_filename, &st) != 0) { - return -1; - } + if (strcmp(backing_file, "fat:")) { + const char *p; + /* XXX: this is a hack: we do not attempt to check for URL + like syntax */ + p = strchr(backing_file, ':'); + if (p && (p - backing_file) >= 2) { + /* URL like but exclude "c:" like filenames */ + pstrcpy(backing_filename, sizeof(backing_filename), + backing_file); + } else { + realpath(backing_file, backing_filename); + if (stat(backing_filename, &st) != 0) { + return -1; + } + } + header.backing_file_offset = cpu_to_be64(header_size); + backing_filename_len = strlen(backing_filename); + header.backing_file_size = cpu_to_be32(backing_filename_len); + header_size += backing_filename_len; + } else + backing_file = NULL; header.mtime = cpu_to_be32(st.st_mtime); - header.backing_file_offset = cpu_to_be64(header_size); - backing_filename_len = strlen(backing_filename); - header.backing_file_size = cpu_to_be32(backing_filename_len); - header_size += backing_filename_len; header.cluster_bits = 9; /* 512 byte cluster to avoid copying unmodifyed sectors */ header.l2_bits = 12; /* 32 KB L2 tables */ @@ -589,6 +603,24 @@ static int qcow_create(const char *filen write(fd, &tmp, sizeof(tmp)); } close(fd); + return 0; +} + +int qcow_make_empty(BlockDriverState *bs) +{ + BDRVQcowState *s = bs->opaque; + uint32_t l1_length = s->l1_size * sizeof(uint64_t); + + memset(s->l1_table, 0, l1_length); + lseek(s->fd, s->l1_table_offset, SEEK_SET); + if (write(s->fd, s->l1_table, l1_length) < 0) + return -1; + ftruncate(s->fd, s->l1_table_offset + l1_length); + + memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t)); + memset(s->l2_cache_offsets, 0, L2_CACHE_SIZE * sizeof(uint64_t)); + memset(s->l2_cache_counts, 0, L2_CACHE_SIZE * sizeof(uint32_t)); + return 0; } @@ -672,6 +704,7 @@ BlockDriver bdrv_qcow = { qcow_create, qcow_is_allocated, qcow_set_key, + qcow_make_empty }; diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/block-vmdk.c --- a/tools/ioemu/block-vmdk.c Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/block-vmdk.c Tue Jul 25 12:19:05 2006 -0600 @@ -2,6 +2,7 @@ * Block driver for the VMDK format * * Copyright (c) 2004 Fabrice Bellard + * Copyright (c) 2005 Filip Navara * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,9 +25,6 @@ #include "vl.h" #include "block_int.h" -/* XXX: this code is untested */ -/* XXX: add write support */ - #define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D') #define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V') @@ -56,14 +54,16 @@ typedef struct { int64_t grain_offset; char filler[1]; char check_bytes[4]; -} VMDK4Header; +} __attribute__((packed)) VMDK4Header; #define L2_CACHE_SIZE 16 typedef struct BDRVVmdkState { int fd; int64_t l1_table_offset; + int64_t l1_backup_table_offset; uint32_t *l1_table; + uint32_t *l1_backup_table; unsigned int l1_size; uint32_t l1_entry_sectors; @@ -96,9 +96,13 @@ static int vmdk_open(BlockDriverState *b uint32_t magic; int l1_size; - fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); - if (fd < 0) - return -1; + fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE); + if (fd < 0) { + fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); + if (fd < 0) + return -1; + bs->read_only = 1; + } if (read(fd, &magic, sizeof(magic)) != sizeof(magic)) goto fail; magic = be32_to_cpu(magic); @@ -111,22 +115,24 @@ static int vmdk_open(BlockDriverState *b s->l2_size = 1 << 9; s->l1_size = 1 << 6; bs->total_sectors = le32_to_cpu(header.disk_sectors); - s->l1_table_offset = le32_to_cpu(header.l1dir_offset) * 512; + s->l1_table_offset = le32_to_cpu(header.l1dir_offset) << 9; + s->l1_backup_table_offset = 0; s->l1_entry_sectors = s->l2_size * s->cluster_sectors; } else if (magic == VMDK4_MAGIC) { VMDK4Header header; if (read(fd, &header, sizeof(header)) != sizeof(header)) goto fail; - bs->total_sectors = le32_to_cpu(header.capacity); - s->cluster_sectors = le32_to_cpu(header.granularity); + bs->total_sectors = le64_to_cpu(header.capacity); + s->cluster_sectors = le64_to_cpu(header.granularity); s->l2_size = le32_to_cpu(header.num_gtes_per_gte); s->l1_entry_sectors = s->l2_size * s->cluster_sectors; if (s->l1_entry_sectors <= 0) goto fail; s->l1_size = (bs->total_sectors + s->l1_entry_sectors - 1) / s->l1_entry_sectors; - s->l1_table_offset = le64_to_cpu(header.rgd_offset) * 512; + s->l1_table_offset = le64_to_cpu(header.rgd_offset) << 9; + s->l1_backup_table_offset = le64_to_cpu(header.gd_offset) << 9; } else { goto fail; } @@ -143,14 +149,26 @@ static int vmdk_open(BlockDriverState *b le32_to_cpus(&s->l1_table[i]); } + if (s->l1_backup_table_offset) { + s->l1_backup_table = qemu_malloc(l1_size); + if (!s->l1_backup_table) + goto fail; + if (lseek(fd, s->l1_backup_table_offset, SEEK_SET) == -1) + goto fail; + if (read(fd, s->l1_backup_table, l1_size) != l1_size) + goto fail; + for(i = 0; i < s->l1_size; i++) { + le32_to_cpus(&s->l1_backup_table[i]); + } + } + s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint32_t)); if (!s->l2_cache) goto fail; s->fd = fd; - /* XXX: currently only read only */ - bs->read_only = 1; return 0; fail: + qemu_free(s->l1_backup_table); qemu_free(s->l1_table); qemu_free(s->l2_cache); close(fd); @@ -158,12 +176,12 @@ static int vmdk_open(BlockDriverState *b } static uint64_t get_cluster_offset(BlockDriverState *bs, - uint64_t offset) + uint64_t offset, int allocate) { BDRVVmdkState *s = bs->opaque; unsigned int l1_index, l2_offset, l2_index; int min_index, i, j; - uint32_t min_count, *l2_table; + uint32_t min_count, *l2_table, tmp; uint64_t cluster_offset; l1_index = (offset >> 9) / s->l1_entry_sectors; @@ -172,7 +190,6 @@ static uint64_t get_cluster_offset(Block l2_offset = s->l1_table[l1_index]; if (!l2_offset) return 0; - for(i = 0; i < L2_CACHE_SIZE; i++) { if (l2_offset == s->l2_cache_offsets[i]) { /* increment the hit count */ @@ -204,6 +221,26 @@ static uint64_t get_cluster_offset(Block found: l2_index = ((offset >> 9) / s->cluster_sectors) % s->l2_size; cluster_offset = le32_to_cpu(l2_table[l2_index]); + if (!cluster_offset) { + if (!allocate) + return 0; + cluster_offset = lseek(s->fd, 0, SEEK_END); + ftruncate(s->fd, cluster_offset + (s->cluster_sectors << 9)); + cluster_offset >>= 9; + /* update L2 table */ + tmp = cpu_to_le32(cluster_offset); + l2_table[l2_index] = tmp; + lseek(s->fd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), SEEK_SET); + if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp)) + return 0; + /* update backup L2 table */ + if (s->l1_backup_table_offset != 0) { + l2_offset = s->l1_backup_table[l1_index]; + lseek(s->fd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), SEEK_SET); + if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp)) + return 0; + } + } cluster_offset <<= 9; return cluster_offset; } @@ -215,7 +252,7 @@ static int vmdk_is_allocated(BlockDriver int index_in_cluster, n; uint64_t cluster_offset; - cluster_offset = get_cluster_offset(bs, sector_num << 9); + cluster_offset = get_cluster_offset(bs, sector_num << 9, 0); index_in_cluster = sector_num % s->cluster_sectors; n = s->cluster_sectors - index_in_cluster; if (n > nb_sectors) @@ -232,7 +269,7 @@ static int vmdk_read(BlockDriverState *b uint64_t cluster_offset; while (nb_sectors > 0) { - cluster_offset = get_cluster_offset(bs, sector_num << 9); + cluster_offset = get_cluster_offset(bs, sector_num << 9, 0); index_in_cluster = sector_num % s->cluster_sectors; n = s->cluster_sectors - index_in_cluster; if (n > nb_sectors) @@ -255,7 +292,130 @@ static int vmdk_write(BlockDriverState * static int vmdk_write(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors) { - return -1; + BDRVVmdkState *s = bs->opaque; + int ret, index_in_cluster, n; + uint64_t cluster_offset; + + while (nb_sectors > 0) { + index_in_cluster = sector_num & (s->cluster_sectors - 1); + n = s->cluster_sectors - index_in_cluster; + if (n > nb_sectors) + n = nb_sectors; + cluster_offset = get_cluster_offset(bs, sector_num << 9, 1); + if (!cluster_offset) + return -1; + lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET); + ret = write(s->fd, buf, n * 512); + if (ret != n * 512) + return -1; + nb_sectors -= n; + sector_num += n; + buf += n * 512; + } + return 0; +} + +static int vmdk_create(const char *filename, int64_t total_size, + const char *backing_file, int flags) +{ + int fd, i; + VMDK4Header header; + uint32_t tmp, magic, grains, gd_size, gt_size, gt_count; + char *desc_template = + "# Disk DescriptorFile\n" + "version=1\n" + "CID=%x\n" + "parentCID=ffffffff\n" + "createType=\"monolithicSparse\"\n" + "\n" + "# Extent description\n" + "RW %lu SPARSE \"%s\"\n" + "\n" + "# The Disk Data Base \n" + "#DDB\n" + "\n" + "ddb.virtualHWVersion = \"3\"\n" + "ddb.geometry.cylinders = \"%lu\"\n" + "ddb.geometry.heads = \"16\"\n" + "ddb.geometry.sectors = \"63\"\n" + "ddb.adapterType = \"ide\"\n"; + char desc[1024]; + const char *real_filename, *temp_str; + + /* XXX: add support for backing file */ + + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, + 0644); + if (fd < 0) + return -1; + magic = cpu_to_be32(VMDK4_MAGIC); + memset(&header, 0, sizeof(header)); + header.version = cpu_to_le32(1); + header.flags = cpu_to_le32(3); /* ?? */ + header.capacity = cpu_to_le64(total_size); + header.granularity = cpu_to_le64(128); + header.num_gtes_per_gte = cpu_to_le32(512); + + grains = (total_size + header.granularity - 1) / header.granularity; + gt_size = ((header.num_gtes_per_gte * sizeof(uint32_t)) + 511) >> 9; + gt_count = (grains + header.num_gtes_per_gte - 1) / header.num_gtes_per_gte; + gd_size = (gt_count * sizeof(uint32_t) + 511) >> 9; + + header.desc_offset = 1; + header.desc_size = 20; + header.rgd_offset = header.desc_offset + header.desc_size; + header.gd_offset = header.rgd_offset + gd_size + (gt_size * gt_count); + header.grain_offset = + ((header.gd_offset + gd_size + (gt_size * gt_count) + + header.granularity - 1) / header.granularity) * + header.granularity; + + header.desc_offset = cpu_to_le64(header.desc_offset); + header.desc_size = cpu_to_le64(header.desc_size); + header.rgd_offset = cpu_to_le64(header.rgd_offset); + header.gd_offset = cpu_to_le64(header.gd_offset); + header.grain_offset = cpu_to_le64(header.grain_offset); + + header.check_bytes[0] = 0xa; + header.check_bytes[1] = 0x20; + header.check_bytes[2] = 0xd; + header.check_bytes[3] = 0xa; + + /* write all the data */ + write(fd, &magic, sizeof(magic)); + write(fd, &header, sizeof(header)); + + ftruncate(fd, header.grain_offset << 9); + + /* write grain directory */ + lseek(fd, le64_to_cpu(header.rgd_offset) << 9, SEEK_SET); + for (i = 0, tmp = header.rgd_offset + gd_size; + i < gt_count; i++, tmp += gt_size) + write(fd, &tmp, sizeof(tmp)); + + /* write backup grain directory */ + lseek(fd, le64_to_cpu(header.gd_offset) << 9, SEEK_SET); + for (i = 0, tmp = header.gd_offset + gd_size; + i < gt_count; i++, tmp += gt_size) + write(fd, &tmp, sizeof(tmp)); + + /* compose the descriptor */ + real_filename = filename; + if ((temp_str = strrchr(real_filename, '\\')) != NULL) + real_filename = temp_str + 1; + if ((temp_str = strrchr(real_filename, '/')) != NULL) + real_filename = temp_str + 1; + if ((temp_str = strrchr(real_filename, ':')) != NULL) + real_filename = temp_str + 1; + sprintf(desc, desc_template, time(NULL), (unsigned long)total_size, + real_filename, total_size / (63 * 16)); + + /* write the descriptor */ + lseek(fd, le64_to_cpu(header.desc_offset) << 9, SEEK_SET); + write(fd, desc, strlen(desc)); + + close(fd); + return 0; } static void vmdk_close(BlockDriverState *bs) @@ -274,6 +434,6 @@ BlockDriver bdrv_vmdk = { vmdk_read, vmdk_write, vmdk_close, - NULL, /* no create yet */ + vmdk_create, vmdk_is_allocated, }; diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/block.c --- a/tools/ioemu/block.c Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/block.c Tue Jul 25 12:19:05 2006 -0600 @@ -24,8 +24,90 @@ #include "vl.h" #include "block_int.h" +#ifdef _BSD +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/queue.h> +#include <sys/disk.h> +#endif + +#ifdef CONFIG_COCOA +#include <paths.h> +#include <sys/param.h> +#include <IOKit/IOKitLib.h> +#include <IOKit/IOBSD.h> +#include <IOKit/storage/IOMediaBSDClient.h> +#include <IOKit/storage/IOMedia.h> +#include <IOKit/storage/IOCDMedia.h> +//#include <IOKit/storage/IOCDTypes.h> +#include <CoreFoundation/CoreFoundation.h> +#endif + +#ifdef __sun__ +#include <sys/dkio.h> +#endif + static BlockDriverState *bdrv_first; static BlockDriver *first_drv; + +#ifdef CONFIG_COCOA +static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator ); +static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize ); + +kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator ) +{ + kern_return_t kernResult; + mach_port_t masterPort; + CFMutableDictionaryRef classesToMatch; + + kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort ); + if ( KERN_SUCCESS != kernResult ) { + printf( "IOMasterPort returned %d\n", kernResult ); + } + + classesToMatch = IOServiceMatching( kIOCDMediaClass ); + if ( classesToMatch == NULL ) { + printf( "IOServiceMatching returned a NULL dictionary.\n" ); + } else { + CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue ); + } + kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator ); + if ( KERN_SUCCESS != kernResult ) + { + printf( "IOServiceGetMatchingServices returned %d\n", kernResult ); + } + + return kernResult; +} + +kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize ) +{ + io_object_t nextMedia; + kern_return_t kernResult = KERN_FAILURE; + *bsdPath = '\0'; + nextMedia = IOIteratorNext( mediaIterator ); + if ( nextMedia ) + { + CFTypeRef bsdPathAsCFString; + bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 ); + if ( bsdPathAsCFString ) { + size_t devPathLength; + strcpy( bsdPath, _PATH_DEV ); + strcat( bsdPath, "r" ); + devPathLength = strlen( bsdPath ); + if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) { + kernResult = KERN_SUCCESS; + } + CFRelease( bsdPathAsCFString ); + } + IOObjectRelease( nextMedia ); + } + + return kernResult; +} + +#endif void bdrv_register(BlockDriver *bdrv) { @@ -71,21 +153,68 @@ int bdrv_create(BlockDriver *drv, return drv->bdrv_create(filename, size_in_sectors, backing_file, flags); } +#ifdef _WIN32 +void get_tmp_filename(char *filename, int size) +{ + char* p = strrchr(filename, '/'); + + if (p == NULL) + return; + + /* XXX: find a better function */ + tmpnam(p); + *p = '/'; +} +#else +void get_tmp_filename(char *filename, int size) +{ + int fd; + /* XXX: race condition possible */ + pstrcpy(filename, size, "/tmp/vl.XXXXXX"); + fd = mkstemp(filename); + close(fd); +} +#endif + +/* XXX: force raw format if block or character device ? It would + simplify the BSD case */ static BlockDriver *find_image_format(const char *filename) { int fd, ret, score, score_max; BlockDriver *drv1, *drv; - uint8_t buf[1024]; + uint8_t *buf; + size_t bufsize = 1024; fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); - if (fd < 0) - return NULL; - ret = read(fd, buf, sizeof(buf)); - if (ret < 0) { + if (fd < 0) { + buf = NULL; + ret = 0; + } else { +#ifdef DIOCGSECTORSIZE + { + unsigned int sectorsize = 512; + if (!ioctl(fd, DIOCGSECTORSIZE, §orsize) && + sectorsize > bufsize) + bufsize = sectorsize; + } +#endif +#ifdef CONFIG_COCOA + u_int32_t blockSize = 512; + if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) { + bufsize = blockSize; + } +#endif + buf = qemu_malloc(bufsize); + if (!buf) + return NULL; + ret = read(fd, buf, bufsize); + if (ret < 0) { + close(fd); + qemu_free(buf); + return NULL; + } close(fd); - return NULL; - } - close(fd); + } drv = NULL; score_max = 0; @@ -96,11 +225,38 @@ static BlockDriver *find_image_format(co drv = drv1; } } + qemu_free(buf); return drv; } int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot) { +#ifdef CONFIG_COCOA + if ( strncmp( filename, "/dev/cdrom", 10 ) == 0 ) { + kern_return_t kernResult; + io_iterator_t mediaIterator; + char bsdPath[ MAXPATHLEN ]; + int fd; + + kernResult = FindEjectableCDMedia( &mediaIterator ); + kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) ); + + if ( bsdPath[ 0 ] != '\0' ) { + strcat(bsdPath,"s0"); + /* some CDs don't have a partition 0 */ + fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE); + if (fd < 0) { + bsdPath[strlen(bsdPath)-1] = '1'; + } else { + close(fd); + } + filename = bsdPath; + } + + if ( mediaIterator ) + IOObjectRelease( mediaIterator ); + } +#endif return bdrv_open2(bs, filename, snapshot, NULL); } @@ -108,11 +264,41 @@ int bdrv_open2(BlockDriverState *bs, con BlockDriver *drv) { int ret; + char tmp_filename[1024]; bs->read_only = 0; bs->is_temporary = 0; bs->encrypted = 0; - + + if (snapshot) { + BlockDriverState *bs1; + int64_t total_size; + + /* if snapshot, we create a temporary backing file and open it + instead of opening 'filename' directly */ + + /* if there is a backing file, use it */ + bs1 = bdrv_new(""); + if (!bs1) { + return -1; + } + if (bdrv_open(bs1, filename, 0) < 0) { + bdrv_delete(bs1); + return -1; + } + total_size = bs1->total_sectors; + bdrv_delete(bs1); + + get_tmp_filename(tmp_filename, sizeof(tmp_filename)); + /* XXX: use cow for linux as it is more efficient ? */ + if (bdrv_create(&bdrv_qcow, tmp_filename, + total_size, filename, 0) < 0) { + return -1; + } + filename = tmp_filename; + bs->is_temporary = 1; + } + pstrcpy(bs->filename, sizeof(bs->filename), filename); if (!drv) { drv = find_image_format(filename); @@ -218,6 +404,10 @@ int bdrv_commit(BlockDriverState *bs) i += n; } } + + if (bs->drv->bdrv_make_empty) + return bs->drv->bdrv_make_empty(bs); + return 0; } @@ -268,6 +458,9 @@ int bdrv_write(BlockDriverState *bs, int return -1; if (bs->read_only) return -1; + if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) { + memcpy(bs->boot_sector_data, buf, 512); + } return bs->drv->bdrv_write(bs, sector_num, buf, nb_sectors); } @@ -301,6 +494,11 @@ void bdrv_set_type_hint(BlockDriverState type == BDRV_TYPE_FLOPPY)); } +void bdrv_set_translation_hint(BlockDriverState *bs, int translation) +{ + bs->translation = translation; +} + void bdrv_get_geometry_hint(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs) { @@ -312,6 +510,11 @@ int bdrv_get_type_hint(BlockDriverState int bdrv_get_type_hint(BlockDriverState *bs) { return bs->type; +} + +int bdrv_get_translation_hint(BlockDriverState *bs) +{ + return bs->translation; } int bdrv_is_removable(BlockDriverState *bs) @@ -449,7 +652,6 @@ void bdrv_info(void) } } - /**************************************************************/ /* RAW block driver */ @@ -467,6 +669,13 @@ static int raw_open(BlockDriverState *bs BDRVRawState *s = bs->opaque; int fd; int64_t size; +#ifdef _BSD + struct stat sb; +#endif +#ifdef __sun__ + struct dk_minfo minfo; + int rv; +#endif fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE); if (fd < 0) { @@ -475,7 +684,38 @@ static int raw_open(BlockDriverState *bs return -1; bs->read_only = 1; } - size = lseek(fd, 0, SEEK_END); +#ifdef _BSD + if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) { +#ifdef DIOCGMEDIASIZE + if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size)) +#endif +#ifdef CONFIG_COCOA + size = LONG_LONG_MAX; +#else + size = lseek(fd, 0LL, SEEK_END); +#endif + } else +#endif +#ifdef __sun__ + /* + * use the DKIOCGMEDIAINFO ioctl to read the size. + */ + rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo ); + if ( rv != -1 ) { + size = minfo.dki_lbsize * minfo.dki_capacity; + } else /* there are reports that lseek on some devices + fails, but irc discussion said that contingency + on contingency was overkill */ +#endif + { + size = lseek(fd, 0, SEEK_END); + } +#ifdef _WIN32 + /* On Windows hosts it can happen that we're unable to get file size + for CD-ROM raw device (it's inherent limitation of the CDFS driver). */ + if (size == -1) + size = LONG_LONG_MAX; +#endif bs->total_sectors = size / 512; s->fd = fd; return 0; @@ -544,6 +784,14 @@ void bdrv_init(void) void bdrv_init(void) { bdrv_register(&bdrv_raw); +#ifndef _WIN32 + bdrv_register(&bdrv_cow); +#endif bdrv_register(&bdrv_qcow); + bdrv_register(&bdrv_vmdk); bdrv_register(&bdrv_cloop); -} + bdrv_register(&bdrv_dmg); + bdrv_register(&bdrv_bochs); + bdrv_register(&bdrv_vpc); + bdrv_register(&bdrv_vvfat); +} diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/block_int.h --- a/tools/ioemu/block_int.h Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/block_int.h Tue Jul 25 12:19:05 2006 -0600 @@ -39,6 +39,7 @@ struct BlockDriver { int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum); int (*bdrv_set_key)(BlockDriverState *bs, const char *key); + int (*bdrv_make_empty)(BlockDriverState *bs); struct BlockDriver *next; }; @@ -68,10 +69,12 @@ struct BlockDriverState { /* NOTE: the following infos are only hints for real hardware drivers. They are not used by the block driver */ - int cyls, heads, secs; + int cyls, heads, secs, translation; int type; char device_name[32]; BlockDriverState *next; }; +void get_tmp_filename(char *filename, int size); + #endif /* BLOCK_INT_H */ diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/configure --- a/tools/ioemu/configure Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/configure Tue Jul 25 12:19:05 2006 -0600 @@ -25,14 +25,18 @@ host_cc="gcc" host_cc="gcc" ar="ar" make="make" +install="install" strip="strip" cpu=`uname -m` -target_list="target-i386-dm" +target_list="" case "$cpu" in i386|i486|i586|i686|i86pc|BePC) cpu="i386" ;; - armv4l) + armv*b) + cpu="armv4b" + ;; + armv*l) cpu="armv4l" ;; alpha) @@ -47,7 +51,7 @@ case "$cpu" in s390) cpu="s390" ;; - sparc) + sparc|sun4[muv]) cpu="sparc" ;; sparc64) @@ -60,7 +64,7 @@ case "$cpu" in cpu="m68k" ;; x86_64|amd64) - cpu="amd64" + cpu="x86_64" libdir="lib64" ;; *) @@ -75,19 +79,40 @@ slirp="no" slirp="no" adlib="no" oss="no" +dsound="no" +coreaudio="no" +alsa="no" fmod="no" fmod_lib="" fmod_inc="" +bsd="no" +linux="no" +kqemu="no" +profiler="no" +kernel_path="" +cocoa="no" +check_gfx="yes" +check_gcc="no" +softmmu="yes" +user="no" +build_docs="no" # OS specific targetos=`uname -s` case $targetos in +CYGWIN*) +mingw32="yes" +CFLAGS="-O2 -mno-cygwin" +;; MINGW32*) mingw32="yes" ;; FreeBSD) bsd="yes" oss="yes" +if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then + kqemu="yes" +fi ;; NetBSD) bsd="yes" @@ -101,52 +126,73 @@ bsd="yes" bsd="yes" darwin="yes" ;; -*) +SunOS) +solaris="yes" +;; +*) oss="yes" +linux="yes" +user="yes" +if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then + kqemu="yes" +fi ;; esac if [ "$bsd" = "yes" ] ; then - if [ ! "$darwin" = "yes" ] ; then + if [ "$darwin" != "yes" ] ; then make="gmake" fi - target_list="i386-softmmu ppc-softmmu sparc-softmmu" +fi + +if [ "$solaris" = "yes" ] ; then + make="gmake" + install="ginstall" + solarisrev=`uname -r | cut -f2 -d.` fi # find source path -# XXX: we assume an absolute path is given when launching configure, -# except in './configure' case. -source_path=${0%configure} -source_path=${source_path%/} -source_path_used="yes" -if test -z "$source_path" -o "$source_path" = "." ; then +source_path=`dirname "$0"` +if [ -z "$source_path" ]; then source_path=`pwd` +else + source_path=`cd "$source_path"; pwd` +fi +if test "$source_path" = `pwd` ; then source_path_used="no" +else + source_path_used="yes" fi for opt do + optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'` case "$opt" in - --prefix=*) prefix=`echo $opt | cut -d '=' -f 2` - ;; - --interp-prefix=*) interp_prefix=`echo $opt | cut -d '=' -f 2` - ;; - --source-path=*) source_path=`echo $opt | cut -d '=' -f 2` - ;; - --cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2` - ;; - --cc=*) cc=`echo $opt | cut -d '=' -f 2` - ;; - --make=*) make=`echo $opt | cut -d '=' -f 2` - ;; - --extra-cflags=*) CFLAGS="${opt#--extra-cflags=}" - ;; - --extra-ldflags=*) LDFLAGS="${opt#--extra-ldflags=}" - ;; - --extra-libs=*) extralibs=${opt#--extra-libs=} - ;; - --cpu=*) cpu=`echo $opt | cut -d '=' -f 2` - ;; - --target-list=*) target_list=${opt#--target-list=} + --help|-h) show_help=yes + ;; + --prefix=*) prefix="$optarg" + ;; + --interp-prefix=*) interp_prefix="$optarg" + ;; + --source-path=*) source_path="$optarg" + source_path_used="yes" + ;; + --cross-prefix=*) cross_prefix="$optarg" + ;; + --cc=*) cc="$optarg" + ;; + --host-cc=*) host_cc="$optarg" + ;; + --make=*) make="$optarg" + ;; + --install=*) install="$optarg" + ;; + --extra-cflags=*) CFLAGS="$optarg" + ;; + --extra-ldflags=*) LDFLAGS="$optarg" + ;; + --cpu=*) cpu="$optarg" + ;; + --target-list=*) target_list="$optarg" ;; --enable-gprof) gprof="yes" ;; @@ -154,20 +200,44 @@ for opt do ;; --disable-sdl) sdl="no" ;; + --enable-coreaudio) coreaudio="yes" + ;; + --enable-alsa) alsa="yes" + ;; + --enable-dsound) dsound="yes" + ;; --enable-fmod) fmod="yes" ;; - --fmod-lib=*) fmod_lib=${opt#--fmod-lib=} - ;; - --fmod-inc=*) fmod_inc=${opt#--fmod-inc=} - ;; - --disable-vnc) vnc="no" + --fmod-lib=*) fmod_lib="$optarg" + ;; + --fmod-inc=*) fmod_inc="$optarg" ;; --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" - ;; + ;; --disable-slirp) slirp="no" - ;; + ;; --enable-adlib) adlib="yes" - ;; + ;; + --disable-kqemu) kqemu="no" + ;; + --enable-profiler) profiler="yes" + ;; + --kernel-path=*) kernel_path="$optarg" + ;; + --enable-cocoa) cocoa="yes" ; coreaudio="yes" ; sdl="no" + ;; + --disable-gfx-check) check_gfx="no" + ;; + --disable-gcc-check) check_gcc="no" + ;; + --disable-system) softmmu="no" + ;; + --enable-system) softmmu="yes" + ;; + --disable-user) user="no" + ;; + --enable-user) user="yes" + ;; esac done @@ -176,16 +246,130 @@ if test -z "$CFLAGS"; then CFLAGS="-O2" fi +if test x"$show_help" = x"yes" ; then +cat << EOF + +Usage: configure [options] +Options: [defaults in brackets after descriptions] + +EOF +echo "Standard options:" +echo " --help print this message" +echo " --prefix=PREFIX install in PREFIX [$prefix]" +echo " --interp-prefix=PREFIX where to find shared libraries, etc." +echo " use %M for cpu name [$interp_prefix]" +echo " --target-list=LIST set target list [$target_list]" +echo "" +echo "kqemu kernel acceleration support:" +echo " --disable-kqemu disable kqemu support" +echo " --kernel-path=PATH set the kernel path (configure probes it)" +echo "" +echo "Advanced options (experts only):" +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 " --make=MAKE use specified make [$make]" +echo " --install=INSTALL use specified install [$install]" +echo " --static enable static build [$static]" +echo " --enable-cocoa enable COCOA (Mac OS X only)" +echo " --enable-mingw32 enable Win32 cross compilation with mingw32" +echo " --enable-adlib enable Adlib emulation" +echo " --enable-coreaudio enable Coreaudio audio driver" +echo " --enable-alsa enable ALSA audio driver" +echo " --enable-fmod enable FMOD audio driver" +echo " --enabled-dsound enable DirectSound audio driver" +echo " --enable-system enable all system emulation targets" +echo " --disable-system disable all system emulation targets" +echo " --enable-user enable all linux usermode emulation targets" +echo " --disable-user disable all linux usermode emulation targets" +echo " --fmod-lib path to FMOD library" +echo " --fmod-inc path to FMOD includes" +echo "" +echo "NOTE: The object files are build at the place where configure is launched" +exit 1 +fi + cc="${cross_prefix}${cc}" ar="${cross_prefix}${ar}" strip="${cross_prefix}${strip}" +if [ ! -x "`which $cc`" ] ; then + echo "Compiler $cc could not be found" + exit +fi + if test "$mingw32" = "yes" ; then - target_list="i386-softmmu ppc-softmmu sparc-softmmu" + linux="no" EXESUF=".exe" gdbstub="no" oss="no" -fi + if [ "$cpu" = "i386" ] ; then + kqemu="yes" + fi +fi + +# +# Solaris specific configure tool chain decisions +# +if test "$solaris" = "yes" ; then + # + # gcc for solaris 10/fcs in /usr/sfw/bin doesn't compile qemu correctly + # override the check with --disable-gcc-check + # + if test "$solarisrev" -eq 10 -a "$check_gcc" = "yes" ; then + solgcc=`which $cc` + if test "$solgcc" = "/usr/sfw/bin/gcc" ; then + echo "Solaris 10/FCS gcc in /usr/sfw/bin will not compiled qemu correctly." + echo "please get gcc-3.4.3 or later, from www.blastwave.org using pkg-get -i gcc3" + echo "or get the latest patch from SunSolve for gcc" + exit 1 + fi + fi + solinst=`which $install 2> /dev/null | /usr/bin/grep -v "no $install in"` + if test -z "$solinst" ; then + echo "Solaris install program not found. Use --install=/usr/ucb/install or" + echo "install fileutils from www.blastwave.org using pkg-get -i fileutils" + echo "to get ginstall which is used by default (which lives in /opt/csw/bin)" + exit 1 + fi + if test "$solinst" = "/usr/sbin/install" ; then + echo "Error: Solaris /usr/sbin/install is not an appropriate install program." + echo "try ginstall from the GNU fileutils available from www.blastwave.org" + echo "using pkg-get -i fileutils, or use --install=/usr/ucb/install" + exit 1 + fi + sol_ar=`which ar 2> /dev/null | /usr/bin/grep -v "no ar in"` + if test -z "$sol_ar" ; then + echo "Error: No path includes ar" + if test -f /usr/ccs/bin/ar ; then + echo "Add /usr/ccs/bin to your path and rerun configure" + fi + exit 1 + fi +fi + + +if test -z "$target_list" ; then +# these targets are portable + if [ "$softmmu" = "yes" ] ; then + target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu arm-softmmu" + fi +# the following are Linux specific + if [ "$user" = "yes" ] ; then + target_list="i386-user arm-user armeb-user sparc-user ppc-user mips-user mipsel-user $target_list" + fi +# the i386-dm target + target_list="i386-dm" +else + target_list=`echo "$target_list" | sed -e 's/,/ /g'` +fi +if test -z "$target_list" ; then + echo "No targets enabled" + exit 1 +fi + +kqemu="no" if test -z "$cross_prefix" ; then @@ -194,8 +378,8 @@ cat > $TMPC << EOF cat > $TMPC << EOF #include <inttypes.h> int main(int argc, char ** argv){ - volatile uint32_t i=0x01234567; - return (*((uint8_t*)(&i))) == 0x67; + volatile uint32_t i=0x01234567; + return (*((uint8_t*)(&i))) == 0x67; } EOF @@ -208,10 +392,16 @@ else else # if cross compiling, cannot launch a program, so make a static guess -if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64" -o "$cpu" = "m68k"; then +if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64" -o "$cpu" = "m68k" -o "$cpu" = "armv4b"; then bigendian="yes" fi +fi + +# host long bits test +hostlongbits="32" +if test "$cpu" = "sparc64" -o "$cpu" = "ia64" -o "$cpu" = "x86_64" -o "$cpu" = "alpha"; then + hostlongbits="64" fi # check gcc options support @@ -225,40 +415,21 @@ if $cc -fno-reorder-blocks -fno-optimize have_gcc3_options="yes" fi -########################################## -# VNC probe - -if test -z "$vnc"; then - -if libvncserver-config --version > /dev/null 2>&1; then - vnc=yes -else - vnc=no -fi - -fi - -if test "$vnc" = "yes" ; then - -# check for eager event handling -cat > $TMPC <<EOF -#include "rfb/rfb.h" -int main(void) { - rfbScreenInfoPtr screen; - - screen->handleEventsEagerly = 1; -} +# Check for gcc4, error if pre-gcc4 +if test "$check_gcc" = "yes" ; then + cat > $TMPC <<EOF +#if __GNUC__ < 4 +#error gcc3 +#endif +int main(){return 0;} EOF - -if $cc `libvncserver-config --cflags` -o $TMPO $TMPC 2> /dev/null ; then - have_eager_events="yes" -else - echo "!!" - echo "!! Slow VNC mouse, LibVNCServer doesn't support eager events" - echo "!!" - have_eager_events="no" -fi - + if $cc -o $TMPO $TMPC 2>/dev/null ; then + echo "ERROR: \"$cc\" looks like gcc 4.x" + echo "QEMU is known to have problems when compiled with gcc 4.x" + echo "It is recommended that you use gcc 3.x to build QEMU" + echo "To use this compiler anyway, configure with --disable-gcc-check" + exit 1; + fi fi ########################################## @@ -312,45 +483,15 @@ fi # cross compilation fi # cross compilation fi # -z $sdl -if test x"$1" = x"-h" -o x"$1" = x"--help" ; then -cat << EOF - -Usage: configure [options] -Options: [defaults in brackets after descriptions] - -EOF -echo "Standard options:" -echo " --help print this message" -echo " --prefix=PREFIX install in PREFIX [$prefix]" -echo " --interp-prefix=PREFIX where to find shared libraries, etc." -echo " use %M for cpu name [$interp_prefix]" -echo " --target-list=LIST set target list [$target_list]" -echo " --disable-vnc disable vnc support (else configure checks" -echo " for libvncserver-config in your PATH)" -echo "" -echo "Advanced options (experts only):" -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 " --make=MAKE use specified make [$make]" -echo " --static enable static build [$static]" -echo " --enable-mingw32 enable Win32 cross compilation with mingw32" -echo " --enable-fmod enable FMOD audio output driver" -echo " --fmod-lib path to FMOD library" -echo " --fmod-inc path to FMOD includes" -echo "" -echo "NOTE: The object files are build at the place where configure is launched" -exit 1 -fi - -#installroot=$source_path/../../dist/install -installroot= +# Check if tools are available to build documentation. +if [ -x "`which texi2html`" ] && [ -x "`which pod2man`" ]; then + build_docs="yes" +fi if test "$mingw32" = "yes" ; then if test -z "$prefix" ; then prefix="/c/Program Files/Qemu" fi - mandir="$prefix" datadir="$prefix" docdir="$prefix" @@ -358,13 +499,13 @@ configdir="" configdir="" else if test -z "$prefix" ; then - prefix="usr/local" -fi -mandir="$installroot/$prefix/share/man" -datadir="$installroot/$prefix/share/xen/qemu" -docdir="$installroot/$prefix/share/doc/qemu" -bindir="$installroot/$prefix/bin" -configdir="$installroot/etc/xen" + prefix="/usr/local" +fi +mandir="$prefix/share/man" +datadir="$prefix/share/xen/qemu" +docdir="$prefix/share/doc/qemu" +bindir="$prefix/$libdir/xen/bin" +configdir="/etc/xen" fi echo "Install prefix $prefix" @@ -372,39 +513,60 @@ echo "binary directory $bindir" echo "binary directory $bindir" if test "$mingw32" = "no" ; then echo "Manual directory $mandir" +echo "ELF interp prefix $interp_prefix" fi echo "Source path $source_path" echo "C compiler $cc" +echo "Host C compiler $host_cc" echo "make $make" +echo "install $install" echo "host CPU $cpu" echo "host big endian $bigendian" echo "target list $target_list" echo "gprof enabled $gprof" +echo "profiler $profiler" echo "static build $static" -echo "VNC support $vnc" +if test "$darwin" = "yes" ; then + echo "Cocoa support $cocoa" +fi echo "SDL support $sdl" -echo "SDL static link $sdl_static" +if test "$sdl" != "no" ; then + echo "SDL static link $sdl_static" +fi echo "mingw32 support $mingw32" echo "Adlib support $adlib" -echo -n "FMOD support $fmod" -if test $fmod = "yes"; then - echo -n " (lib='$fmod_lib' include='$fmod_inc')" -fi -echo "" +echo "CoreAudio support $coreaudio" +echo "ALSA support $alsa" +echo "DSound support $dsound" +if test "$fmod" = "yes"; then + if test -z $fmod_lib || test -z $fmod_inc; then + echo + echo "Error: You must specify path to FMOD library and headers" + echo "Example: --fmod-inc=/path/include/fmod --fmod-lib=/path/lib/libfmod-3.74.so" + echo + exit 1 + fi + fmod_support=" (lib='$fmod_lib' include='$fmod_inc')" +else + fmod_support="" +fi +echo "FMOD support $fmod $fmod_support" +echo "kqemu support $kqemu" +echo "Documentation $build_docs" if test $sdl_too_old = "yes"; then -echo "-> Your SDL version is too old - please upgrade to have FFplay/SDL support" -fi -if test "$sdl_static" = "no"; then - echo "WARNING: cannot compile statically with SDL - qemu-fast won't have a graphical output" -fi - +echo "-> Your SDL version is too old - please upgrade to have SDL support" +fi +#if test "$sdl_static" = "no"; then +# echo "WARNING: cannot compile statically with SDL - qemu-fast won't have a graphical output" +#fi config_mak="config-host.mak" config_h="config-host.h" #echo "Creating $config_mak and $config_h" echo "# Automatically generated by configure - do not modify" > $config_mak +echo "# Configured with: $0 $@" >> $config_mak echo "/* Automatically generated by configure - do not modify */" > $config_h echo "prefix=$prefix" >> $config_mak @@ -415,22 +577,63 @@ echo "configdir=$configdir" >> $config_m echo "configdir=$configdir" >> $config_mak echo "LIBDIR=$libdir" >> $config_mak echo "#define CONFIG_QEMU_SHAREDIR \"$datadir\"" >> $config_h -#echo "MAKE=$make" >> $config_mak -#echo "CC=$cc" >> $config_mak -#if test "$have_gcc3_options" = "yes" ; then -# echo "HAVE_GCC3_OPTIONS=yes" >> $config_mak -#fi -#echo "HOST_CC=$host_cc" >> $config_mak -#echo "AR=$ar" >> $config_mak -#echo "STRIP=$strip -s -R .comment -R .note" >> $config_mak -#echo "CFLAGS=$CFLAGS" >> $config_mak -#echo "LDFLAGS=$LDFLAGS" >> $config_mak -#echo "EXESUF=$EXESUF" >> $config_mak - +echo "MAKE=$make" >> $config_mak +echo "INSTALL=$install" >> $config_mak +echo "CC=$cc" >> $config_mak +if test "$have_gcc3_options" = "yes" ; then + echo "HAVE_GCC3_OPTIONS=yes" >> $config_mak +fi +echo "HOST_CC=$host_cc" >> $config_mak +echo "AR=$ar" >> $config_mak +echo "STRIP=$strip -s -R .comment -R .note" >> $config_mak +echo "CFLAGS=$CFLAGS" >> $config_mak +echo "LDFLAGS=$LDFLAGS" >> $config_mak +echo "EXESUF=$EXESUF" >> $config_mak +if test "$cpu" = "i386" ; then + echo "ARCH=i386" >> $config_mak + echo "#define HOST_I386 1" >> $config_h +elif test "$cpu" = "x86_64" ; then + echo "ARCH=x86_64" >> $config_mak + echo "#define HOST_X86_64 1" >> $config_h +elif test "$cpu" = "armv4b" ; then + echo "ARCH=arm" >> $config_mak + echo "#define HOST_ARM 1" >> $config_h +elif test "$cpu" = "armv4l" ; then + echo "ARCH=arm" >> $config_mak + echo "#define HOST_ARM 1" >> $config_h +elif test "$cpu" = "powerpc" ; then + echo "ARCH=ppc" >> $config_mak + echo "#define HOST_PPC 1" >> $config_h +elif test "$cpu" = "mips" ; then + echo "ARCH=mips" >> $config_mak + echo "#define HOST_MIPS 1" >> $config_h +elif test "$cpu" = "s390" ; then + echo "ARCH=s390" >> $config_mak + echo "#define HOST_S390 1" >> $config_h +elif test "$cpu" = "alpha" ; then + echo "ARCH=alpha" >> $config_mak + echo "#define HOST_ALPHA 1" >> $config_h +elif test "$cpu" = "sparc" ; then + echo "ARCH=sparc" >> $config_mak + echo "#define HOST_SPARC 1" >> $config_h +elif test "$cpu" = "sparc64" ; then + echo "ARCH=sparc64" >> $config_mak + echo "#define HOST_SPARC64 1" >> $config_h +elif test "$cpu" = "ia64" ; then + echo "ARCH=ia64" >> $config_mak + echo "#define HOST_IA64 1" >> $config_h +elif test "$cpu" = "m68k" ; then + echo "ARCH=m68k" >> $config_mak + echo "#define HOST_M68K 1" >> $config_h +else + echo "Unsupported CPU" + exit 1 +fi if test "$bigendian" = "yes" ; then echo "WORDS_BIGENDIAN=yes" >> $config_mak echo "#define WORDS_BIGENDIAN 1" >> $config_h fi +echo "#define HOST_LONG_BITS $hostlongbits" >> $config_h if test "$mingw32" = "yes" ; then echo "CONFIG_WIN32=yes" >> $config_mak echo "#define CONFIG_WIN32 1" >> $config_h @@ -441,6 +644,10 @@ if test "$darwin" = "yes" ; then echo "CONFIG_DARWIN=yes" >> $config_mak echo "#define CONFIG_DARWIN 1" >> $config_h fi +if test "$solaris" = "yes" ; then + echo "CONFIG_SOLARIS=yes" >> $config_mak + echo "#define HOST_SOLARIS $solarisrev" >> $config_h +fi if test "$gdbstub" = "yes" ; then echo "CONFIG_GDBSTUB=yes" >> $config_mak echo "#define CONFIG_GDBSTUB 1" >> $config_h @@ -453,6 +660,9 @@ if test "$static" = "yes" ; then echo "CONFIG_STATIC=yes" >> $config_mak echo "#define CONFIG_STATIC 1" >> $config_h fi +if test $profiler = "yes" ; then + echo "#define CONFIG_PROFILER 1" >> $config_h +fi if test "$slirp" = "yes" ; then echo "CONFIG_SLIRP=yes" >> $config_mak echo "#define CONFIG_SLIRP 1" >> $config_h @@ -464,6 +674,18 @@ if test "$oss" = "yes" ; then if test "$oss" = "yes" ; then echo "CONFIG_OSS=yes" >> $config_mak echo "#define CONFIG_OSS 1" >> $config_h +fi +if test "$coreaudio" = "yes" ; then + echo "CONFIG_COREAUDIO=yes" >> $config_mak + echo "#define CONFIG_COREAUDIO 1" >> $config_h +fi +if test "$alsa" = "yes" ; then + echo "CONFIG_ALSA=yes" >> $config_mak + echo "#define CONFIG_ALSA 1" >> $config_h +fi +if test "$dsound" = "yes" ; then + echo "CONFIG_DSOUND=yes" >> $config_mak + echo "#define CONFIG_DSOUND 1" >> $config_h fi if test "$fmod" = "yes" ; then echo "CONFIG_FMOD=yes" >> $config_mak @@ -471,15 +693,18 @@ if test "$fmod" = "yes" ; then echo "CONFIG_FMOD_INC=$fmod_inc" >> $config_mak echo "#define CONFIG_FMOD 1" >> $config_h fi -echo -n "VERSION=" >>$config_mak -head $source_path/VERSION >>$config_mak -echo "" >>$config_mak -echo -n "#define QEMU_VERSION \"" >> $config_h -head $source_path/VERSION >> $config_h -echo "\"" >> $config_h +qemu_version=`head $source_path/VERSION` +echo "VERSION=$qemu_version" >>$config_mak +echo "#define QEMU_VERSION \"$qemu_version\"" >> $config_h echo "SRC_PATH=$source_path" >> $config_mak +if [ "$source_path_used" = "yes" ]; then + echo "VPATH=$source_path" >> $config_mak +fi echo "TARGET_DIRS=$target_list" >> $config_mak +if [ "$build_docs" = "yes" ] ; then + echo "BUILD_DOCS=yes" >> $config_mak +fi # XXX: suppress that if [ "$bsd" = "yes" ] ; then @@ -488,30 +713,18 @@ if [ "$bsd" = "yes" ] ; then echo "#define _BSD 1" >> $config_h fi -if test "$vnc" = "yes"; then - echo "CONFIG_VNC=yes" >> $config_mak - vnc_cflags=`libvncserver-config --cflags` - if [ -z $vnc_cflags ]; then - vnc_cflags="/usr/include" - fi - echo "VNC_CFLAGS=$vnc_cflags" >> $config_mak - if test "$have_eager_events" = "yes" ; then - echo "#define VNC_EAGER_EVENTS 1" >> $config_h - fi -fi - -if test "$sdl" = "yes"; then - echo "CONFIG_SDL=yes" >> $config_mak - echo "SDL_CFLAGS=`$sdl_config --cflags`" >> $config_mak -fi - -for target in $target_list; do - +for target in $target_list; do target_dir="$target" config_mak=$target_dir/config.mak config_h=$target_dir/config.h -target_cpu=`echo $target | cut -d '-' -f 2` +target_cpu=`echo $target | cut -d '-' -f 1` +target_bigendian="no" +[ "$target_cpu" = "armeb" ] && target_bigendian=yes +[ "$target_cpu" = "sparc" ] && target_bigendian=yes +[ "$target_cpu" = "sparc64" ] && target_bigendian=yes [ "$target_cpu" = "ppc" ] && target_bigendian=yes +[ "$target_cpu" = "ppc64" ] && target_bigendian=yes +[ "$target_cpu" = "mips" ] && target_bigendian=yes target_softmmu="no" if expr $target : '.*-softmmu' > /dev/null ; then target_softmmu="yes" @@ -522,17 +735,32 @@ if expr $target : '.*-user' > /dev/null if expr $target : '.*-user' > /dev/null ; then target_user_only="yes" fi + +if test "$target_user_only" = "no" -a "$check_gfx" = "yes" \ + -a "$sdl" = "no" -a "$cocoa" = "no" ; then + echo "ERROR: QEMU requires SDL or Cocoa for graphical output" + echo "To build QEMU without graphical output configure with --disable-gfx-check" + echo "Note that this will disable all output from the virtual graphics card." + exit 1; +fi + #echo "Creating $config_mak, $config_h and $target_dir/Makefile" mkdir -p $target_dir -if test "$target" = "arm-user" ; then +mkdir -p $target_dir/fpu +if test "$target" = "arm-user" -o "$target" = "armeb-user" ; then mkdir -p $target_dir/nwfpe fi if test "$target_user_only" = "no" ; then mkdir -p $target_dir/slirp fi -#ln -sf $source_path/Makefile.target $target_dir/Makefile +# +# don't use ln -sf as not all "ln -sf" over write the file/link +# +rm -f $target_dir/Makefile +ln -s ../Makefile.target $target_dir/Makefile + echo "# Automatically generated by configure - do not modify" > $config_mak echo "/* Automatically generated by configure - do not modify */" > $config_h @@ -541,13 +769,64 @@ echo "include ../config-host.mak" >> $co echo "include ../config-host.mak" >> $config_mak echo "#include \"../config-host.h\"" >> $config_h -echo "TARGET_ARCH=i386" >> $config_mak -echo "#define TARGET_ARCH \"i386\"" >> $config_h -echo "#define TARGET_I386 1" >> $config_h - interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"` echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h +target_sub= +if expr $target : '.*-dm' > /dev/null ; then + target_sub=-dm +fi +echo "TARGET_SUB=${target_sub}" >> $config_mak + +if test "$target_cpu" = "i386" ; then + echo "TARGET_ARCH=i386" >> $config_mak + echo "#define TARGET_ARCH \"i386\"" >> $config_h + echo "#define TARGET_I386 1" >> $config_h + if test $kqemu = "yes" -a "$target_softmmu" = "yes" -a $cpu = "i386" ; then + echo "#define USE_KQEMU 1" >> $config_h + fi +elif test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" ; then + echo "TARGET_ARCH=arm" >> $config_mak + echo "#define TARGET_ARCH \"arm\"" >> $config_h + echo "#define TARGET_ARM 1" >> $config_h +elif test "$target_cpu" = "sparc" ; then + echo "TARGET_ARCH=sparc" >> $config_mak + echo "#define TARGET_ARCH \"sparc\"" >> $config_h + echo "#define TARGET_SPARC 1" >> $config_h +elif test "$target_cpu" = "sparc64" ; then + echo "TARGET_ARCH=sparc64" >> $config_mak + echo "#define TARGET_ARCH \"sparc64\"" >> $config_h + echo "#define TARGET_SPARC 1" >> $config_h + echo "#define TARGET_SPARC64 1" >> $config_h +elif test "$target_cpu" = "ppc" ; then + echo "TARGET_ARCH=ppc" >> $config_mak + echo "#define TARGET_ARCH \"ppc\"" >> $config_h + echo "#define TARGET_PPC 1" >> $config_h +elif test "$target_cpu" = "ppc64" ; then + echo "TARGET_ARCH=ppc64" >> $config_mak + echo "#define TARGET_ARCH \"ppc64\"" >> $config_h + echo "#define TARGET_PPC 1" >> $config_h + echo "#define TARGET_PPC64 1" >> $config_h +elif test "$target_cpu" = "x86_64" ; then + echo "TARGET_ARCH=x86_64" >> $config_mak + echo "#define TARGET_ARCH \"x86_64\"" >> $config_h + echo "#define TARGET_I386 1" >> $config_h + echo "#define TARGET_X86_64 1" >> $config_h + if test $kqemu = "yes" -a "$target_softmmu" = "yes" -a $cpu = "x86_64" ; then + echo "#define USE_KQEMU 1" >> $config_h + fi +elif test "$target_cpu" = "mips" -o "$target_cpu" = "mipsel" ; then + echo "TARGET_ARCH=mips" >> $config_mak + echo "#define TARGET_ARCH \"mips\"" >> $config_h + echo "#define TARGET_MIPS 1" >> $config_h +elif test "$target_cpu" = "sh4" ; then + echo "TARGET_ARCH=sh4" >> $config_mak + echo "#define TARGET_ARCH \"sh4\"" >> $config_h + echo "#define TARGET_SH4 1" >> $config_h +else + echo "Unsupported target CPU" + exit 1 +fi if test "$target_bigendian" = "yes" ; then echo "TARGET_WORDS_BIGENDIAN=yes" >> $config_mak echo "#define TARGET_WORDS_BIGENDIAN 1" >> $config_h @@ -561,18 +840,17 @@ if test "$target_user_only" = "yes" ; th echo "#define CONFIG_USER_ONLY 1" >> $config_h fi +if expr $target : '.*-dm' > /dev/null ; then + echo "#define CONFIG_DM 1" >> $config_h +fi + +if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" ; then + echo "CONFIG_SOFTFLOAT=yes" >> $config_mak + echo "#define CONFIG_SOFTFLOAT 1" >> $config_h +fi +# sdl defines + if test "$target_user_only" = "no"; then - if test "$vnc" = "yes"; then - echo "#define CONFIG_VNC 1" >> $config_h - echo "CONFIG_VNC=yes" >> $config_mak - echo "VNC_CFLAGS=`libvncserver-config --cflags`" >> $config_mak - echo "VNC_LIBS=`libvncserver-config --libs`" >> $config_mak - fi -fi - -# sdl defines - -if test "$sdl" = "yes" -a "$target_user_only" = "no"; then if test "$target_softmmu" = "no" -o "$static" = "yes"; then sdl1=$sdl_static else @@ -586,12 +864,17 @@ if test "$sdl" = "yes" -a "$target_user_ else echo "SDL_LIBS=`$sdl_config --libs`" >> $config_mak fi - echo -n "SDL_CFLAGS=`$sdl_config --cflags`" >> $config_mak if [ "${aa}" = "yes" ] ; then - echo -n " `aalib-config --cflags`" >> $config_mak ; + echo "SDL_CFLAGS=`$sdl_config --cflags` `aalib-config --cflags`" >> $config_mak + else + echo "SDL_CFLAGS=`$sdl_config --cflags`" >> $config_mak fi - echo "" >> $config_mak - fi + fi +fi + +if test "$cocoa" = "yes" ; then + echo "#define CONFIG_COCOA 1" >> $config_h + echo "CONFIG_COCOA=yes" >> $config_mak fi done # for target in $targets @@ -603,8 +886,10 @@ if test "$source_path_used" = "yes" ; th for dir in $DIRS ; do mkdir -p $dir done + # remove the link and recreate it, as not all "ln -sf" overwrite the link for f in $FILES ; do - ln -sf $source_path/$f $f + rm -f $f + ln -s $source_path/$f $f done fi diff -r 2db50529223e -r f7b43e5c42b9 tools/ioemu/console.c --- a/tools/ioemu/console.c Tue Jul 25 09:51:50 2006 -0600 +++ b/tools/ioemu/console.c Tue Jul 25 12:19:05 2006 -0600 @@ -23,16 +23,26 @@ */ #include "vl.h" +//#define DEBUG_CONSOLE #define DEFAULT_BACKSCROLL 512 #define MAX_CONSOLES 12 #define RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) #define RGB(r, g, b) RGBA(r, g, b, 0xff) +typedef struct TextAttributes { + uint8_t fgcol:4; + uint8_t bgcol:4; + uint8_t bold:1; + uint8_t uline:1; + uint8_t blink:1; + uint8_t invers:1; + uint8_t unvisible:1; +} TextAttributes; + typedef struct TextCell { uint8_t ch; - uint8_t bgcol:4; - uint8_t fgcol:4; + TextAttributes t_attrib; } TextCell; #define MAX_ESC_PARAMS 3 @@ -43,19 +53,27 @@ enum TTYState { TTY_STATE_CSI, }; +/* ??? This is mis-named. + It is used for both text and graphical consoles. */ struct TextConsole { int text_console; /* true if text console */ DisplayState *ds; + /* Graphic console state. */ + vga_hw_update_ptr hw_update; + vga_hw_invalidate_ptr hw_invalidate; + vga_hw_screen_dump_ptr hw_screen_dump; + void *hw; + int g_width, g_height; int width; int height; int total_height; int backscroll_height; - int fgcol; - int bgcol; int x, y; int y_displayed; int y_base; + TextAttributes t_attrib_default; /* default text attributes */ + TextAttributes t_attrib; /* currently active text attributes */ TextCell *cells; enum TTYState state; @@ -70,6 +88,26 @@ static TextConsole *active_console; static TextConsole *active_console; static TextConsole *consoles[MAX_CONSOLES]; static int nb_consoles = 0; + +void vga_hw_update(void) +{ + if (active_console->hw_update) + active_console->hw_update(active_console->hw); +} + +void vga_hw_invalidate(void) +{ + if (active_console->hw_invalidate) + active_console->hw_invalidate(active_console->hw); +} + +void vga_hw_screen_dump(const char *filename) +{ + /* There is currently no was of specifying which screen we want to dump, + so always dump the dirst one. */ + if (consoles[0]->hw_screen_dump) + consoles[0]->hw_screen_dump(consoles[0]->hw, filename); +} /* convert a RGBA color to a color index usable in graphic primitives */ static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba) @@ -221,17 +259,40 @@ static const uint32_t dmask4[4] = { PAT(0xffffffff), }; -static uint32_t color_table[8]; - -static const uint32_t color_table_rgb[8] = { - RGB(0x00, 0x00, 0x00), - RGB(0xff, 0x00, 0x00), - RGB(0x00, 0xff, 0x00), - RGB(0xff, 0xff, 0x00), - RGB(0x00, 0x00, 0xff), - RGB(0xff, 0x00, 0xff), - RGB(0x00, 0xff, 0xff), - RGB(0xff, 0xff, 0xff), +static uint32_t color_table[2][8]; + +enum color_names { + COLOR_BLACK = 0, + COLOR_RED = 1, + COLOR_GREEN = 2, + COLOR_YELLOW = 3, + COLOR_BLUE = 4, + COLOR_MAGENTA = 5, + COLOR_CYAN = 6, + COLOR_WHITE = 7 +}; + +static const uint32_t color_table_rgb[2][8] = { + { /* dark */ + RGB(0x00, 0x00, 0x00), /* black */ + RGB(0xaa, 0x00, 0x00), /* red */ + RGB(0x00, 0xaa, 0x00), /* green */ + RGB(0xaa, 0xaa, 0x00), /* yellow */ + RGB(0x00, 0x00, 0xaa), /* blue */ + RGB(0xaa, 0x00, 0xaa), /* magenta */ + RGB(0x00, 0xaa, 0xaa), /* cyan */ + RGB(0xaa, 0xaa, 0xaa), /* white */ + }, + { /* bright */ + RGB(0x00, 0x00, 0x00), /* black */ + RGB(0xff, 0x00, 0x00), /* red */ + RGB(0x00, 0xff, 0x00), /* green */ + RGB(0xff, 0xff, 0x00), /* yellow */ + RGB(0x00, 0x00, 0xff), /* blue */ + RGB(0xff, 0x00, 0xff), /* magenta */ + RGB(0x00, 0xff, 0xff), /* cyan */ + RGB(0xff, 0xff, 0xff), /* white */ + } }; static inline unsigned int col_expand(DisplayState *ds, unsigned int col) @@ -251,14 +312,60 @@ static inline unsigned int col_expand(Di return col; } +#ifdef DEBUG_CONSOLE +static void console_print_text_attributes(TextAttributes *t_attrib, char ch) +{ + if (t_attrib->bold) { + printf("b"); + } else { + printf(" "); + } + if (t_attrib->uline) { + printf("u"); + } else { + printf(" "); + } + if (t_attrib->blink) { + printf("l"); + } else { + printf(" "); + } + if (t_attrib->invers) { + printf("i"); + } else { + printf(" "); + } + if (t_attrib->unvisible) { + printf("n"); + } else { + printf(" "); + } + + printf(" fg: %d bg: %d ch:'%2X' '%c'\n", t_attrib->fgcol, t_attrib->bgcol, ch, ch); +} +#endif static void vga_putcharxy(DisplayState *ds, int x, int y, int ch, - unsigned int fgcol, unsigned int bgcol) + TextAttributes *t_attrib) { uint8_t *d; const uint8_t *font_ptr; unsigned int font_data, linesize, xorcol, bpp; int i; + unsigned int fgcol, bgcol; + +#ifdef DEBUG_CONSOLE + printf("x: %2i y: %2i", x, y); + console_print_text_attributes(t_attrib, ch); +#endif + + if (t_attrib->invers) { + bgcol = color_table[t_attrib->bold][t_attrib->fgcol]; + fgcol = color_table[t_attrib->bold][t_attrib->bgcol]; + } else { + fgcol = color_table[t_attrib->bold][t_attrib->fgcol]; + bgcol = color_table[t_attrib->bold][t_attrib->bgcol]; + } bpp = (ds->depth + 7) >> 3; d = ds->data + @@ -270,6 +377,10 @@ static void vga_putcharxy(DisplayState * case 8: for(i = 0; i < FONT_HEIGHT; i++) { font_data = *font_ptr++; + if (t_attrib->uline + && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) { + font_data = 0xFFFF; + } ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol; ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol; d += linesize; @@ -279,6 +390,10 @@ static void vga_putcharxy(DisplayState * case 15: for(i = 0; i < FONT_HEIGHT; i++) { font_data = *font_ptr++; + if (t_attrib->uline + && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) { + font_data = 0xFFFF; + } ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol; ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol; ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol; @@ -289,6 +404,9 @@ static void vga_putcharxy(DisplayState * case 32: for(i = 0; i < FONT_HEIGHT; i++) { font_data = *font_ptr++; + if (t_attrib->uline && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) { + font_data = 0xFFFF; + } ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol; ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol; ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol; @@ -327,8 +445,7 @@ static void text_console_resize(TextCons } for(x = w1; x < s->width; x++) { c->ch = ' '; - c->fgcol = 7; - c->bgcol = 0; + c->t_attrib = s->t_attrib_default; c++; } } @@ -349,7 +466,7 @@ static void update_xy(TextConsole *s, in if (y2 < s->height) { c = &s->cells[y1 * s->width + x]; vga_putcharxy(s->ds, x, y2, c->ch, - color_table[c->fgcol], color_table[c->bgcol]); + &(c->t_attrib)); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |