WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-ppc-devel

[XenPPC] [xenppc-unstable] merge with http://xenbits.xensource.com/ext/x

To: xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
Subject: [XenPPC] [xenppc-unstable] merge with http://xenbits.xensource.com/ext/xenppc-unstable.hg
From: Xen patchbot-xenppc-unstable <patchbot-xenppc-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 04 Aug 2006 21:30:47 +0000
Delivery-date: Fri, 04 Aug 2006 14:40:20 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-ppc-devel-request@lists.xensource.com?subject=help>
List-id: Xen PPC development <xen-ppc-devel.lists.xensource.com>
List-post: <mailto:xen-ppc-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ppc-devel>, <mailto:xen-ppc-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ppc-devel>, <mailto:xen-ppc-devel-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-ppc-devel-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
# Node ID 5ecfc7102ccae3252062f685c12e249bbd272fdb
# Parent  a75c389e4a7d23f8ab3345bf8f417d9c2fe471c0
# Parent  7f21d87ec95d093d58bbc05c0b38292202ffe079
merge with http://xenbits.xensource.com/ext/xenppc-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/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/libxc/xc_ia64_stubs.c                                             |  756 
-
 tools/vtpm/tpm_emulator-0.3-x86_64.patch                                |  657 
-
 xen/arch/powerpc/xen.lds                                                |  226 
 xen/include/asm-ia64/linux/asm/asmmacro.h                               |  111 
 .hgignore                                                               |   47 
 Config.mk                                                               |    2 
 README                                                                  |    1 
 buildconfigs/Rules.mk                                                   |   14 
 buildconfigs/conf.linux-native/00_xen_to_native                         |   84 
 buildconfigs/create_config.sh                                           |   50 
 buildconfigs/linux-defconfig_xen0_ia64                                  |   29 
 buildconfigs/linux-defconfig_xen0_x86_32                                |    1 
 buildconfigs/linux-defconfig_xen0_x86_64                                |    1 
 buildconfigs/linux-defconfig_xen_ia64                                   |   29 
 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/x86_32.mk                                                        |    2 
 config/x86_64.mk                                                        |    2 
 docs/src/user.tex                                                       |  180 
 extras/mini-os/mm.c                                                     |    2 
 linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c                        |   21 
 linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c                          |   41 
 linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c                         |    5 
 linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c                      |   23 
 linux-2.6-xen-sparse/arch/ia64/Kconfig                                  |    9 
 linux-2.6-xen-sparse/arch/ia64/kernel/gate.S                            |  488 
 linux-2.6-xen-sparse/arch/ia64/kernel/gate.lds.S                        |  117 
 linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c                        |   77 
 linux-2.6-xen-sparse/arch/ia64/kernel/patch.c                           |  268 
 linux-2.6-xen-sparse/arch/ia64/kernel/setup.c                           |   24 
 linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S                          |   56 
 linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c                         |   20 
 linux-2.6-xen-sparse/arch/ia64/xen/util.c                               |    3 
 linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S                           |   20 
 linux-2.6-xen-sparse/arch/x86_64/Kconfig                                |    2 
 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/core/reboot.c                          |  135 
 linux-2.6-xen-sparse/drivers/xen/netback/interface.c                    |    1 
 linux-2.6-xen-sparse/drivers/xen/netback/loopback.c                     |    1 
 linux-2.6-xen-sparse/drivers/xen/netback/netback.c                      |   11 
 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c                    |    3 
 linux-2.6-xen-sparse/drivers/xen/pciback/Makefile                       |    3 
 linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c                   |   76 
 linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.h                   |   11 
 linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c            |  128 
 linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h            |   35 
 linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c                     |  224 
 linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h                      |    2 
 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/asm-ia64/hypercall.h                       |   18 
 linux-2.6-xen-sparse/include/asm-ia64/xen/privop.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/domctrl/DomU.dts.in                                               |    2 
 tools/domctrl/DomU.sh                                                   |    2 
 tools/examples/Makefile                                                 |    5 
 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/xend-pci-permissive.sxp                                  |   27 
 tools/examples/xend-pci-quirks.sxp                                      |   96 
 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                                                   |  396 
 tools/ioemu/cpu-all.h                                                   |  480 
 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                                                  |  252 
 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                                                  |  206 
 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                                                    |  335 
 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/ioemu-ia64                                          |   86 
 tools/ioemu/patches/qemu-64bit                                          |   95 
 tools/ioemu/patches/qemu-bugfixes                                       |   56 
 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-init-vgabios                                   |   17 
 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                                 |  126 
 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                                              |   37 
 tools/ioemu/patches/shadow-vram                                         |   34 
 tools/ioemu/patches/shared-vram                                         |  129 
 tools/ioemu/patches/support-xm-console                                  |   38 
 tools/ioemu/patches/vnc-access-monitor-vt                               |   34 
 tools/ioemu/patches/vnc-cleanup                                         |   65 
 tools/ioemu/patches/vnc-fixes                                           |  336 
 tools/ioemu/patches/vnc-start-vncviewer                                 |   69 
 tools/ioemu/patches/vnc-title-domain-name                               |   19 
 tools/ioemu/patches/xen-build                                           |  179 
 tools/ioemu/patches/xen-domain-name                                     |   64 
 tools/ioemu/patches/xen-domid                                           |   38 
 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                                        |   90 
 tools/ioemu/target-i386-dm/exec-dm.c                                    |  536 
 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                                                        | 4459 
+++++-
 tools/ioemu/vl.h                                                        |  540 
 tools/ioemu/vnc.c                                                       | 1649 
+-
 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                                                    |    7 
 tools/libxc/ia64/Makefile                                               |    5 
 tools/libxc/ia64/xc_ia64_hvm_build.c                                    |  673 
+
 tools/libxc/ia64/xc_ia64_linux_restore.c                                |  320 
 tools/libxc/ia64/xc_ia64_linux_save.c                                   |  509 
 tools/libxc/ia64/xc_ia64_stubs.c                                        |  106 
 tools/libxc/xc_hvm_build.c                                              |   32 
 tools/libxc/xc_linux_build.c                                            |   67 
 tools/libxc/xc_private.c                                                |    4 
 tools/libxc/xenctrl.h                                                   |    3 
 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/pci.py                                            |   97 
 tools/python/xen/util/security.py                                       |   98 
 tools/python/xen/xend/XendDomain.py                                     |   30 
 tools/python/xen/xend/XendDomainInfo.py                                 |    9 
 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/xend/server/pciif.py                                   |    7 
 tools/python/xen/xend/server/pciquirk.py                                |  145 
 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/xenstat/libxenstat/src/xenstat.c                                  |    1 
 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/arch/ia64/Makefile                                                  |   14 
 xen/arch/ia64/asm-offsets.c                                             |   11 
 xen/arch/ia64/linux-xen/Makefile                                        |    2 
 xen/arch/ia64/linux-xen/README.origin                                   |    2 
 xen/arch/ia64/linux-xen/entry.S                                         |   15 
 xen/arch/ia64/linux-xen/iosapic.c                                       |    8 
 xen/arch/ia64/linux-xen/mca.c                                           | 1600 
++
 xen/arch/ia64/linux-xen/mca_asm.S                                       |  970 
+
 xen/arch/ia64/linux-xen/minstate.h                                      |   46 
 xen/arch/ia64/linux-xen/tlb.c                                           |    4 
 xen/arch/ia64/linux-xen/unwind.c                                        |   22 
 xen/arch/ia64/tools/README.RunVT                                        |   95 
 xen/arch/ia64/vmx/mmio.c                                                |   11 
 xen/arch/ia64/vmx/pal_emul.c                                            |  591 
 xen/arch/ia64/vmx/vlsapic.c                                             |   49 
 xen/arch/ia64/vmx/vmmu.c                                                |    8 
 xen/arch/ia64/vmx/vmx_entry.S                                           |   64 
 xen/arch/ia64/vmx/vmx_init.c                                            |   80 
 xen/arch/ia64/vmx/vmx_interrupt.c                                       |    2 
 xen/arch/ia64/vmx/vmx_ivt.S                                             |   51 
 xen/arch/ia64/vmx/vmx_minstate.h                                        |   51 
 xen/arch/ia64/vmx/vmx_phy_mode.c                                        |   22 
 xen/arch/ia64/vmx/vmx_process.c                                         |   35 
 xen/arch/ia64/vmx/vmx_support.c                                         |    2 
 xen/arch/ia64/vmx/vmx_utility.c                                         |    2 
 xen/arch/ia64/vmx/vmx_vcpu.c                                            |   59 
 xen/arch/ia64/vmx/vmx_virt.c                                            |   51 
 xen/arch/ia64/xen/Makefile                                              |    1 
 xen/arch/ia64/xen/dom0_ops.c                                            |  185 
 xen/arch/ia64/xen/dom_fw.c                                              |  187 
 xen/arch/ia64/xen/domain.c                                              |  408 
 xen/arch/ia64/xen/faults.c                                              |  139 
 xen/arch/ia64/xen/fw_emul.c                                             |   17 
 xen/arch/ia64/xen/hypercall.c                                           |   11 
 xen/arch/ia64/xen/irq.c                                                 |   13 
 xen/arch/ia64/xen/ivt.S                                                 |  181 
 xen/arch/ia64/xen/mm.c                                                  |  171 
 xen/arch/ia64/xen/privop.c                                              |  420 
 xen/arch/ia64/xen/privop_stat.c                                         |  389 
 xen/arch/ia64/xen/regionreg.c                                           |   19 
 xen/arch/ia64/xen/vcpu.c                                                |  136 
 xen/arch/ia64/xen/vhpt.c                                                |   24 
 xen/arch/ia64/xen/xenasm.S                                              |    4 
 xen/arch/ia64/xen/xenmisc.c                                             |    4 
 xen/arch/ia64/xen/xensetup.c                                            |   12 
 xen/arch/powerpc/Makefile                                               |    3 
 xen/arch/powerpc/setup.c                                                |   36 
 xen/arch/powerpc/xen.lds.S                                              |  239 
 xen/arch/x86/dom0_ops.c                                                 |   14 
 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                                              |  130 
 xen/arch/x86/hvm/vmx/io.c                                               |    1 
 xen/arch/x86/hvm/vmx/vmcs.c                                             |   20 
 xen/arch/x86/hvm/vmx/vmx.c                                              |   49 
 xen/arch/x86/irq.c                                                      |   17 
 xen/arch/x86/mm.c                                                       |   19 
 xen/arch/x86/shadow.c                                                   |   19 
 xen/arch/x86/shadow32.c                                                 |   24 
 xen/arch/x86/shadow_public.c                                            |   74 
 xen/arch/x86/traps.c                                                    |  122 
 xen/arch/x86/x86_32/mm.c                                                |    5 
 xen/arch/x86/x86_32/traps.c                                             |    4 
 xen/arch/x86/x86_64/entry.S                                             |    8 
 xen/arch/x86/x86_64/mm.c                                                |    6 
 xen/arch/x86/x86_64/traps.c                                             |   28 
 xen/arch/x86/x86_emulate.c                                              |   19 
 xen/common/grant_table.c                                                |    6 
 xen/common/memory.c                                                     |    2 
 xen/common/schedule.c                                                   |    7 
 xen/common/trace.c                                                      |   24 
 xen/include/asm-ia64/bundle.h                                           |  231 
 xen/include/asm-ia64/config.h                                           |   20 
 xen/include/asm-ia64/dom_fw.h                                           |    4 
 xen/include/asm-ia64/domain.h                                           |  122 
 xen/include/asm-ia64/iocap.h                                            |    8 
 xen/include/asm-ia64/linux-xen/asm/README.origin                        |    1 
 xen/include/asm-ia64/linux-xen/asm/asmmacro.h                           |  119 
 xen/include/asm-ia64/linux-xen/asm/mca_asm.h                            |    4 
 xen/include/asm-ia64/linux-xen/asm/pgtable.h                            |    5 
 xen/include/asm-ia64/linux-xen/asm/system.h                             |    2 
 xen/include/asm-ia64/linux/asm/README.origin                            |    1 
 xen/include/asm-ia64/mm.h                                               |    7 
 xen/include/asm-ia64/perfc_defn.h                                       |    1 
 xen/include/asm-ia64/privop.h                                           |  225 
 xen/include/asm-ia64/privop_stat.h                                      |   66 
 xen/include/asm-ia64/regionreg.h                                        |    1 
 xen/include/asm-ia64/shadow.h                                           |   18 
 xen/include/asm-ia64/tlbflush.h                                         |    6 
 xen/include/asm-ia64/vcpu.h                                             |   25 
 xen/include/asm-ia64/vhpt.h                                             |    3 
 xen/include/asm-ia64/vmx.h                                              |    4 
 xen/include/asm-ia64/vmx_pal.h                                          |    5 
 xen/include/asm-ia64/vmx_phy_mode.h                                     |    1 
 xen/include/asm-ia64/vmx_vcpu.h                                         |    1 
 xen/include/asm-ia64/vmx_vpd.h                                          |    2 
 xen/include/asm-ia64/xenpage.h                                          |    7 
 xen/include/asm-ia64/xensystem.h                                        |    1 
 xen/include/asm-powerpc/mm.h                                            |    5 
 xen/include/asm-powerpc/percpu.h                                        |   22 
 xen/include/asm-x86/config.h                                            |   12 
 xen/include/asm-x86/hvm/io.h                                            |    4 
 xen/include/asm-x86/hvm/vcpu.h                                          |   18 
 xen/include/asm-x86/hvm/vmx/vmx.h                                       |   52 
 xen/include/asm-x86/hvm/vpit.h                                          |    4 
 xen/include/asm-x86/mm.h                                                |    5 
 xen/include/asm-x86/perfc_defn.h                                        |  147 
 xen/include/asm-x86/processor.h                                         |    3 
 xen/include/public/arch-ia64.h                                          |  109 
 xen/include/public/dom0_ops.h                                           |   14 
 xen/include/public/grant_table.h                                        |    4 
 xen/include/public/trace.h                                              |    1 
 xen/include/xen/irq.h                                                   |    2 
 xen/include/xen/perfc_defn.h                                            |  136 
 670 files changed, 134737 insertions(+), 20765 deletions(-)

