[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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



# 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


 


Rackspace

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