[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, &sectorsize) &&
+                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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.