diff -r a75c389e4a7d -r 5ecfc7102cca .hgignore
--- a/.hgignore Tue Aug 01 16:42:48 2006 -0400
+++ b/.hgignore Tue Aug 01 16:51:03 2006 -0400
@@ -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$
diff -r a75c389e4a7d -r 5ecfc7102cca Config.mk
--- a/Config.mk Tue Aug 01 16:42:48 2006 -0400
+++ b/Config.mk Tue Aug 01 16:51:03 2006 -0400
@@ -36,6 +36,8 @@ CFLAGS    ?= -O2 -fomit-frame-pointer
 CFLAGS    ?= -O2 -fomit-frame-pointer
 CFLAGS    += -DNDEBUG
 else
+# Less than -O1 produces bad code and large stack frames
+CFLAGS    ?= -O1 -fno-omit-frame-pointer
 CFLAGS    += -g
 endif
 
diff -r a75c389e4a7d -r 5ecfc7102cca README
--- a/README    Tue Aug 01 16:42:48 2006 -0400
+++ b/README    Tue Aug 01 16:51:03 2006 -0400
@@ -91,6 +91,7 @@ provided by your Linux distributor:
     * GNU Binutils
     * Development install of zlib (e.g., zlib-dev)
     * Development install of Python v2.3 or later (e.g., python-dev)
+    * Development install of curses (e.g., libncurses-dev)
     * bridge-utils package (/sbin/brctl)
     * iproute package (/sbin/ip)
     * hotplug or udev
diff -r a75c389e4a7d -r 5ecfc7102cca buildconfigs/Rules.mk
--- a/buildconfigs/Rules.mk     Tue Aug 01 16:42:48 2006 -0400
+++ b/buildconfigs/Rules.mk     Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca buildconfigs/linux-defconfig_xen0_ia64
--- a/buildconfigs/linux-defconfig_xen0_ia64    Tue Aug 01 16:42:48 2006 -0400
+++ b/buildconfigs/linux-defconfig_xen0_ia64    Tue Aug 01 16:51:03 2006 -0400
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.16.13-xen0
-# Mon May 22 14:46:31 2006
+# Fri Jun 30 12:59:19 2006
 #
 
 #
@@ -721,21 +721,10 @@ CONFIG_SERIAL_NONSTANDARD=y
 #
 # Serial drivers
 #
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_ACPI=y
-CONFIG_SERIAL_8250_NR_UARTS=6
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_RSA is not set
 
 #
 # Non-8250 serial port support
 #
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
@@ -1516,8 +1505,16 @@ CONFIG_CRYPTO_DES=y
 #
 # Hardware crypto devices
 #
+# CONFIG_XEN_UTIL is not set
 CONFIG_HAVE_ARCH_ALLOC_SKB=y
 CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_SKBUFF=y
+CONFIG_XEN_NETDEV_BACKEND=y
+CONFIG_XEN_NETDEV_FRONTEND=y
+# CONFIG_XEN_DEVMEM is not set
+# CONFIG_XEN_REBOOT is not set
+# CONFIG_XEN_SMPBOOT is not set
 CONFIG_XEN_INTERFACE_VERSION=0x00030202
 
 #
@@ -1525,19 +1522,21 @@ CONFIG_XEN_INTERFACE_VERSION=0x00030202
 #
 CONFIG_XEN_PRIVILEGED_GUEST=y
 # CONFIG_XEN_UNPRIVILEGED_GUEST is not set
+CONFIG_XEN_PRIVCMD=y
 CONFIG_XEN_BACKEND=y
 # CONFIG_XEN_PCIDEV_BACKEND is not set
 CONFIG_XEN_BLKDEV_BACKEND=y
-CONFIG_XEN_NETDEV_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
 CONFIG_XEN_BLKDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_FRONTEND=y
 # CONFIG_XEN_SCRUB_PAGES is not set
-# CONFIG_XEN_DISABLE_SERIAL is not set
+CONFIG_XEN_DISABLE_SERIAL=y
 CONFIG_XEN_SYSFS=y
 CONFIG_XEN_COMPAT_030002_AND_LATER=y
 # CONFIG_XEN_COMPAT_LATEST_ONLY is not set
 CONFIG_XEN_COMPAT_030002=y
+CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
 CONFIG_NO_IDLE_HZ=y
diff -r a75c389e4a7d -r 5ecfc7102cca buildconfigs/linux-defconfig_xen0_x86_32
--- a/buildconfigs/linux-defconfig_xen0_x86_32  Tue Aug 01 16:42:48 2006 -0400
+++ b/buildconfigs/linux-defconfig_xen0_x86_32  Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca buildconfigs/linux-defconfig_xen0_x86_64
--- a/buildconfigs/linux-defconfig_xen0_x86_64  Tue Aug 01 16:42:48 2006 -0400
+++ b/buildconfigs/linux-defconfig_xen0_x86_64  Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca buildconfigs/linux-defconfig_xen_ia64
--- a/buildconfigs/linux-defconfig_xen_ia64     Tue Aug 01 16:42:48 2006 -0400
+++ b/buildconfigs/linux-defconfig_xen_ia64     Tue Aug 01 16:51:03 2006 -0400
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.16.13-xen
-# Mon May 22 14:15:20 2006
+# Thu Jun 29 16:23:48 2006
 #
 
 #
@@ -727,21 +727,10 @@ CONFIG_SERIAL_NONSTANDARD=y
 #
 # Serial drivers
 #
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_ACPI=y
-CONFIG_SERIAL_8250_NR_UARTS=6
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_RSA is not set
 
 #
 # Non-8250 serial port support
 #
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
@@ -1522,8 +1511,16 @@ CONFIG_CRYPTO_DES=y
 #
 # Hardware crypto devices
 #
+# CONFIG_XEN_UTIL is not set
 CONFIG_HAVE_ARCH_ALLOC_SKB=y
 CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_SKBUFF=y
+CONFIG_XEN_NETDEV_BACKEND=y
+CONFIG_XEN_NETDEV_FRONTEND=y
+# CONFIG_XEN_DEVMEM is not set
+# CONFIG_XEN_REBOOT is not set
+# CONFIG_XEN_SMPBOOT is not set
 CONFIG_XEN_INTERFACE_VERSION=0x00030202
 
 #
@@ -1531,19 +1528,21 @@ CONFIG_XEN_INTERFACE_VERSION=0x00030202
 #
 CONFIG_XEN_PRIVILEGED_GUEST=y
 # CONFIG_XEN_UNPRIVILEGED_GUEST is not set
+CONFIG_XEN_PRIVCMD=y
 CONFIG_XEN_BACKEND=y
 # CONFIG_XEN_PCIDEV_BACKEND is not set
 CONFIG_XEN_BLKDEV_BACKEND=y
-CONFIG_XEN_NETDEV_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
 CONFIG_XEN_BLKDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_FRONTEND=y
 # CONFIG_XEN_SCRUB_PAGES is not set
-# CONFIG_XEN_DISABLE_SERIAL is not set
+CONFIG_XEN_DISABLE_SERIAL=y
 CONFIG_XEN_SYSFS=y
 CONFIG_XEN_COMPAT_030002_AND_LATER=y
 # CONFIG_XEN_COMPAT_LATEST_ONLY is not set
 CONFIG_XEN_COMPAT_030002=y
+CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
 CONFIG_NO_IDLE_HZ=y
diff -r a75c389e4a7d -r 5ecfc7102cca buildconfigs/linux-defconfig_xen_x86_32
--- a/buildconfigs/linux-defconfig_xen_x86_32   Tue Aug 01 16:42:48 2006 -0400
+++ b/buildconfigs/linux-defconfig_xen_x86_32   Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca buildconfigs/linux-defconfig_xen_x86_64
--- a/buildconfigs/linux-defconfig_xen_x86_64   Tue Aug 01 16:42:48 2006 -0400
+++ b/buildconfigs/linux-defconfig_xen_x86_64   Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca buildconfigs/mk.linux-2.6-xen
--- a/buildconfigs/mk.linux-2.6-xen     Tue Aug 01 16:42:48 2006 -0400
+++ b/buildconfigs/mk.linux-2.6-xen     Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca config/ia64.mk
--- a/config/ia64.mk    Tue Aug 01 16:42:48 2006 -0400
+++ b/config/ia64.mk    Tue Aug 01 16:51:03 2006 -0400
@@ -1,4 +1,5 @@ CONFIG_IA64 := y
 CONFIG_IA64 := y
 CONFIG_IOEMU := y
+CONFIG_XCUTILS := y
 
 LIBDIR := lib
diff -r a75c389e4a7d -r 5ecfc7102cca config/x86_32.mk
--- a/config/x86_32.mk  Tue Aug 01 16:42:48 2006 -0400
+++ b/config/x86_32.mk  Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca config/x86_64.mk
--- a/config/x86_64.mk  Tue Aug 01 16:42:48 2006 -0400
+++ b/config/x86_64.mk  Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca docs/src/user.tex
--- a/docs/src/user.tex Tue Aug 01 16:42:48 2006 -0400
+++ b/docs/src/user.tex Tue Aug 01 16:51:03 2006 -0400
@@ -1287,8 +1287,8 @@ backend domain. The PCI Backend appears 
 backend domain. The PCI Backend appears to the Linux kernel as a regular PCI
 device driver. The PCI Backend ensures that no other device driver loads
 for the devices by binding itself as the device driver for those devices.
-PCI devices are identified by hexadecimal slot/funciton numbers (on Linux,
-use \path{lspci} to determine slot/funciton numbers of your devices) and
+PCI devices are identified by hexadecimal slot/function numbers (on Linux,
+use \path{lspci} to determine slot/function numbers of your devices) and
 can be specified with or without the PCI domain: \\
 \centerline{  {\tt ({\em bus}:{\em slot}.{\em func})} example {\tt (02:1d.3)}} 
\\
 \centerline{  {\tt ({\em domain}:{\em bus}:{\em slot}.{\em func})} example 
{\tt (0000:02:1d.3)}} \\
@@ -1344,6 +1344,50 @@ Note that the "-n" option in the example
 Note that the "-n" option in the example is important as it causes echo to not
 output a new-line.
 
+\subsubsection{PCI Backend Configuration - User-space Quirks}
+Quirky devices (such as the Broadcom Tigon 3) may need write access to their
+configuration space registers.  Xen can be instructed to allow specified PCI
+devices write access to specific configuration space registers.  The policy may
+be found in:
+
+\centerline{ \path{/etc/xen/xend-pci-quirks.sxp} }
+
+The policy file is heavily commented and is intended to provide enough
+documentation for developers to extend it.
+
+\subsubsection{PCI Backend Configuration - Permissive Flag}
+If the user-space quirks approach doesn't meet your needs you may want to 
enable
+the permissive flag for that device.  To do so, first get the PCI domain, bus,
+slot, and function information from dom0 via \path{lspci}.  Then augment the
+user-space policy for permissive devices.  The permissive policy can be found
+in:
+
+\centerline{ \path{/etc/xen/xend-pci-permissive.sxp} }
+
+Currently, the only way to reset the permissive flag is to unbind the device
+from the PCI Backend driver.
+
+\subsubsection{PCI Backend - Checking Status}
+There two important sysfs nodes that provide a mechanism to view specifics on
+quirks and permissive devices:
+\begin{description}
+\item \path{/sys/bus/drivers/pciback/permissive} \\
+ Use \path{cat} on this file to view a list of permissive slots.
+\item \path{/sys/bus/drivers/pciback/quirks} \\
+ Use \path{cat} on this file view a hierarchical view of devices bound to the
+PCI backend, their PCI vendor/device ID, and any quirks that are associated 
with
+that particular slot.  
+\end{description}
+
+You may notice that every device bound to the PCI backend has 17 quirks 
standard 
+"quirks" regardless of \path{xend-pci-quirks.sxp}.  These default entries are
+necessary to support interactions between the PCI bus manager and the device 
bound
+to it.  Even non-quirky devices should have these standard entries.  
+
+In this case, preference was given to accuracy over aesthetics by choosing to
+show the standard quirks in the quirks list rather than hide them from the
+inquiring user 
+
 \subsubsection{PCI Frontend Configuration}
 To configure a domU to receive a PCI device:
 
@@ -1374,8 +1418,136 @@ To configure a domU to receive a PCI dev
 %% There are two possible types of privileges: IO privileges and
 %% administration privileges.
 
-
-
+\section{Support for virtual Trusted Platform Module (vTPM)}
+\label{ss:vtpm}
+
+Paravirtualized domains can be given access to a virtualized version
+of a TPM. This enables applications in these domains to use the services
+of the TPM device for example through a TSS stack
+\footnote{Trousers TSS stack: http://sourceforge.net/projects/trousers}.
+The Xen source repository provides the necessary software components to
+enable virtual TPM access. Support is provided through several
+different pieces. First, a TPM emulator has been modified to provide TPM's
+functionality for the virtual TPM subsystem. Second, a virtual TPM Manager
+coordinates the virtual TPMs efforts, manages their creation, and provides
+protected key storage using the TPM. Third, a device driver pair providing
+a TPM front- and backend is available for XenLinux to deliver TPM commands
+from the domain to the virtual TPM manager, which dispatches it to a
+software TPM. Since the TPM Manager relies on a HW TPM for protected key
+storage, therefore this subsystem requires a Linux-supported hardware TPM.
+For development purposes, a TPM emulator is available for use on non-TPM
+enabled platforms.
+
+\subsubsection{Compile-Time Setup}
+To enable access to the virtual TPM, the virtual TPM backend driver must
+be compiled for a privileged domain (e.g. domain 0). Using the XenLinux
+configuration, the necessary driver can be selected in the Xen configuration
+section. Unless the driver has been compiled into the kernel, its module
+must be activated using the following command:
+
+\begin{verbatim}
+modprobe tpmbk
+\end{verbatim}
+
+Similarly, the TPM frontend driver must be compiled for the kernel trying
+to use TPM functionality. Its driver can be selected in the kernel
+configuration section Device Driver / Character Devices / TPM Devices.
+Along with that the TPM driver for the built-in TPM must be selected.
+If the virtual TPM driver has been compiled as module, it
+must be activated using the following command:
+
+\begin{verbatim}
+modprobe tpm_xenu
+\end{verbatim}
+
+Furthermore, it is necessary to build the virtual TPM manager and software
+TPM by making changes to entries in Xen build configuration files.
+The following entry in the file Config.mk in the Xen root source
+directory must be made:
+
+\begin{verbatim}
+VTPM_TOOLS ?= y
+\end{verbatim}
+
+After a build of the Xen tree and a reboot of the machine, the TPM backend
+drive must be loaded. Once loaded, the virtual TPM manager daemon
+must be started before TPM-enabled guest domains may be launched.
+To enable being the destination of a virtual TPM Migration, the virtual TPM
+migration daemon must also be loaded.
+
+\begin{verbatim}
+vtpm_managerd
+\end{verbatim}
+\begin{verbatim}
+vtpm_migratord
+\end{verbatim}
+
+Once the VTPM manager is running, the VTPM can be accessed by loading the
+front end driver in a guest domain.
+
+\subsubsection{Development and Testing TPM Emulator}
+For development and testing on non-TPM enabled platforms, a TPM emulator
+can be used in replacement of a platform TPM. First, the entry in the file
+tools/vtpm/Rules.mk must look as follows:
+
+\begin{verbatim}
+BUILD_EMULATOR = y
+\end{verbatim}
+
+Second, the entry in the file tool/vtpm\_manager/Rules.mk must be uncommented
+as follows:
+
+\begin{verbatim}
+# TCS talks to fifo's rather than /dev/tpm. TPM Emulator assumed on fifos
+CFLAGS += -DDUMMY_TPM
+\end{verbatim}
+
+Before starting the virtual TPM Manager, start the emulator by executing
+the following in dom0:
+
+\begin{verbatim}
+tpm_emulator clear
+\end{verbatim}
+
+\subsubsection{vTPM Frontend Configuration}
+To provide TPM functionality to a user domain, a line must be added to
+the virtual TPM configuration file using the following format:
+
+\begin{verbatim}
+vtpm = ['instance=<instance number>, backend=<domain id>']
+\end{verbatim}
+
+The { \it instance number} reflects the preferred virtual TPM instance
+to associate with the domain. If the selected instance is
+already associated with another domain, the system will automatically
+select the next available instance. An instance number greater than
+zero must be provided. It is possible to omit the instance
+parameter from the configuration file.
+
+The {\it domain id} provides the ID of the domain where the
+virtual TPM backend driver and virtual TPM are running in. It should
+currently always be set to '0'.
+
+
+Examples for valid vtpm entries in the configuration file are
+
+\begin{verbatim}
+ vtpm = ['instance=1, backend=0']
+\end{verbatim}
+and
+\begin{verbatim}
+ vtpm = ['backend=0'].
+\end{verbatim}
+
+\subsubsection{Using the virtual TPM}
+
+Access to TPM functionality is provided by the virtual TPM frontend driver.
+Similar to existing hardware TPM drivers, this driver provides basic TPM
+status information through the {\it sysfs} filesystem. In a Xen user domain
+the sysfs entries can be found in /sys/devices/xen/vtpm-0.
+
+Commands can be sent to the virtual TPM instance using the character
+device /dev/tpm0 (major 10, minor 224).
 
 % Chapter Storage and FileSytem Management
 \chapter{Storage and File System Management}
diff -r a75c389e4a7d -r 5ecfc7102cca extras/mini-os/mm.c
--- a/extras/mini-os/mm.c       Tue Aug 01 16:42:48 2006 -0400
+++ b/extras/mini-os/mm.c       Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c  Tue Aug 01 16:42:48 
2006 -0400
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c  Tue Aug 01 16:51:03 
2006 -0400
@@ -958,11 +958,17 @@ u64 jiffies_to_st(unsigned long j)
        do {
                seq = read_seqbegin(&xtime_lock);
                delta = j - jiffies;
-               /* NB. The next check can trigger in some wrap-around cases,
-                * but that's ok: we'll just end up with a shorter timeout. */
-               if (delta < 1)
-                       delta = 1;
-               st = processed_system_time + (delta * (u64)NS_PER_TICK);
+               if (delta < 1) {
+                       /* Triggers in some wrap-around cases, but that's okay:
+                        * we just end up with a shorter timeout. */
+                       st = processed_system_time + NS_PER_TICK;
+               } else if (((unsigned long)delta >> (BITS_PER_LONG-3)) != 0) {
+                       /* Very long timeout means there is no pending timer.
+                        * We indicate this to Xen by passing zero timeout. */
+                       st = 0;
+               } else {
+                       st = processed_system_time + delta * (u64)NS_PER_TICK;
+               }
        } while (read_seqretry(&xtime_lock, seq));
 
        return st;
@@ -989,14 +995,15 @@ static void stop_hz_timer(void)
 
        smp_mb();
 
-       /* Leave ourselves in 'tick mode' if rcu or softirq or timer pending. */
+       /* Leave ourselves in tick mode if rcu or softirq or timer pending. */
        if (rcu_needs_cpu(cpu) || local_softirq_pending() ||
            (j = next_timer_interrupt(), time_before_eq(j, jiffies))) {
                cpu_clear(cpu, nohz_cpu_mask);
                j = jiffies + 1;
        }
 
-       BUG_ON(HYPERVISOR_set_timer_op(jiffies_to_st(j)) != 0);
+       if (HYPERVISOR_set_timer_op(jiffies_to_st(j)) != 0)
+               BUG();
 }
 
 static void start_hz_timer(void)
diff -r a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c    Tue Aug 01 16:42:48 
2006 -0400
+++ b/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c    Tue Aug 01 16:51:03 
2006 -0400
@@ -266,6 +266,7 @@ static void contiguous_bitmap_clear(
 /* Protected by balloon_lock. */
 #define MAX_CONTIG_ORDER 9 /* 2MB */
 static unsigned long discontig_frames[1<<MAX_CONTIG_ORDER];
+static multicall_entry_t cr_mcl[1<<MAX_CONTIG_ORDER];
 
 /* Ensure multi-page extents are contiguous in machine memory. */
 int xen_create_contiguous_region(
@@ -310,12 +311,13 @@ int xen_create_contiguous_region(
        /* 1. Zap current PTEs, remembering MFNs. */
        for (i = 0; i < (1UL<<order); i++) {
                in_frames[i] = pfn_to_mfn((__pa(vstart) >> PAGE_SHIFT) + i);
-               if (HYPERVISOR_update_va_mapping(vstart + (i*PAGE_SIZE),
-                                                __pte_ma(0), 0))
-                       BUG();
+               MULTI_update_va_mapping(cr_mcl + i, vstart + (i*PAGE_SIZE),
+                                       __pte_ma(0), 0);
                set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
                        INVALID_P2M_ENTRY);
        }
+       if (HYPERVISOR_multicall(cr_mcl, i))
+               BUG();
 
        /* 2. Get a new contiguous memory extent. */
        out_frame = __pa(vstart) >> PAGE_SHIFT;
@@ -343,15 +345,16 @@ int xen_create_contiguous_region(
        /* 3. Map the new extent in place of old pages. */
        for (i = 0; i < (1UL<<order); i++) {
                frame = success ? (out_frame + i) : in_frames[i];
-               if (HYPERVISOR_update_va_mapping(vstart + (i*PAGE_SIZE),
-                                                pfn_pte_ma(frame,
-                                                           PAGE_KERNEL),
-                                                0))
-                       BUG();
+               MULTI_update_va_mapping(cr_mcl + i, vstart + (i*PAGE_SIZE),
+                                       pfn_pte_ma(frame, PAGE_KERNEL), 0);
                set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, frame);
        }
 
-       flush_tlb_all();
+       cr_mcl[i - 1].args[MULTI_UVMFLAGS_INDEX] = order
+                                                  ? UVMF_TLB_FLUSH|UVMF_ALL
+                                                  : UVMF_INVLPG|UVMF_ALL;
+       if (HYPERVISOR_multicall(cr_mcl, i))
+               BUG();
 
        if (success)
                contiguous_bitmap_set(__pa(vstart) >> PAGE_SHIFT,
@@ -402,13 +405,14 @@ void xen_destroy_contiguous_region(unsig
 
        /* 2. Zap current PTEs. */
        for (i = 0; i < (1UL<<order); i++) {
-               if (HYPERVISOR_update_va_mapping(vstart + (i*PAGE_SIZE),
-                                                __pte_ma(0), 0))
-                       BUG();
+               MULTI_update_va_mapping(cr_mcl + i, vstart + (i*PAGE_SIZE),
+                                       __pte_ma(0), 0);
                set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
                        INVALID_P2M_ENTRY);
                out_frames[i] = (__pa(vstart) >> PAGE_SHIFT) + i;
        }
+       if (HYPERVISOR_multicall(cr_mcl, i))
+               BUG();
 
        /* 3. Do the exchange for non-contiguous MFNs. */
        rc = HYPERVISOR_memory_op(XENMEM_exchange, &exchange);
@@ -429,15 +433,16 @@ void xen_destroy_contiguous_region(unsig
        /* 4. Map new pages in place of old pages. */
        for (i = 0; i < (1UL<<order); i++) {
                frame = success ? out_frames[i] : (in_frame + i);
-               if (HYPERVISOR_update_va_mapping(vstart + (i*PAGE_SIZE),
-                                                pfn_pte_ma(frame,
-                                                           PAGE_KERNEL),
-                                                0))
-                       BUG();
+               MULTI_update_va_mapping(cr_mcl + i, vstart + (i*PAGE_SIZE),
+                                       pfn_pte_ma(frame, PAGE_KERNEL), 0);
                set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, frame);
        }
 
-       flush_tlb_all();
+       cr_mcl[i - 1].args[MULTI_UVMFLAGS_INDEX] = order
+                                                  ? UVMF_TLB_FLUSH|UVMF_ALL
+                                                  : UVMF_INVLPG|UVMF_ALL;
+       if (HYPERVISOR_multicall(cr_mcl, i))
+               BUG();
 
        balloon_unlock(flags);
 }
diff -r a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c   Tue Aug 01 16:42:48 
2006 -0400
+++ b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c   Tue Aug 01 16:51:03 
2006 -0400
@@ -652,8 +652,13 @@ void mm_pin_all(void)
 void mm_pin_all(void)
 {
        struct page *page;
+
+       /* Only pgds on the pgd_list please: none hidden in the slab cache. */
+       kmem_cache_shrink(pgd_cache);
+
        if (xen_feature(XENFEAT_writable_page_tables))
                return;
+
        for (page = pgd_list; page; page = (struct page *)page->index) {
                if (!test_bit(PG_pinned, &page->flags))
                        __pgd_pin((pgd_t *)page_address(page));
diff -r a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c
--- a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c        Tue Aug 01 
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c        Tue Aug 01 
16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca linux-2.6-xen-sparse/arch/ia64/Kconfig
--- a/linux-2.6-xen-sparse/arch/ia64/Kconfig    Tue Aug 01 16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/arch/ia64/Kconfig    Tue Aug 01 16:51:03 2006 -0400
@@ -70,6 +70,13 @@ config XEN_IA64_DOM0_NON_VP
        default y
        help
          dom0 P=M model
+
+config XEN_IA64_VDSO_PARAVIRT
+       bool
+       depends on XEN && !ITANIUM
+       default y
+       help
+         vDSO paravirtualization
 
 config SCHED_NO_NO_OMIT_FRAME_POINTER
        bool
@@ -518,7 +525,7 @@ config XEN_DEVMEM
        default n
 
 config XEN_REBOOT
-       default n
+       default y
 
 config XEN_SMPBOOT
        default n
diff -r a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c
--- a/linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c  Tue Aug 01 16:42:48 
2006 -0400
+++ b/linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c  Tue Aug 01 16:51:03 
2006 -0400
@@ -31,6 +31,9 @@
 #include <linux/smp_lock.h>
 #include <linux/threads.h>
 #include <linux/bitops.h>
+#ifdef CONFIG_XEN
+#include <linux/cpu.h>
+#endif
 
 #include <asm/delay.h>
 #include <asm/intrinsics.h>
@@ -235,6 +238,9 @@ static struct irqaction ipi_irqaction = 
 #include <xen/evtchn.h>
 #include <xen/interface/callback.h>
 
+static DEFINE_PER_CPU(int, timer_irq) = -1;
+static DEFINE_PER_CPU(int, ipi_irq) = -1;
+static DEFINE_PER_CPU(int, resched_irq) = -1;
 static char timer_name[NR_CPUS][15];
 static char ipi_name[NR_CPUS][15];
 static char resched_name[NR_CPUS][15];
@@ -252,6 +258,7 @@ static unsigned short saved_irq_cnt = 0;
 static unsigned short saved_irq_cnt = 0;
 static int xen_slab_ready = 0;
 
+#ifdef CONFIG_SMP
 /* Dummy stub. Though we may check RESCHEDULE_VECTOR before __do_IRQ,
  * it ends up to issue several memory accesses upon percpu data and
  * thus adds unnecessary traffic to other paths.
@@ -268,6 +275,7 @@ static struct irqaction resched_irqactio
        .flags =        SA_INTERRUPT,
        .name =         "RESCHED"
 };
+#endif
 
 /*
  * This is xen version percpu irq registration, which needs bind
@@ -294,6 +302,7 @@ xen_register_percpu_irq (unsigned int ir
                        ret = bind_virq_to_irqhandler(VIRQ_ITC, cpu,
                                action->handler, action->flags,
                                timer_name[cpu], action->dev_id);
+                       per_cpu(timer_irq,cpu) = ret;
                        printk(KERN_INFO "register VIRQ_ITC (%s) to xen irq 
(%d)\n", timer_name[cpu], ret);
                        break;
                case IA64_IPI_RESCHEDULE:
@@ -301,6 +310,7 @@ xen_register_percpu_irq (unsigned int ir
                        ret = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR, cpu,
                                action->handler, action->flags,
                                resched_name[cpu], action->dev_id);
+                       per_cpu(resched_irq,cpu) = ret;
                        printk(KERN_INFO "register RESCHEDULE_VECTOR (%s) to 
xen irq (%d)\n", resched_name[cpu], ret);
                        break;
                case IA64_IPI_VECTOR:
@@ -308,6 +318,7 @@ xen_register_percpu_irq (unsigned int ir
                        ret = bind_ipi_to_irqhandler(IPI_VECTOR, cpu,
                                action->handler, action->flags,
                                ipi_name[cpu], action->dev_id);
+                       per_cpu(ipi_irq,cpu) = ret;
                        printk(KERN_INFO "register IPI_VECTOR (%s) to xen irq 
(%d)\n", ipi_name[cpu], ret);
                        break;
                case IA64_SPURIOUS_INT_VECTOR:
@@ -343,7 +354,7 @@ xen_bind_early_percpu_irq (void)
         */
        for (i = 0; i < late_irq_cnt; i++)
                xen_register_percpu_irq(saved_percpu_irqs[i].irq,
-                       saved_percpu_irqs[i].action, 0);
+                                       saved_percpu_irqs[i].action, 0);
 }
 
 /* FIXME: There's no obvious point to check whether slab is ready. So
@@ -352,6 +363,38 @@ extern void (*late_time_init)(void);
 extern void (*late_time_init)(void);
 extern char xen_event_callback;
 extern void xen_init_IRQ(void);
+
+#ifdef CONFIG_HOTPLUG_CPU
+static int __devinit
+unbind_evtchn_callback(struct notifier_block *nfb,
+                       unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (unsigned long)hcpu;
+
+       if (action == CPU_DEAD) {
+               /* Unregister evtchn.  */
+               if (per_cpu(ipi_irq,cpu) >= 0) {
+                       unbind_from_irqhandler (per_cpu(ipi_irq, cpu), NULL);
+                       per_cpu(ipi_irq, cpu) = -1;
+               }
+               if (per_cpu(resched_irq,cpu) >= 0) {
+                       unbind_from_irqhandler (per_cpu(resched_irq, cpu),
+                                               NULL);
+                       per_cpu(resched_irq, cpu) = -1;
+               }
+               if (per_cpu(timer_irq,cpu) >= 0) {
+                       unbind_from_irqhandler (per_cpu(timer_irq, cpu), NULL);
+                       per_cpu(timer_irq, cpu) = -1;
+               }
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block unbind_evtchn_notifier = {
+       .notifier_call = unbind_evtchn_callback,
+       .priority = 0
+};
+#endif
 
 DECLARE_PER_CPU(int, ipi_to_irq[NR_IPIS]);
 void xen_smp_intr_init(void)
@@ -363,21 +406,22 @@ void xen_smp_intr_init(void)
                .type = CALLBACKTYPE_event,
                .address = (unsigned long)&xen_event_callback,
        };
-       static cpumask_t registered_cpumask;
-
-       if (!cpu)
+
+       if (cpu == 0) {
+               /* Initialization was already done for boot cpu.  */
+#ifdef CONFIG_HOTPLUG_CPU
+               /* Register the notifier only once.  */
+               register_cpu_notifier(&unbind_evtchn_notifier);
+#endif
                return;
+       }
 
        /* This should be piggyback when setup vcpu guest context */
        BUG_ON(HYPERVISOR_callback_op(CALLBACKOP_register, &event));
 
-       if (!cpu_isset(cpu, registered_cpumask)) {
-               cpu_set(cpu, registered_cpumask);
-               for (i = 0; i < saved_irq_cnt; i++)
-                       xen_register_percpu_irq(saved_percpu_irqs[i].irq,
-                                               saved_percpu_irqs[i].action,
-                                               0);
-       }
+       for (i = 0; i < saved_irq_cnt; i++)
+               xen_register_percpu_irq(saved_percpu_irqs[i].irq,
+                                       saved_percpu_irqs[i].action, 0);
 #endif /* CONFIG_SMP */
 }
 #endif /* CONFIG_XEN */
@@ -388,12 +432,13 @@ register_percpu_irq (ia64_vector vec, st
        irq_desc_t *desc;
        unsigned int irq;
 
+#ifdef CONFIG_XEN
+       if (is_running_on_xen())
+               return xen_register_percpu_irq(vec, action, 1);
+#endif
+
        for (irq = 0; irq < NR_IRQS; ++irq)
                if (irq_to_vector(irq) == vec) {
-#ifdef CONFIG_XEN
-                       if (is_running_on_xen())
-                               return xen_register_percpu_irq(vec, action, 1);
-#endif
                        desc = irq_descp(irq);
                        desc->status |= IRQ_PER_CPU;
                        desc->handler = &irq_type_ia64_lsapic;
@@ -441,6 +486,7 @@ ia64_send_ipi (int cpu, int vector, int 
         if (is_running_on_xen()) {
                int irq = -1;
 
+#ifdef CONFIG_SMP
                /* TODO: we need to call vcpu_up here */
                if (unlikely(vector == ap_wakeup_vector)) {
                        extern void xen_send_ipi (int cpu, int vec);
@@ -448,6 +494,7 @@ ia64_send_ipi (int cpu, int vector, int 
                        //vcpu_prepare_and_up(cpu);
                        return;
                }
+#endif
 
                switch(vector) {
                case IA64_IPI_VECTOR:
diff -r a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/arch/ia64/kernel/setup.c
--- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c     Tue Aug 01 16:42:48 
2006 -0400
+++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c     Tue Aug 01 16:51:03 
2006 -0400
@@ -75,6 +75,20 @@ EXPORT_SYMBOL(__per_cpu_offset);
 EXPORT_SYMBOL(__per_cpu_offset);
 #endif
 
+#ifdef CONFIG_XEN
+static int
+xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+       HYPERVISOR_shutdown(SHUTDOWN_crash);
+       /* we're never actually going to get here... */
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block xen_panic_block = {
+       xen_panic_event, NULL, 0 /* try to go last */
+};
+#endif
+
 extern void ia64_setup_printk_clock(void);
 
 DEFINE_PER_CPU(struct cpuinfo_ia64, cpu_info);
@@ -418,8 +432,11 @@ setup_arch (char **cmdline_p)
        unw_init();
 
 #ifdef CONFIG_XEN
-       if (is_running_on_xen())
+       if (is_running_on_xen()) {
                setup_xen_features();
+               /* Register a call for panic conditions. */
+               notifier_chain_register(&panic_notifier_list, &xen_panic_block);
+       }
 #endif
 
        ia64_patch_vtop((u64) __start___vtop_patchlist, (u64) 
__end___vtop_patchlist);
@@ -523,15 +540,14 @@ setup_arch (char **cmdline_p)
                shared_info_t *s = HYPERVISOR_shared_info;
 
                xen_start_info = __va(s->arch.start_info_pfn << PAGE_SHIFT);
-               xen_start_info->flags = s->arch.flags;
 
                printk("Running on Xen! start_info_pfn=0x%lx nr_pages=%ld "
                       "flags=0x%x\n", s->arch.start_info_pfn,
                       xen_start_info->nr_pages, xen_start_info->flags);
 
                /* xen_start_info isn't setup yet, get the flags manually */
-               if (s->arch.flags & SIF_INITDOMAIN) {
-                       if (!(s->arch.flags & SIF_PRIVILEGED))
+               if (xen_start_info->flags & SIF_INITDOMAIN) {
+                       if (!(xen_start_info->flags & SIF_PRIVILEGED))
                                panic("Xen granted us console access "
                                      "but not privileged status");
                } else {
diff -r a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S
--- a/linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S    Tue Aug 01 16:42:48 
2006 -0400
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S    Tue Aug 01 16:51:03 
2006 -0400
@@ -351,3 +351,59 @@ GLOBAL_ENTRY(xen_send_ipi)
         br.ret.sptk.many rp
         ;;
 END(xen_send_ipi)
+
+#ifdef CONFIG_XEN_IA64_VDSO_PARAVIRT
+// Those are vdso specialized.
+// In fsys mode, call, ret can't be used.
+GLOBAL_ENTRY(xen_rsm_be_i)
+       ld8 r22=[r22]
+       ;; 
+       st1 [r22]=r20
+       st4 [r23]=r0
+       XEN_HYPER_RSM_BE
+       st4 [r23]=r20
+       brl.cond.sptk   .vdso_rsm_be_i_ret
+       ;; 
+END(xen_rsm_be_i)
+
+GLOBAL_ENTRY(xen_get_psr)
+       mov r31=r8
+       mov r25=IA64_PSR_IC
+       st4 [r23]=r0
+       XEN_HYPER_GET_PSR
+       ;; 
+       st4 [r23]=r20
+       or r29=r8,r25 // vpsr.ic was cleared for hyperprivop
+       mov r8=r31
+       brl.cond.sptk   .vdso_get_psr_ret
+       ;; 
+END(xen_get_psr)
+
+GLOBAL_ENTRY(xen_ssm_i_0)
+       st4 [r22]=r20
+       ld4 r25=[r24]
+       ;;
+       cmp.ne.unc p11,p0=r0, r25
+       ;; 
+(p11)  st4 [r22]=r0
+(p11)  st4 [r23]=r0
+(p11)  XEN_HYPER_SSM_I
+       
+       brl.cond.sptk   .vdso_ssm_i_0_ret
+       ;; 
+END(xen_ssm_i_0)
+
+GLOBAL_ENTRY(xen_ssm_i_1)
+       st4 [r22]=r20
+       ld4 r25=[r24]
+       ;; 
+       cmp.ne.unc p11,p0=r0, r25
+       ;; 
+(p11)  st4 [r22]=r0
+(p11)  st4 [r23]=r0
+(p11)  XEN_HYPER_SSM_I
+       ;;
+       brl.cond.sptk   .vdso_ssm_i_1_ret
+       ;; 
+END(xen_ssm_i_1)
+#endif
diff -r a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c
--- a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c   Tue Aug 01 16:42:48 
2006 -0400
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c   Tue Aug 01 16:51:03 
2006 -0400
@@ -198,7 +198,7 @@ __xen_create_contiguous_region(unsigned 
                .nr_exchanged = 0
        };
 
-       if (order > MAX_CONTIG_ORDER)
+       if (unlikely(order > MAX_CONTIG_ORDER))
                return -ENOMEM;
        
        set_xen_guest_handle(exchange.in.extent_start, in_frames);
@@ -299,7 +299,7 @@ __xen_destroy_contiguous_region(unsigned
        if (!test_bit(start_gpfn, contiguous_bitmap))
                return;
 
-       if (order > MAX_CONTIG_ORDER)
+       if (unlikely(order > MAX_CONTIG_ORDER))
                return;
 
        set_xen_guest_handle(exchange.in.extent_start, &in_frame);
@@ -547,8 +547,10 @@ xen_ia64_privcmd_entry_mmap(struct vm_ar
        unsigned long gpfn;
        unsigned long flags;
 
-       BUG_ON((addr & ~PAGE_MASK) != 0);
-       BUG_ON(mfn == INVALID_MFN);
+       if ((addr & ~PAGE_MASK) != 0 || mfn == INVALID_MFN) {
+               error = -EINVAL;
+               goto out;
+       }
 
        if (entry->gpfn != INVALID_GPFN) {
                error = -EBUSY;
@@ -793,3 +795,13 @@ direct_remap_pfn_range(struct vm_area_st
        return error;
 }
 
+
+/* Called after suspend, to resume time.  */
+void
+time_resume(void)
+{
+       extern void ia64_cpu_local_tick(void);
+
+       /* Just trigger a tick.  */
+       ia64_cpu_local_tick();
+}
diff -r a75c389e4a7d -r 5ecfc7102cca linux-2.6-xen-sparse/arch/ia64/xen/util.c
--- a/linux-2.6-xen-sparse/arch/ia64/xen/util.c Tue Aug 01 16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/util.c Tue Aug 01 16:51:03 2006 -0400
@@ -71,6 +71,9 @@ void free_vm_area(struct vm_struct *area
        unsigned int order = get_order(area->size);
        unsigned long i;
 
+       /* xenbus_map_ring_valloc overrides this field!  */
+       area->phys_addr = __pa(area->addr);
+
        // This area is used for foreign page mappping.
        // So underlying machine page may not be assigned.
        for (i = 0; i < (1 << order); i++) {
diff -r a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S
--- a/linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S     Tue Aug 01 16:42:48 
2006 -0400
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S     Tue Aug 01 16:51:03 
2006 -0400
@@ -33,3 +33,23 @@ GLOBAL_ENTRY(early_xen_setup)
        br.ret.sptk.many rp
        ;;
 END(early_xen_setup)
+
+#include <xen/interface/xen.h>
+
+/* Stub for suspend.
+   Just force the stacked registers to be written in memory.  */       
+GLOBAL_ENTRY(HYPERVISOR_suspend)
+       alloc r20=ar.pfs,0,0,0,0
+       mov r14=2
+       mov r15=r12
+       ;;
+       /* We don't want to deal with RSE.  */
+       flushrs
+       mov r2=__HYPERVISOR_sched_op
+       st4 [r12]=r14
+       ;;
+       break 0x1000
+       ;; 
+       mov ar.pfs=r20
+       br.ret.sptk.many b0
+END(HYPERVISOR_suspend)
diff -r a75c389e4a7d -r 5ecfc7102cca linux-2.6-xen-sparse/arch/x86_64/Kconfig
--- a/linux-2.6-xen-sparse/arch/x86_64/Kconfig  Tue Aug 01 16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/arch/x86_64/Kconfig  Tue Aug 01 16:51:03 2006 -0400
@@ -330,7 +330,7 @@ config ARCH_DISCONTIGMEM_DEFAULT
 
 config ARCH_SPARSEMEM_ENABLE
        def_bool y
-       depends on (NUMA || EXPERIMENTAL)
+       depends on (NUMA || EXPERIMENTAL) && !X86_64_XEN
 
 config ARCH_MEMORY_PROBE
        def_bool y
diff -r a75c389e4a7d -r 5ecfc7102cca linux-2.6-xen-sparse/drivers/xen/Kconfig
--- a/linux-2.6-xen-sparse/drivers/xen/Kconfig  Tue Aug 01 16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig  Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca linux-2.6-xen-sparse/drivers/xen/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/Makefile Tue Aug 01 16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/Makefile Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/drivers/xen/console/console.c
--- a/linux-2.6-xen-sparse/drivers/xen/console/console.c        Tue Aug 01 
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c        Tue Aug 01 
16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/drivers/xen/core/reboot.c
--- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c    Tue Aug 01 16:42:48 
2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c    Tue Aug 01 16:51:03 
2006 -0400
@@ -19,14 +19,6 @@
 #include <xen/xencons.h>
 #include <xen/cpu_hotplug.h>
 
-#if defined(__i386__) || defined(__x86_64__)
-/*
- * Power off function, if any
- */
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
-#endif
-
 extern void ctrl_alt_del(void);
 
 #define SHUTDOWN_INVALID  -1
@@ -39,6 +31,14 @@ extern void ctrl_alt_del(void);
  */
 #define SHUTDOWN_HALT      4
 
+#if defined(__i386__) || defined(__x86_64__)
+
+/*
+ * Power off function, if any
+ */
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
 void machine_emergency_restart(void)
 {
        /* We really want to get pending console data out before we die. */
@@ -60,10 +60,8 @@ void machine_power_off(void)
 {
        /* We really want to get pending console data out before we die. */
        xencons_force_flush();
-#if defined(__i386__) || defined(__x86_64__)
        if (pm_power_off)
                pm_power_off();
-#endif
        HYPERVISOR_shutdown(SHUTDOWN_poweroff);
 }
 
@@ -72,6 +70,7 @@ EXPORT_SYMBOL(machine_halt);
 EXPORT_SYMBOL(machine_halt);
 EXPORT_SYMBOL(machine_power_off);
 
+#endif /* defined(__i386__) || defined(__x86_64__) */
 
 /******************************************************************************
  * Stop/pickle callback handling.
@@ -81,6 +80,8 @@ static int shutting_down = SHUTDOWN_INVA
 static int shutting_down = SHUTDOWN_INVALID;
 static void __shutdown_handler(void *unused);
 static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
+
+#if defined(__i386__) || defined(__x86_64__)
 
 /* Ensure we run on the idle task page tables so that we will
    switch page tables before running user space. This is needed
@@ -99,56 +100,21 @@ static void switch_idle_mm(void)
        mmdrop(mm);
 }
 
-static int __do_suspend(void *ignore)
-{
-       int i, j, k, fpp, err;
-
+static void pre_suspend(void)
+{
+       HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
+       clear_fixmap(FIX_SHARED_INFO);
+
+       xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
+       xen_start_info->console_mfn = mfn_to_pfn(xen_start_info->console_mfn);
+}
+
+static void post_suspend(void)
+{
+       int i, j, k, fpp;
        extern unsigned long max_pfn;
        extern unsigned long *pfn_to_mfn_frame_list_list;
        extern unsigned long *pfn_to_mfn_frame_list[];
-
-       extern void time_resume(void);
-
-       BUG_ON(smp_processor_id() != 0);
-       BUG_ON(in_interrupt());
-
-       if (xen_feature(XENFEAT_auto_translated_physmap)) {
-               printk(KERN_WARNING "Cannot suspend in "
-                      "auto_translated_physmap mode.\n");
-               return -EOPNOTSUPP;
-       }
-
-       err = smp_suspend();
-       if (err)
-               return err;
-
-       xenbus_suspend();
-
-       preempt_disable();
-
-#ifdef __i386__
-       kmem_cache_shrink(pgd_cache);
-#endif
-       mm_pin_all();
-
-       __cli();
-       preempt_enable();
-
-       gnttab_suspend();
-
-       HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
-       clear_fixmap(FIX_SHARED_INFO);
-
-       xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
-       xen_start_info->console_mfn = mfn_to_pfn(xen_start_info->console_mfn);
-
-       /*
-        * We'll stop somewhere inside this hypercall. When it returns,
-        * we'll start resuming after the restore.
-        */
-       HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
-
-       shutting_down = SHUTDOWN_INVALID;
 
        set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
 
@@ -171,6 +137,59 @@ static int __do_suspend(void *ignore)
                        virt_to_mfn(&phys_to_machine_mapping[i]);
        }
        HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
+}
+
+#else /* !(defined(__i386__) || defined(__x86_64__)) */
+
+#define switch_idle_mm()       ((void)0)
+#define mm_pin_all()           ((void)0)
+#define pre_suspend()          ((void)0)
+#define post_suspend()         ((void)0)
+
+#endif
+
+static int __do_suspend(void *ignore)
+{
+       int err;
+
+       extern void time_resume(void);
+
+       BUG_ON(smp_processor_id() != 0);
+       BUG_ON(in_interrupt());
+
+#if defined(__i386__) || defined(__x86_64__)
+       if (xen_feature(XENFEAT_auto_translated_physmap)) {
+               printk(KERN_WARNING "Cannot suspend in "
+                      "auto_translated_physmap mode.\n");
+               return -EOPNOTSUPP;
+       }
+#endif
+
+       err = smp_suspend();
+       if (err)
+               return err;
+
+       xenbus_suspend();
+
+       preempt_disable();
+
+       mm_pin_all();
+       local_irq_disable();
+       preempt_enable();
+
+       gnttab_suspend();
+
+       pre_suspend();
+
+       /*
+        * We'll stop somewhere inside this hypercall. When it returns,
+        * we'll start resuming after the restore.
+        */
+       HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
+
+       shutting_down = SHUTDOWN_INVALID;
+
+       post_suspend();
 
        gnttab_resume();
 
@@ -180,7 +199,7 @@ static int __do_suspend(void *ignore)
 
        switch_idle_mm();
 
-       __sti();
+       local_irq_enable();
 
        xencons_resume();
 
diff -r a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/drivers/xen/netback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c      Tue Aug 01 
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c      Tue Aug 01 
16:51:03 2006 -0400
@@ -76,6 +76,7 @@ static struct ethtool_ops network_ethtoo
 {
        .get_tx_csum = ethtool_op_get_tx_csum,
        .set_tx_csum = ethtool_op_set_tx_csum,
+       .get_link = ethtool_op_get_link,
 };
 
 netif_t *netif_alloc(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN])
diff -r a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/drivers/xen/netback/loopback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c       Tue Aug 01 
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c       Tue Aug 01 
16:51:03 2006 -0400
@@ -129,6 +129,7 @@ static struct ethtool_ops network_ethtoo
        .set_sg = ethtool_op_set_sg,
        .get_tso = ethtool_op_get_tso,
        .set_tso = ethtool_op_set_tso,
+       .get_link = ethtool_op_get_link,
 };
 
 /*
diff -r a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c        Tue Aug 01 
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c        Tue Aug 01 
16:51:03 2006 -0400
@@ -99,24 +99,21 @@ static spinlock_t net_schedule_list_lock
 #define MAX_MFN_ALLOC 64
 static unsigned long mfn_list[MAX_MFN_ALLOC];
 static unsigned int alloc_index = 0;
-static DEFINE_SPINLOCK(mfn_lock);
 
 static unsigned long alloc_mfn(void)
 {
-       unsigned long mfn = 0, flags;
+       unsigned long mfn = 0;
        struct xen_memory_reservation reservation = {
                .nr_extents   = MAX_MFN_ALLOC,
                .extent_order = 0,
                .domid        = DOMID_SELF
        };
        set_xen_guest_handle(reservation.extent_start, mfn_list);
-       spin_lock_irqsave(&mfn_lock, flags);
        if ( unlikely(alloc_index == 0) )
                alloc_index = HYPERVISOR_memory_op(
                        XENMEM_increase_reservation, &reservation);
        if ( alloc_index != 0 )
                mfn = mfn_list[--alloc_index];
-       spin_unlock_irqrestore(&mfn_lock, flags);
        return mfn;
 }
 
@@ -222,9 +219,13 @@ static void net_rx_action(unsigned long 
        unsigned long vdata, old_mfn, new_mfn;
        struct sk_buff_head rxq;
        struct sk_buff *skb;
-       u16 notify_list[NET_RX_RING_SIZE];
        int notify_nr = 0;
        int ret;
+       /*
+        * Putting hundreds of bytes on the stack is considered rude.
+        * Static works because a tasklet can only be on one CPU at any time.
+        */
+       static u16 notify_list[NET_RX_RING_SIZE];
 
        skb_queue_head_init(&rxq);
 
diff -r a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Tue Aug 01 
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Tue Aug 01 
16:51:03 2006 -0400
@@ -788,6 +788,8 @@ static int network_start_xmit(struct sk_
 
                gso->u.gso.size = skb_shinfo(skb)->gso_size;
                gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
+               gso->u.gso.pad = 0;
+               gso->u.gso.features = 0;
 
                gso->type = XEN_NETIF_EXTRA_TYPE_GSO;
                gso->flags = 0;
@@ -1201,6 +1203,7 @@ static struct ethtool_ops network_ethtoo
        .set_sg = xennet_set_sg,
        .get_tso = ethtool_op_get_tso,
        .set_tso = xennet_set_tso,
+       .get_link = ethtool_op_get_link,
 };
 
 #ifdef CONFIG_SYSFS
diff -r a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/drivers/xen/pciback/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/Makefile Tue Aug 01 16:42:48 
2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/Makefile Tue Aug 01 16:51:03 
2006 -0400
@@ -4,7 +4,8 @@ pciback-y += conf_space.o conf_space_hea
 pciback-y += conf_space.o conf_space_header.o \
             conf_space_capability.o \
             conf_space_capability_vpd.o \
-            conf_space_capability_pm.o
+            conf_space_capability_pm.o \
+             conf_space_quirks.o
 pciback-$(CONFIG_XEN_PCIDEV_BACKEND_VPCI) += vpci.o
 pciback-$(CONFIG_XEN_PCIDEV_BACKEND_PASS) += passthrough.o
 
diff -r a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c     Tue Aug 01 
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c     Tue Aug 01 
16:51:03 2006 -0400
@@ -13,9 +13,7 @@
 #include <linux/pci.h>
 #include "pciback.h"
 #include "conf_space.h"
-
-static int permissive = 0;
-module_param(permissive, bool, 0644);
+#include "conf_space_quirks.h"
 
 #define DEFINE_PCI_CONFIG(op,size,type)                        \
 int pciback_##op##_config_##size                               \
@@ -81,7 +79,7 @@ static int conf_space_write(struct pci_d
        case 4:
                if (field->u.dw.write)
                        ret = field->u.dw.write(dev, offset, value,
-                                               entry->data);
+                                               entry->data);
                break;
        }
        return ret;
@@ -257,40 +255,60 @@ int pciback_config_write(struct pci_dev 
                 * This means that some fields may still be read-only because
                 * they have entries in the config_field list that intercept
                 * the write and do nothing. */
-               if (permissive) {
+               if (dev_data->permissive) {
                        switch (size) {
                        case 1:
                                err = pci_write_config_byte(dev, offset,
-                                                           (u8)value);
+                                                           (u8) value);
                                break;
                        case 2:
                                err = pci_write_config_word(dev, offset,
-                                                           (u16)value);
+                                                           (u16) value);
                                break;
                        case 4:
                                err = pci_write_config_dword(dev, offset,
-                                                            (u32)value);
+                                                            (u32) value);
                                break;
                        }
                } else if (!dev_data->warned_on_write) {
                        dev_data->warned_on_write = 1;
-                       dev_warn(&dev->dev, "Driver wrote to a read-only "
-                                "configuration space field!\n");
-                       dev_warn(&dev->dev, "Write at offset 0x%x size %d\n",
-                               offset, size);
-                       dev_warn(&dev->dev, "This may be harmless, but if\n");
-                       dev_warn(&dev->dev, "you have problems with your "
-                                "device:\n");
-                       dev_warn(&dev->dev, "1) see the permissive "
-                                "attribute in sysfs.\n");
-                       dev_warn(&dev->dev, "2) report problems to the "
-                                "xen-devel mailing list along\n");
-                       dev_warn(&dev->dev, "   with details of your device "
-                                "obtained from lspci.\n");
+                       dev_warn(&dev->dev, "Driver tried to write to a "
+                                "read-only configuration space field at offset 
"
+                                "0x%x, size %d. This may be harmless, but if "
+                                "you have problems with your device:\n"
+                                "1) see permissive attribute in sysfs\n"
+                                "2) report problems to the xen-devel "
+                                "mailing list along with details of your "
+                                "device obtained from lspci.\n", offset, size);
                }
        }
 
        return pcibios_err_to_errno(err);
+}
+
+void pciback_config_free_dyn_fields(struct pci_dev *dev)
+{
+       struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
+       struct config_field_entry *cfg_entry, *t;
+       struct config_field *field;
+
+       dev_dbg(&dev->dev,
+               "free-ing dynamically allocated virtual configuration space 
fields\n");
+
+       list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
+               field = cfg_entry->field;
+
+               if (field->clean) {
+                       field->clean(field);
+
+                       if (cfg_entry->data)
+                               kfree(cfg_entry->data);
+
+                       list_del(&cfg_entry->list);
+                       kfree(cfg_entry);
+               }
+
+       }
 }
 
 void pciback_config_reset_dev(struct pci_dev *dev)
@@ -337,6 +355,10 @@ int pciback_config_add_field_offset(stru
        struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
        struct config_field_entry *cfg_entry;
        void *tmp;
+
+       /* silently ignore duplicate fields */
+       if (pciback_field_is_dup(dev, field->offset))
+               goto out;
 
        cfg_entry = kmalloc(sizeof(*cfg_entry), GFP_KERNEL);
        if (!cfg_entry) {
@@ -388,6 +410,10 @@ int pciback_config_init_dev(struct pci_d
                goto out;
 
        err = pciback_config_capability_add_fields(dev);
+       if (err)
+               goto out;
+
+       err = pciback_config_quirks_init(dev);
 
       out:
        return err;
@@ -395,9 +421,5 @@ int pciback_config_init_dev(struct pci_d
 
 int pciback_config_init(void)
 {
-       int err;
-
-       err = pciback_config_capability_init();
-
-       return err;
-}
+       return pciback_config_capability_init();
+}
diff -r a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.h
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.h     Tue Aug 01 
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.h     Tue Aug 01 
16:51:03 2006 -0400
@@ -33,11 +33,13 @@ typedef int (*conf_byte_read) (struct pc
  * values.
  */
 struct config_field {
-       unsigned int     offset;
-       unsigned int     size;
-       conf_field_init  init;
+       unsigned int offset;
+       unsigned int size;
+       unsigned int mask;
+       conf_field_init init;
        conf_field_reset reset;
-       conf_field_free  release;
+       conf_field_free release;
+       void (*clean) (struct config_field * field);
        union {
                struct {
                        conf_dword_write write;
@@ -52,6 +54,7 @@ struct config_field {
                        conf_byte_read read;
                } b;
        } u;
+       struct list_head list;
 };
 
 struct config_field_entry {
diff -r a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c       Tue Aug 01 
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c       Tue Aug 01 
16:51:03 2006 -0400
@@ -1,7 +1,8 @@
 /*
  * PCI Stub Driver - Grabs devices in backend to be exported later
  *
- *   Author: Ryan Wilson <hap9@xxxxxxxxxxxxxx>
+ * Ryan Wilson <hap9@xxxxxxxxxxxxxx>
+ * Chris Bookholt <hap10@xxxxxxxxxxxxxx>
  */
 #include <linux/module.h>
 #include <linux/init.h>
@@ -10,6 +11,8 @@
 #include <linux/kref.h>
 #include <asm/atomic.h>
 #include "pciback.h"
+#include "conf_space.h"
+#include "conf_space_quirks.h"
 
 static char *pci_devs_to_hide = NULL;
 module_param_named(hide, pci_devs_to_hide, charp, 0444);
@@ -31,6 +34,7 @@ struct pcistub_device {
        struct pci_dev *dev;
        struct pciback_device *pdev;    /* non-NULL if struct pci_dev is in use 
*/
 };
+
 /* Access to pcistub_devices & seized_devices lists and the initialize_devices
  * flag must be locked with pcistub_devices_lock
  */
@@ -76,6 +80,7 @@ static void pcistub_device_release(struc
 
        /* Clean-up the device */
        pciback_reset_device(psdev->dev);
+       pciback_config_free_dyn_fields(psdev->dev);
        pciback_config_free_dev(psdev->dev);
        kfree(pci_get_drvdata(psdev->dev));
        pci_set_drvdata(psdev->dev, NULL);
@@ -93,6 +98,32 @@ static inline void pcistub_device_put(st
 static inline void pcistub_device_put(struct pcistub_device *psdev)
 {
        kref_put(&psdev->kref, pcistub_device_release);
+}
+
+static struct pcistub_device *pcistub_device_find(int domain, int bus,
+                                                 int slot, int func)
+{
+       struct pcistub_device *psdev = NULL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+       list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+               if (psdev->dev != NULL
+                   && domain == pci_domain_nr(psdev->dev->bus)
+                   && bus == psdev->dev->bus->number
+                   && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
+                       pcistub_device_get(psdev);
+                       goto out;
+               }
+       }
+
+       /* didn't find it */
+       psdev = NULL;
+
+      out:
+       spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+       return psdev;
 }
 
 static struct pci_dev *pcistub_device_get_pci_dev(struct pciback_device *pdev,
@@ -180,6 +211,7 @@ void pcistub_put_pci_dev(struct pci_dev 
         * (so it's ready for the next domain)
         */
        pciback_reset_device(found_psdev->dev);
+       pciback_config_free_dyn_fields(found_psdev->dev);
        pciback_config_reset_dev(found_psdev->dev);
 
        spin_lock_irqsave(&found_psdev->lock, flags);
@@ -392,6 +424,8 @@ static void pcistub_remove(struct pci_de
 
        spin_lock_irqsave(&pcistub_devices_lock, flags);
 
+       pciback_config_quirk_release(dev);
+
        list_for_each_entry(psdev, &pcistub_devices, dev_list) {
                if (psdev->dev == dev) {
                        found_psdev = psdev;
@@ -471,6 +505,19 @@ static inline int str_to_slot(const char
        return -EINVAL;
 }
 
+static inline int str_to_quirk(const char *buf, int *domain, int *bus, int
+                              *slot, int *func, int *reg, int *size, int *mask)
+{
+       int err;
+
+       err =
+           sscanf(buf, " %04x:%02x:%02x.%1x-%08x:%1x:%08x", domain, bus, slot,
+                  func, reg, size, mask);
+       if (err == 7)
+               return 0;
+       return -EINVAL;
+}
+
 static int pcistub_device_id_add(int domain, int bus, int slot, int func)
 {
        struct pcistub_device_id *pci_dev_id;
@@ -523,6 +570,46 @@ static int pcistub_device_id_remove(int 
        return err;
 }
 
+static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg,
+                          int size, int mask)
+{
+       int err = 0;
+       struct pcistub_device *psdev;
+       struct pci_dev *dev;
+       struct config_field *field;
+
+       psdev = pcistub_device_find(domain, bus, slot, func);
+       if (!psdev || !psdev->dev) {
+               err = -ENODEV;
+               goto out;
+       }
+       dev = psdev->dev;
+
+       /* check for duplicate field */
+       if (pciback_field_is_dup(dev, reg))
+               goto out;
+
+       field = kzalloc(sizeof(*field), GFP_ATOMIC);
+       if (!field) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       field->offset = reg;
+       field->size = size;
+       field->mask = mask;
+       field->init = NULL;
+       field->reset = NULL;
+       field->release = NULL;
+       field->clean = pciback_config_field_free;
+
+       err = pciback_config_quirks_add_field(dev, field);
+       if (err)
+               kfree(field);
+      out:
+       return err;
+}
+
 static ssize_t pcistub_slot_add(struct device_driver *drv, const char *buf,
                                size_t count)
 {
@@ -586,6 +673,137 @@ static ssize_t pcistub_slot_show(struct 
 }
 
 DRIVER_ATTR(slots, S_IRUSR, pcistub_slot_show, NULL);
+
+static ssize_t pcistub_quirk_add(struct device_driver *drv, const char *buf,
+                                size_t count)
+{
+       int domain, bus, slot, func, reg, size, mask;
+       int err;
+
+       err = str_to_quirk(buf, &domain, &bus, &slot, &func, &reg, &size,
+                          &mask);
+       if (err)
+               goto out;
+
+       err = pcistub_reg_add(domain, bus, slot, func, reg, size, mask);
+
+      out:
+       if (!err)
+               err = count;
+       return err;
+}
+
+static ssize_t pcistub_quirk_show(struct device_driver *drv, char *buf)
+{
+       int count = 0;
+       unsigned long flags;
+       extern struct list_head pciback_quirks;
+       struct pciback_config_quirk *quirk;
+       struct pciback_dev_data *dev_data;
+       struct config_field *field;
+       struct config_field_entry *cfg_entry;
+
+       spin_lock_irqsave(&device_ids_lock, flags);
+       list_for_each_entry(quirk, &pciback_quirks, quirks_list) {
+               if (count >= PAGE_SIZE)
+                       goto out;
+
+               count += scnprintf(buf + count, PAGE_SIZE - count,
+                                  "%02x:%02x.%01x\n\t%04x:%04x:%04x:%04x\n",
+                                  quirk->pdev->bus->number,
+                                  PCI_SLOT(quirk->pdev->devfn),
+                                  PCI_FUNC(quirk->pdev->devfn),
+                                  quirk->devid.vendor, quirk->devid.device,
+                                  quirk->devid.subvendor,
+                                  quirk->devid.subdevice);
+
+               dev_data = pci_get_drvdata(quirk->pdev);
+
+               list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
+                       field = cfg_entry->field;
+                       if (count >= PAGE_SIZE)
+                               goto out;
+
+                       count += scnprintf(buf + count, PAGE_SIZE -
+                                          count, "\t\t%08x:%01x:%08x\n",
+                                          field->offset, field->size,
+                                          field->mask);
+               }
+       }
+
+      out:
+       spin_unlock_irqrestore(&device_ids_lock, flags);
+
+       return count;
+}
+
+DRIVER_ATTR(quirks, S_IRUSR | S_IWUSR, pcistub_quirk_show, pcistub_quirk_add);
+
+static ssize_t permissive_add(struct device_driver *drv, const char *buf,
+                             size_t count)
+{
+       int domain, bus, slot, func;
+       int err;
+       struct pcistub_device *psdev;
+       struct pciback_dev_data *dev_data;
+       err = str_to_slot(buf, &domain, &bus, &slot, &func);
+       if (err)
+               goto out;
+       psdev = pcistub_device_find(domain, bus, slot, func);
+       if (!psdev) {
+               err = -ENODEV;
+               goto out;
+       }
+       if (!psdev->dev) {
+               err = -ENODEV;
+               goto release;
+       }
+       dev_data = pci_get_drvdata(psdev->dev);
+       /* the driver data for a device should never be null at this point */
+       if (!dev_data) {
+               err = -ENXIO;
+               goto release;
+       }
+       if (!dev_data->permissive) {
+               dev_data->permissive = 1;
+               /* Let user know that what they're doing could be unsafe */
+               dev_warn(&psdev->dev->dev,
+                        "enabling permissive mode configuration space 
accesses!\n");
+               dev_warn(&psdev->dev->dev,
+                        "permissive mode is potentially unsafe!\n");
+       }
+      release:
+       pcistub_device_put(psdev);
+      out:
+       if (!err)
+               err = count;
+       return err;
+}
+
+static ssize_t permissive_show(struct device_driver *drv, char *buf)
+{
+       struct pcistub_device *psdev;
+       struct pciback_dev_data *dev_data;
+       size_t count = 0;
+       unsigned long flags;
+       spin_lock_irqsave(&pcistub_devices_lock, flags);
+       list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+               if (count >= PAGE_SIZE)
+                       break;
+               if (!psdev->dev)
+                       continue;
+               dev_data = pci_get_drvdata(psdev->dev);
+               if (!dev_data || !dev_data->permissive)
+                       continue;
+               count +=
+                   scnprintf(buf + count, PAGE_SIZE - count, "%s\n",
+                             pci_name(psdev->dev));
+       }
+       spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+       return count;
+}
+
+DRIVER_ATTR(permissive, S_IRUSR | S_IWUSR, permissive_show, permissive_add);
 
 static int __init pcistub_init(void)
 {
@@ -631,6 +849,8 @@ static int __init pcistub_init(void)
        driver_create_file(&pciback_pci_driver.driver,
                           &driver_attr_remove_slot);
        driver_create_file(&pciback_pci_driver.driver, &driver_attr_slots);
+       driver_create_file(&pciback_pci_driver.driver, &driver_attr_quirks);
+       driver_create_file(&pciback_pci_driver.driver, &driver_attr_permissive);
 
       out:
        return err;
@@ -680,6 +900,8 @@ static void __exit pciback_cleanup(void)
        driver_remove_file(&pciback_pci_driver.driver,
                           &driver_attr_remove_slot);
        driver_remove_file(&pciback_pci_driver.driver, &driver_attr_slots);
+       driver_remove_file(&pciback_pci_driver.driver, &driver_attr_quirks);
+       driver_remove_file(&pciback_pci_driver.driver, &driver_attr_permissive);
 
        pci_unregister_driver(&pciback_pci_driver);
 }
diff -r a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h        Tue Aug 01 
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h        Tue Aug 01 
16:51:03 2006 -0400
@@ -44,6 +44,7 @@ struct pciback_device {
 
 struct pciback_dev_data {
        struct list_head config_fields;
+       int permissive;
        int warned_on_write;
 };
 
@@ -61,6 +62,7 @@ void pciback_reset_device(struct pci_dev
 /* Access a virtual configuration space for a PCI device */
 int pciback_config_init(void);
 int pciback_config_init_dev(struct pci_dev *dev);
+void pciback_config_free_dyn_fields(struct pci_dev *dev);
 void pciback_config_reset_dev(struct pci_dev *dev);
 void pciback_config_free_dev(struct pci_dev *dev);
 int pciback_config_read(struct pci_dev *dev, int offset, int size,
diff -r a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c        Tue Aug 01 
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c        Tue Aug 01 
16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca 
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 Aug 
01 16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h  Tue Aug 
01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/include/asm-ia64/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Tue Aug 01 16:42:48 
2006 -0400
+++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Tue Aug 01 16:51:03 
2006 -0400
@@ -302,23 +302,7 @@ HYPERVISOR_vcpu_op(
     return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
 }
 
-static inline int
-HYPERVISOR_suspend(
-       unsigned long srec)
-{
-       struct sched_shutdown sched_shutdown = {
-               .reason = SHUTDOWN_suspend
-       };
-
-       int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
-                            &sched_shutdown, srec);
-
-       if (rc == -ENOSYS)
-               rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
-                                SHUTDOWN_suspend, srec);
-
-       return rc;
-}
+extern int HYPERVISOR_suspend(unsigned long srec);
 
 static inline int
 HYPERVISOR_callback_op(
diff -r a75c389e4a7d -r 5ecfc7102cca 
linux-2.6-xen-sparse/include/asm-ia64/xen/privop.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/xen/privop.h        Tue Aug 01 
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/include/asm-ia64/xen/privop.h        Tue Aug 01 
16:51:03 2006 -0400
@@ -48,6 +48,8 @@
 #define        XEN_HYPER_GET_PMD               break HYPERPRIVOP_GET_PMD
 #define        XEN_HYPER_GET_EFLAG             break HYPERPRIVOP_GET_EFLAG
 #define        XEN_HYPER_SET_EFLAG             break HYPERPRIVOP_SET_EFLAG
+#define        XEN_HYPER_RSM_BE                break HYPERPRIVOP_RSM_BE
+#define        XEN_HYPER_GET_PSR               break HYPERPRIVOP_GET_PSR
 
 #define XSI_IFS                        (XSI_BASE + XSI_IFS_OFS)
 #define XSI_PRECOVER_IFS       (XSI_BASE + XSI_PRECOVER_IFS_OFS)
diff -r a75c389e4a7d -r 5ecfc7102cca linux-2.6-xen-sparse/include/linux/skbuff.h
--- a/linux-2.6-xen-sparse/include/linux/skbuff.h       Tue Aug 01 16:42:48 
2006 -0400
+++ b/linux-2.6-xen-sparse/include/linux/skbuff.h       Tue Aug 01 16:51:03 
2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca linux-2.6-xen-sparse/net/core/dev.c
--- a/linux-2.6-xen-sparse/net/core/dev.c       Tue Aug 01 16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/net/core/dev.c       Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca patches/linux-2.6.16.13/net-csum.patch
--- a/patches/linux-2.6.16.13/net-csum.patch    Tue Aug 01 16:42:48 2006 -0400
+++ b/patches/linux-2.6.16.13/net-csum.patch    Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca 
patches/linux-2.6.16.13/xenoprof-generic.patch
--- a/patches/linux-2.6.16.13/xenoprof-generic.patch    Tue Aug 01 16:42:48 
2006 -0400
+++ b/patches/linux-2.6.16.13/xenoprof-generic.patch    Tue Aug 01 16:51:03 
2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/Makefile
--- a/tools/Makefile    Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/Makefile    Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/domctrl/DomU.dts.in
--- a/tools/domctrl/DomU.dts.in Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/domctrl/DomU.dts.in Tue Aug 01 16:51:03 2006 -0400
@@ -66,7 +66,7 @@
                linux,platform = <501>;
                linux,initrd-start = <@INITRD_START@>;
                linux,initrd-end = <@INITRD_END@>;
-               linux,stdout-package = "&/xen/console";
+               linux,stdout-package = <&/xen/console>;
                linux,stdout-path = "/xen/console";
                interrupt-controller = <&/xen>;
                cpu = <&/cpus/@CPU_TYPE@@0>;
diff -r a75c389e4a7d -r 5ecfc7102cca tools/domctrl/DomU.sh
--- a/tools/domctrl/DomU.sh     Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/domctrl/DomU.sh     Tue Aug 01 16:51:03 2006 -0400
@@ -19,7 +19,7 @@ s%@DOMAIN_NAME@%$DOMAIN_NAME%g;
 s%@DOMAIN_NAME@%$DOMAIN_NAME%g;
 s%@DOMAIN_ID@%$DOMAIN_ID%g;
 s%@MODEL@%$MODEL%g;
-s%@COMAPTIBLE@%$COMPATIBLE%g;
+s%@COMPATIBLE@%$COMPATIBLE%g;
 s%@BOOTARGS@%$BOOTARGS%g;
 s%@INITRD_START@%$INITRD_START%g;
 s%@INITRD_END@%$INITRD_END%g;
diff -r a75c389e4a7d -r 5ecfc7102cca tools/examples/Makefile
--- a/tools/examples/Makefile   Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/examples/Makefile   Tue Aug 01 16:51:03 2006 -0400
@@ -18,6 +18,8 @@ XEN_CONFIGS += xmexample2
 XEN_CONFIGS += xmexample2
 XEN_CONFIGS += xmexample.hvm
 XEN_CONFIGS += xmexample.vti
+XEN_CONFIGS += xend-pci-quirks.sxp
+XEN_CONFIGS += xend-pci-permissive.sxp
 
 # Xen script dir and scripts to go there.
 XEN_SCRIPT_DIR = /etc/xen/scripts
@@ -26,7 +28,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 a75c389e4a7d -r 5ecfc7102cca tools/examples/README
--- a/tools/examples/README     Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/examples/README     Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/examples/vtpm-common.sh
--- a/tools/examples/vtpm-common.sh     Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/examples/vtpm-common.sh     Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/examples/vtpm-impl
--- a/tools/examples/vtpm-impl  Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/examples/vtpm-impl  Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/examples/xen-backend.agent
--- a/tools/examples/xen-backend.agent  Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/examples/xen-backend.agent  Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/examples/xen-backend.rules
--- a/tools/examples/xen-backend.rules  Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/examples/xen-backend.rules  Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/examples/xmexample.hvm
--- a/tools/examples/xmexample.hvm      Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/examples/xmexample.hvm      Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/firmware/vmxassist/vmxassist.ld
--- a/tools/firmware/vmxassist/vmxassist.ld     Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/firmware/vmxassist/vmxassist.ld     Tue Aug 01 16:51:03 2006 -0400
@@ -11,8 +11,7 @@ SECTIONS
                _btext = .;
                *(.text)
                *(.rodata)
-               *(.rodata.str1.1)
-               *(.rodata.str1.4)
+               *(.rodata.*)
                _etext = .;
        }
 
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/Changelog
--- a/tools/ioemu/Changelog     Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/Changelog     Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/ioemu/Makefile
--- a/tools/ioemu/Makefile      Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/Makefile      Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/ioemu/README
--- a/tools/ioemu/README        Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/README        Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/ioemu/TODO
--- a/tools/ioemu/TODO  Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/TODO  Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/ioemu/VERSION
--- a/tools/ioemu/VERSION       Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/VERSION       Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/audio.c
--- a/tools/ioemu/audio/audio.c Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/audio.c Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/audio.h
--- a/tools/ioemu/audio/audio.h Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/audio.h Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/audio_int.h
--- a/tools/ioemu/audio/audio_int.h     Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/audio_int.h     Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/mixeng.c
--- a/tools/ioemu/audio/mixeng.c        Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/mixeng.c        Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/mixeng.h
--- a/tools/ioemu/audio/mixeng.h        Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/mixeng.h        Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/mixeng_template.h
--- a/tools/ioemu/audio/mixeng_template.h       Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/mixeng_template.h       Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/noaudio.c
--- a/tools/ioemu/audio/noaudio.c       Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/noaudio.c       Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/ossaudio.c
--- a/tools/ioemu/audio/ossaudio.c      Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/ossaudio.c      Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/sdlaudio.c
--- a/tools/ioemu/audio/sdlaudio.c      Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/sdlaudio.c      Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/wavaudio.c
--- a/tools/ioemu/audio/wavaudio.c      Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/wavaudio.c      Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/ioemu/block-cloop.c
--- a/tools/ioemu/block-cloop.c Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/block-cloop.c Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/ioemu/block-cow.c
--- a/tools/ioemu/block-cow.c   Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/block-cow.c   Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/ioemu/block-qcow.c
--- a/tools/ioemu/block-qcow.c  Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/block-qcow.c  Tue Aug 01 16:51:03 2006 -0400
@@ -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 a75c389e4a7d -r 5ecfc7102cca tools/ioemu/block-vmdk.c
--- a/tools/ioemu/block-vmdk.c  Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/block-vmdk.c  Tue Aug 01 16:51:03 2006 -0400
@@ -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);

_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel

<Prev in Thread] Current Thread [Next in Thread>
  • [XenPPC] [xenppc-unstable] merge with http://xenbits.xensource.com/ext/xenppc-unstable.hg, Xen patchbot-xenppc-unstable <=