[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Add qemu 0.8.1 based ioemu.
# HG changeset patch # User chris@xxxxxxxxxxxxxxxxxxxxxxxx # Node ID b450f21472a0574fbc382f2f84ea0a8295aa6423 # Parent bd68ce5a3f0cb22e12a860fb20846c35cce68bf2 Add qemu 0.8.1 based ioemu. Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxxx> --- .hgignore | 18 tools/ioemu/.cvsignore | 29 tools/ioemu/COPYING | 339 + tools/ioemu/COPYING.LIB | 504 ++ tools/ioemu/CVS/Entries | 109 tools/ioemu/CVS/Repository | 1 tools/ioemu/CVS/Root | 1 tools/ioemu/CVS/Tag | 1 tools/ioemu/Changelog | 376 + tools/ioemu/LICENSE | 12 tools/ioemu/Makefile | 149 tools/ioemu/Makefile.target | 531 ++ tools/ioemu/README | 3 tools/ioemu/README.distrib | 16 tools/ioemu/TODO | 61 tools/ioemu/VERSION | 1 tools/ioemu/a.out.h | 431 + tools/ioemu/aes.c | 1317 +++++ tools/ioemu/aes.h | 26 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 | 1481 ++++++ tools/ioemu/audio/audio.h | 133 tools/ioemu/audio/audio_int.h | 268 + 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 | 277 + tools/ioemu/audio/mixeng.h | 51 tools/ioemu/audio/mixeng_template.h | 177 tools/ioemu/audio/noaudio.c | 170 tools/ioemu/audio/ossaudio.c | 762 +++ tools/ioemu/audio/rate_template.h | 111 tools/ioemu/audio/sdlaudio.c | 437 + tools/ioemu/audio/sys-queue.h | 241 + tools/ioemu/audio/wavaudio.c | 255 + tools/ioemu/block-bochs.c | 224 tools/ioemu/block-cloop.c | 169 tools/ioemu/block-cow.c | 264 + tools/ioemu/block-dmg.c | 297 + tools/ioemu/block-qcow.c | 710 ++ tools/ioemu/block-vmdk.c | 439 + tools/ioemu/block-vpc.c | 242 + tools/ioemu/block-vvfat.c | 2807 +++++++++++ tools/ioemu/block.c | 797 +++ tools/ioemu/block_int.h | 80 tools/ioemu/bswap.h | 202 tools/ioemu/cocoa.m | 911 +++ tools/ioemu/configure | 896 +++ tools/ioemu/console.c | 1008 ++++ tools/ioemu/cpu-all.h | 944 +++ tools/ioemu/cpu-defs.h | 125 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 | 605 ++ tools/ioemu/exec.c | 2379 +++++++++ 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 | 410 + tools/ioemu/hw/adlib.c | 341 + 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 | 3311 +++++++++++++ tools/ioemu/hw/cirrus_vga_rop.h | 78 tools/ioemu/hw/cirrus_vga_rop2.h | 281 + tools/ioemu/hw/cuda.c | 656 ++ tools/ioemu/hw/dma.c | 537 ++ tools/ioemu/hw/es1370.c | 1062 ++++ tools/ioemu/hw/esp.c | 747 +++ tools/ioemu/hw/fdc.c | 1757 +++++++ tools/ioemu/hw/fmopl.c | 1390 +++++ tools/ioemu/hw/fmopl.h | 174 tools/ioemu/hw/heathrow_pic.c | 168 tools/ioemu/hw/i8254.c | 482 ++ tools/ioemu/hw/i8259.c | 561 ++ tools/ioemu/hw/ide.c | 2726 +++++++++++ tools/ioemu/hw/integratorcp.c | 546 ++ tools/ioemu/hw/iommu.c | 258 + tools/ioemu/hw/lance.c | 462 + tools/ioemu/hw/m48t59.c | 608 ++ tools/ioemu/hw/m48t59.h | 13 tools/ioemu/hw/mc146818rtc.c | 486 ++ tools/ioemu/hw/mips_r4k.c | 295 + tools/ioemu/hw/ne2000.c | 816 +++ tools/ioemu/hw/openpic.c | 1027 ++++ tools/ioemu/hw/parallel.c | 183 tools/ioemu/hw/pc.c | 927 +++ tools/ioemu/hw/pci.c | 1872 +++++++ tools/ioemu/hw/pckbd.c | 370 + tools/ioemu/hw/pcspk.c | 147 tools/ioemu/hw/piix4acpi.c | 484 ++ 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 | 428 + tools/ioemu/hw/ppc_chrp.c | 564 ++ tools/ioemu/hw/ppc_prep.c | 690 ++ tools/ioemu/hw/ps2.c | 566 ++ tools/ioemu/hw/rtl8139.c | 2875 ++++++++++++ tools/ioemu/hw/sb16.c | 1415 +++++ tools/ioemu/hw/serial.c | 456 + 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 | 324 + tools/ioemu/hw/sun4u.c | 376 + tools/ioemu/hw/tc58128.c | 181 tools/ioemu/hw/tcx.c | 330 + tools/ioemu/hw/usb-hid.c | 537 ++ tools/ioemu/hw/usb-hub.c | 549 ++ tools/ioemu/hw/usb-uhci.c | 680 ++ tools/ioemu/hw/usb.c | 193 tools/ioemu/hw/usb.h | 166 tools/ioemu/hw/versatilepb.c | 271 + tools/ioemu/hw/vga.c | 2029 ++++++++ tools/ioemu/hw/vga_int.h | 172 tools/ioemu/hw/vga_template.h | 519 ++ 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/keymaps/ar | 98 tools/ioemu/keymaps/common | 157 tools/ioemu/keymaps/da | 120 tools/ioemu/keymaps/de | 114 tools/ioemu/keymaps/de-ch | 169 tools/ioemu/keymaps/en-gb | 119 tools/ioemu/keymaps/en-us | 35 tools/ioemu/keymaps/es | 105 tools/ioemu/keymaps/et | 86 tools/ioemu/keymaps/fi | 124 tools/ioemu/keymaps/fo | 77 tools/ioemu/keymaps/fr | 181 tools/ioemu/keymaps/fr-be | 140 tools/ioemu/keymaps/fr-ca | 50 tools/ioemu/keymaps/fr-ch | 114 tools/ioemu/keymaps/hr | 125 tools/ioemu/keymaps/hu | 115 tools/ioemu/keymaps/is | 140 tools/ioemu/keymaps/it | 115 tools/ioemu/keymaps/ja | 104 tools/ioemu/keymaps/lt | 57 tools/ioemu/keymaps/lv | 128 tools/ioemu/keymaps/mk | 101 tools/ioemu/keymaps/modifiers | 17 tools/ioemu/keymaps/nl | 60 tools/ioemu/keymaps/nl-be | 3 tools/ioemu/keymaps/no | 119 tools/ioemu/keymaps/pl | 122 tools/ioemu/keymaps/pt | 113 tools/ioemu/keymaps/pt-br | 69 tools/ioemu/keymaps/ru | 109 tools/ioemu/keymaps/sl | 110 tools/ioemu/keymaps/sv | 82 tools/ioemu/keymaps/th | 131 tools/ioemu/keymaps/tr | 123 tools/ioemu/kqemu.c | 900 +++ tools/ioemu/kqemu.h | 132 tools/ioemu/loader.c | 235 tools/ioemu/monitor.c | 2335 +++++++++ tools/ioemu/osdep.c | 628 ++ tools/ioemu/osdep.h | 53 tools/ioemu/patches/acpi-poweroff-support | 26 tools/ioemu/patches/acpi-support | 58 tools/ioemu/patches/acpi-timer-support | 43 tools/ioemu/patches/domain-destroy | 24 tools/ioemu/patches/domain-reset | 45 tools/ioemu/patches/domain-timeoffset | 138 tools/ioemu/patches/hypervisor-pit | 48 tools/ioemu/patches/ide-hd-multithread | 75 tools/ioemu/patches/qemu-64bit | 80 tools/ioemu/patches/qemu-bugfixes | 19 tools/ioemu/patches/qemu-cleanup | 66 tools/ioemu/patches/qemu-dm | 385 + tools/ioemu/patches/qemu-hvm-banner | 19 tools/ioemu/patches/qemu-infrastructure | 9 tools/ioemu/patches/qemu-logging | 57 tools/ioemu/patches/qemu-no-apic | 42 tools/ioemu/patches/qemu-nobios | 48 tools/ioemu/patches/qemu-smp | 38 tools/ioemu/patches/qemu-target-i386-dm | 115 tools/ioemu/patches/qemu-timer | 37 tools/ioemu/patches/sdl-mouse-invisible-wall | 17 tools/ioemu/patches/serial-non-block | 23 tools/ioemu/patches/series | 32 tools/ioemu/patches/shadow-vram | 32 tools/ioemu/patches/shared-vram | 123 tools/ioemu/patches/support-xm-console | 37 tools/ioemu/patches/vnc-cleanup | 63 tools/ioemu/patches/vnc-fixes | 317 + tools/ioemu/patches/xen-build | 171 tools/ioemu/patches/xen-domain-name | 64 tools/ioemu/patches/xen-domid | 37 tools/ioemu/patches/xen-mm | 61 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 | 39 tools/ioemu/qemu-doc.texi | 1748 +++++++ tools/ioemu/qemu-img.c | 699 ++ tools/ioemu/qemu-img.texi | 126 tools/ioemu/qemu-tech.texi | 595 ++ tools/ioemu/qemu_socket.h | 30 tools/ioemu/readline.c | 425 + tools/ioemu/sdl.c | 556 ++ tools/ioemu/sdl_keysym.h | 278 + tools/ioemu/softmmu_exec.h | 65 tools/ioemu/softmmu_header.h | 385 + tools/ioemu/softmmu_template.h | 313 + tools/ioemu/tap-win32.c | 680 ++ tools/ioemu/target-i386-dm/cpu.h | 86 tools/ioemu/target-i386-dm/exec-dm.c | 512 ++ tools/ioemu/target-i386-dm/helper2.c | 507 ++ tools/ioemu/target-i386-dm/i8259-dm.c | 107 tools/ioemu/target-i386-dm/qemu-dm.debug | 5 tools/ioemu/target-i386-dm/qemu-ifup | 10 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 | 243 + tools/ioemu/thunk.h | 158 tools/ioemu/translate-all.c | 311 + tools/ioemu/translate-op.c | 37 tools/ioemu/usb-linux.c | 488 ++ tools/ioemu/vgafont.h | 4611 +++++++++++++++++++ tools/ioemu/vl.c | 6001 +++++++++++++++++++++++++ tools/ioemu/vl.h | 1111 ++++ tools/ioemu/vnc.c | 1001 ++++ tools/ioemu/vnc_keysym.h | 275 + tools/ioemu/vnchextile.h | 189 tools/ioemu/x86_64.ld | 171 319 files changed, 149548 insertions(+), 6 deletions(-) diff -r bd68ce5a3f0c -r b450f21472a0 .hgignore --- a/.hgignore Wed Jul 12 19:16:07 2006 +0100 +++ b/.hgignore Wed Jul 12 19:16:10 2006 +0100 @@ -123,12 +123,18 @@ ^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/misc/cpuperf/cpuperf-perfcntr$ ^tools/misc/cpuperf/cpuperf-xen$ diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/.cvsignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/.cvsignore Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,29 @@ +arm-user +arm-softmmu +armeb-user +config-host.* +dyngen +i386 +i386-softmmu +i386-user +ppc-softmmu +ppc64-softmmu +ppc-user +qemu-doc.html +qemu-tech.html +qemu.1 +qemu.pod +qemu-img.1 +qemu-img.pod +sparc-user +qemu-img +sparc-softmmu +x86_64-softmmu +sparc64-user +sparc64-softmmu +mips-softmmu +mipsel-softmmu +mips-user +mipsel-user +sh4-user +sh4-softmmu diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/COPYING --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/COPYING Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/COPYING.LIB --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/COPYING.LIB Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/CVS/Entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/CVS/Entries Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,109 @@ +D/audio//// +D/hw//// +D/linux-user//// +D/pc-bios//// +D/slirp//// +D/target-arm//// +D/target-i386//// +D/target-ppc//// +D/target-sparc//// +D/tests//// +D/fpu//// +D/keymaps//// +D/target-mips//// +/.cvsignore/1.13/Thu May 25 18:22:25 2006//Trelease_0_8_1 +/COPYING/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1 +/COPYING.LIB/1.2/Wed May 17 14:47:01 2006//Trelease_0_8_1 +/Changelog/1.116/Thu May 25 18:22:25 2006//Trelease_0_8_1 +/LICENSE/1.2/Sat Feb 12 14:45:23 2005//Trelease_0_8_1 +/Makefile/1.99/Thu May 25 18:22:25 2006//Trelease_0_8_1 +/Makefile.target/1.107/Thu May 25 18:22:25 2006//Trelease_0_8_1 +/README/1.12/Wed May 24 10:40:08 2006//Trelease_0_8_1 +/README.distrib/1.2/Wed May 17 14:47:01 2006//Trelease_0_8_1 +/TODO/1.38/Thu May 25 18:22:25 2006//Trelease_0_8_1 +/VERSION/1.28/Thu May 25 18:22:25 2006//Trelease_0_8_1 +/a.out.h/1.2/Wed May 24 10:40:08 2006//Trelease_0_8_1 +/aes.c/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1 +/aes.h/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1 +/alpha-dis.c/1.3/Thu May 25 18:22:25 2006//Trelease_0_8_1 +/alpha.ld/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1 +/arm-dis.c/1.3/Wed May 24 10:40:08 2006//Trelease_0_8_1 +/arm.ld/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1 +/block-bochs.c/1.1/Tue Apr 26 21:34:00 2005//Trelease_0_8_1 +/block-cloop.c/1.3/Thu May 25 18:22:25 2006//Trelease_0_8_1 +/block-cow.c/1.5/Thu May 25 12:38:49 2006//Trelease_0_8_1 +/block-dmg.c/1.4/Thu May 25 18:22:25 2006//Trelease_0_8_1 +/block-qcow.c/1.6/Thu May 25 18:22:25 2006//Trelease_0_8_1 +/block-vmdk.c/1.7/Thu May 25 18:22:25 2006//Trelease_0_8_1 +/block-vpc.c/1.2/Thu May 25 12:38:49 2006//Trelease_0_8_1 +/block-vvfat.c/1.5/Thu May 25 18:22:25 2006//Trelease_0_8_1 +/block.c/1.26/Thu May 25 18:22:26 2006//Trelease_0_8_1 +/block_int.h/1.4/Thu May 25 18:22:26 2006//Trelease_0_8_1 +/bswap.h/1.5/Wed May 17 14:47:01 2006//Trelease_0_8_1 +/cocoa.m/1.8/Thu May 25 18:22:26 2006//Trelease_0_8_1 +/configure/1.100/Thu May 25 18:22:26 2006//Trelease_0_8_1 +/console.c/1.5/Thu May 25 18:22:26 2006//Trelease_0_8_1 +/cpu-all.h/1.54/Thu May 25 18:22:26 2006//Trelease_0_8_1 +/cpu-defs.h/1.15/Thu May 25 18:22:26 2006//Trelease_0_8_1 +/cpu-exec.c/1.78/Thu May 25 18:22:26 2006//Trelease_0_8_1 +/dis-asm.h/1.11/Thu May 25 18:22:26 2006//Trelease_0_8_1 +/disas.c/1.30/Thu May 25 18:22:26 2006//Trelease_0_8_1 +/disas.h/1.7/Thu May 25 18:22:26 2006//Trelease_0_8_1 +/dyngen-exec.h/1.27/Thu May 25 18:22:26 2006//Trelease_0_8_1 +/dyngen-op.h/1.1/Mon Jan 3 23:40:55 2005//Trelease_0_8_1 +/dyngen.c/1.42/Thu May 25 18:22:26 2006//Trelease_0_8_1 +/dyngen.h/1.10/Thu May 25 18:22:26 2006//Trelease_0_8_1 +/elf.h/1.6/Thu May 25 12:38:50 2006//Trelease_0_8_1 +/elf_ops.h/1.3/Tue May 2 20:54:12 2006//Trelease_0_8_1 +/exec-all.h/1.47/Thu May 25 18:22:26 2006//Trelease_0_8_1 +/exec.c/1.79/Thu May 25 18:22:26 2006//Trelease_0_8_1 +/gdbstub.c/1.36/Thu May 25 18:22:26 2006//Trelease_0_8_1 +/gdbstub.h/1.2/Tue Apr 26 20:42:36 2005//Trelease_0_8_1 +/i386-dis.c/1.5/Wed May 17 14:47:01 2006//Trelease_0_8_1 +/i386-vl.ld/1.3/Wed May 17 14:47:01 2006//Trelease_0_8_1 +/i386.ld/1.2/Wed May 17 14:47:01 2006//Trelease_0_8_1 +/ia64.ld/1.1/Thu Apr 7 22:20:28 2005//Trelease_0_8_1 +/keymaps.c/1.2/Thu May 25 18:22:26 2006//Trelease_0_8_1 +/kqemu.c/1.10/Thu May 25 18:22:26 2006//Trelease_0_8_1 +/kqemu.h/1.1/Wed Feb 8 22:39:17 2006//Trelease_0_8_1 +/linux-2.6.9-qemu-fast.patch/1.1/Wed Dec 8 23:48:11 2004//Trelease_0_8_1 +/loader.c/1.2/Wed Apr 26 22:05:26 2006//Trelease_0_8_1 +/m68k-dis.c/1.1/Sun Nov 6 16:52:11 2005//Trelease_0_8_1 +/m68k.ld/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1 +/mips-dis.c/1.3/Thu May 25 18:22:28 2006//Trelease_0_8_1 +/monitor.c/1.48/Thu May 25 18:22:28 2006//Trelease_0_8_1 +/osdep.c/1.10/Wed May 24 10:40:10 2006//Trelease_0_8_1 +/osdep.h/1.5/Wed May 24 10:40:10 2006//Trelease_0_8_1 +/ppc-dis.c/1.7/Thu May 25 12:38:51 2006//Trelease_0_8_1 +/ppc.ld/1.2/Thu May 25 12:38:51 2006//Trelease_0_8_1 +/qemu-binfmt-conf.sh/1.4/Thu May 25 18:22:28 2006//Trelease_0_8_1 +/qemu-doc.texi/1.87/Thu May 25 18:22:29 2006//Trelease_0_8_1 +/qemu-img.c/1.8/Thu May 25 12:38:51 2006//Trelease_0_8_1 +/qemu-img.texi/1.2/Thu May 25 12:38:51 2006//Trelease_0_8_1 +/qemu-tech.texi/1.9/Thu May 25 18:22:29 2006//Trelease_0_8_1 +/qemu_socket.h/1.1/Sun Apr 30 22:53:25 2006//Trelease_0_8_1 +/readline.c/1.1/Tue May 23 19:16:56 2006//Trelease_0_8_1 +/s390.ld/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1 +/sdl.c/1.26/Thu May 25 18:22:29 2006//Trelease_0_8_1 +/sdl_keysym.h/1.3/Tue Mar 1 21:43:41 2005//Trelease_0_8_1 +/sh4-dis.c/1.1/Thu Apr 27 21:05:14 2006//Trelease_0_8_1 +/softmmu_exec.h/1.1/Sun Oct 30 18:16:26 2005//Trelease_0_8_1 +/softmmu_header.h/1.13/Thu May 25 18:22:29 2006//Trelease_0_8_1 +/softmmu_template.h/1.16/Thu May 25 18:22:29 2006//Trelease_0_8_1 +/sparc-dis.c/1.2/Thu May 25 18:22:29 2006//Trelease_0_8_1 +/sparc.ld/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1 +/tap-win32.c/1.2/Sun Feb 19 12:40:00 2006//Trelease_0_8_1 +/texi2pod.pl/1.1/Wed May 17 14:47:02 2006//Trelease_0_8_1 +/thunk.c/1.6/Wed May 24 10:40:10 2006//Trelease_0_8_1 +/thunk.h/1.13/Wed May 17 14:47:02 2006//Trelease_0_8_1 +/translate-all.c/1.14/Thu May 25 18:22:29 2006//Trelease_0_8_1 +/translate-op.c/1.1/Sun Mar 13 16:53:06 2005//Trelease_0_8_1 +/usb-linux.c/1.4/Sat Mar 11 18:03:38 2006//Trelease_0_8_1 +/vgafont.h/1.1/Wed May 17 14:47:02 2006//Trelease_0_8_1 +/vl.c/1.184/Thu May 25 18:22:30 2006//Trelease_0_8_1 +/vl.h/1.116/Thu May 25 18:22:30 2006//Trelease_0_8_1 +/vnc.c/1.4/Mon May 1 21:44:22 2006//Trelease_0_8_1 +/vnc_keysym.h/1.1/Sun Apr 30 21:28:36 2006//Trelease_0_8_1 +/vnchextile.h/1.1/Sun Apr 30 21:28:36 2006//Trelease_0_8_1 +/x86_64.ld/1.1/Thu Jan 6 20:50:00 2005//Trelease_0_8_1 +D/target-sh4//// diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/CVS/Repository --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/CVS/Repository Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,1 @@ +qemu diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/CVS/Root --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/CVS/Root Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,1 @@ +:pserver:anonymous@xxxxxxxxxxxxxxxxxxxxxxx:/sources/qemu diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/CVS/Tag --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/CVS/Tag Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,1 @@ +Nrelease_0_8_1 diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/Changelog --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/Changelog Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,376 @@ +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) + - Virtual console support + - Better monitor line edition + - New block device layer + - New 'qcow' growable disk image support with AES encryption and + transparent decompression + - VMware 3 and 4 read-only disk image support (untested) + - Support for up to 4 serial ports + - TFTP server support (Magnus Damm) + - Port redirection support in user mode networking + - Support for not executable data sections + - Compressed loop disk image support (Johannes Schindelin) + - Level triggered IRQ fix (aka NE2000 PCI performance fix) (Steve + Wormley) + - Fixed Fedora Core 2 problems (now you can run qemu without any + LD_ASSUME_KERNEL tricks on FC2) + - DHCP fix for Windows (accept DHCPREQUEST alone) + - SPARC system emulation (Blue Swirl) + - Automatic Samba configuration for host file access from Windows. + - '-loadvm' and '-full-screen' options + - ne2000 savevm support (Johannes Schindelin) + - Ctrl-Alt is now the default grab key. Ctrl-Alt-[0-9] switches to + the virtual consoles. + - BIOS floppy fix for NT4 (Mike Nordell, Derek Fawcus, Volker Ruppert) + - Floppy fixes for NT4 and NT5 (Mike Nordell) + - NT4 IDE fixes (Ben Pfaf, Mike Nordell) + - SDL Audio support and SB16 fixes (malc) + - ENTER instruction bug fix (initial patch by Stefan Kisdaroczi) + - VGA font change fix + - VGA read-only CRTC register fix + +version 0.6.0: + + - minimalist FPU exception support (NetBSD FPU probe fix) + - cr0.ET fix (Win95 boot) + - *BSD port (Markus Niemisto) + - I/O access fix (signaled by Mark Jonckheere) + - IDE drives serial number fix (Mike Nordell) + - int13 CDROM BIOS fix (aka Solaris x86 install CD fix) + - int15, ah=86 BIOS fix (aka Solaris x86 hardware probe hang up fix) + - BSR/BSF "undefined behaviour" fix + - vmdk2raw: convert VMware disk images to raw images + - PCI support + - NE2K PCI support + - dummy VGA PCI support + - VGA font selection fix (Daniel Serpell) + - PIC reset fix (Hidemi KAWAI) + - PIC spurious irq support (aka Solaris install bug) + - added '-localtime' option + - Cirrus CL-GD54xx VGA support (initial patch by Makoto Suzuki (suzu)) + - APM and system shutdown support + - Fixed system reset + - Support for other PC BIOSes + - Initial PowerMac hardware emulation + - PowerMac/PREP OpenFirmware compatible BIOS (Jocelyn Mayer) + - initial IDE BMDMA support (needed for Darwin x86) + - Set the default memory size for PC emulation to 128 MB + +version 0.5.5: + + - SDL full screen support (initial patch by malc) + - VGA support on PowerPC PREP + - VBE fixes (Matthew Mastracci) + - PIT fixes (aka Win98 hardware probe and "VGA slowness" bug) + - IDE master only fixes (aka Win98 CD-ROM probe bug) + - ARM load/store half word fix (Ulrich Hecht) + - FDC fixes for Win98 + +version 0.5.4: + + - qemu-fast fixes + - BIOS area protection fix (aka EMM386.EXE fix) (Mike Nordell) + - keyboard/mouse fix (Mike Nordell) + - IDE fixes (Linux did not recognized slave drivers) + - VM86 EIP masking fix (aka NT5 install fix) (Mike Nordell) + - QEMU can now boot a PowerPC Linux kernel (Jocelyn Mayer) + - User mode network stack + - imul imm8 fix + 0x82 opcode support (Hidemi KAWAI) + - precise self modifying code (aka BeOS install bug) + +version 0.5.3: + + - added Bochs VESA VBE support + - VGA memory map mode 3 access fix (OS/2 install fix) + - IDE fixes (Jens Axboe) + - CPU interrupt fixes + - fixed various TLB invalidation cases (NT install) + - fixed cr0.WP semantics (XP install) + - direct chaining support for SPARC and PowerPC (faster) + - ARM NWFPE support (initial patch by Ulrich Hecht) + - added specific x86 to x86 translator (close to native performance + in qemu-i386 and qemu-fast) + - shm syscalls support (Paul McKerras) + - added accurate CR0.MP/ME/TS emulation + - fixed DMA memory write access (Win95 boot floppy fix) + - graphical x86 linux loader + - command line monitor + - generic removable device support + - support of CD-ROM change + - multiple network interface support + - initial x86-64 host support (Gwenole Beauchesne) + - lret to outer priviledge fix (OS/2 install fix) + - task switch fixes (SkyOS boot) + - VM save/restore commands + - new timer API + - more precise RTC emulation (periodic timers + time updates) + - Win32 port (initial patch by Kazu) + +version 0.5.2: + + - improved soft MMU speed (assembly functions and specializing) + - improved multitasking speed by avoiding flushing TBs when + switching tasks + - improved qemu-fast speed + - improved self modifying code handling (big performance gain in + softmmu mode). + - fixed IO checking + - fixed CD-ROM detection (win98 install CD) + - fixed addseg real mode bug (GRUB boot fix) + - added ROM memory support (win98 boot) + - fixed 'call Ev' in case of paging exception + - updated the script 'qemu-binfmt-conf.sh' to use QEMU automagically + when launching executables for the supported target CPUs. + - PowerPC system emulation update (Jocelyn Mayer) + - PC floppy emulation and DMA fixes (Jocelyn Mayer) + - polled mode for PIC (Jocelyn Mayer) + - fixed PTE dirty bit handling + - fixed xadd same reg bug + - fixed cmpxchg exception safeness + - access to virtual memory in gdb stub + - task gate and NT flag fixes + - eflags optimisation fix for string operations + +version 0.5.1: + + - float access fixes when using soft mmu + - PC emulation support on PowerPC + - A20 support + - IDE CD-ROM emulation + - ARM fixes (Ulrich Hecht) + - SB16 emulation (malc) + - IRET and INT fixes in VM86 mode with IOPL=3 + - Port I/Os use TSS io map + - Full task switching/task gate support + - added verr, verw, arpl, fcmovxx + - PowerPC target support (Jocelyn Mayer) + - Major SPARC target fixes (dynamically linked programs begin to work) + +version 0.5.0: + + - full hardware level VGA emulation + - graphical display with SDL + - added PS/2 mouse and keyboard emulation + - popw (%esp) fix + - mov to/from segment data width fix + - added real mode support + - added Bochs BIOS and LGPL'ed VGA BIOS loader in qemu + - m68k host port (Richard Zidlicky) + - partial soft MMU support for memory mapped I/Os + - multi-target build + - fixed: no error code in hardware interrupts + - fixed: pop ss, mov ss, x and sti disable hardware irqs for the next insn + - correct single stepping thru string operations + - preliminary SPARC target support (Thomas M. Ogrisegg) + - tun-fd option (Rusty Russell) + - automatic IDE geometry detection + - renamed 'vl' to qemu[-fast] and user qemu to qemu-{cpu}. + - added man page + - added full soft mmu mode to launch unpatched OSes. + +version 0.4.3: + + - x86 exception fix in case of nop instruction. + - gcc 3.2.2 bug workaround (RedHat 9 fix) + - sparc and Alpha host fixes + - many ARM target fixes: 'ls' and 'bash' can be launched. + +version 0.4.2: + + - many exception handling fixes (can compile a Linux kernel inside vl) + - IDE emulation support + - initial GDB stub support + - deferred update support for disk images (Rusty Russell) + - accept User Mode Linux Copy On Write disk images + - SMP kernels can at least be booted + +version 0.4.1: + + - more accurate timer support in vl. + - more reliable NE2000 probe in vl. + - added 2.5.66 kernel in vl-test. + - added VLTMPDIR environment variable in vl. + +version 0.4: + + - initial support for ring 0 x86 processor emulation + - fixed signal handling for correct dosemu DPMI emulation + - fast x86 MMU emulation with mmap() + - fixed popl (%esp) case + - Linux kernel can be executed by QEMU with the 'vl' command. + +version 0.3: + + - initial support for ARM emulation + - added fnsave, frstor, fnstenv, fldenv FPU instructions + - added FPU register save in signal emulation + - initial ARM port + - Sparc and Alpha ports work on the regression test + - generic ioctl number conversion + - fixed ioctl type conversion + +version 0.2: + + - PowerPC disassembly and ELF symbols output (Rusty Russell) + - flock support (Rusty Russell) + - ugetrlimit support (Rusty Russell) + - fstat64 fix (Rusty Russell) + - initial Alpha port (Falk Hueffner) + - initial IA64 port (Matt Wilson) + - initial Sparc and Sparc64 port (David S. Miller) + - added HLT instruction + - LRET instruction fix. + - added GPF generation for I/Os. + - added INT3 and TF flag support. + - SHL instruction C flag fix. + - mmap emulation for host page size > 4KB + - self-modifying code support + - better VM86 support (dosemu works on non trivial programs) + - precise exception support (EIP is computed correctly in most cases) + - more precise LDT/GDT/IDT emulation + - faster segment load in vm86 mode + - direct chaining of basic blocks (faster emulation) + +version 0.1.6: + + - automatic library search system. QEMU can now work with unpatched + ELF dynamic loader and libc (Rusty Russell). + - ISO C warning fixes (Alistair Strachan) + - first self-virtualizable version (works only as long as the + translation cache is not flushed) + - RH9 fixes + +version 0.1.5: + + - ppc64 support + personality() patch (Rusty Russell) + - first Alpha CPU patches (Falk Hueffner) + - removed bfd.h dependancy + - fixed shrd, shld, idivl and divl on PowerPC. + - fixed buggy glibc PowerPC rint() function (test-i386 passes now on PowerPC). + +version 0.1.4: + + - more accurate VM86 emulation (can launch small DOS 16 bit + executables in wine). + - fixed push/pop fs/gs + - added iret instruction. + - added times() syscall and SIOCATMARK ioctl. + +version 0.1.3: + + - S390 support (Ulrich Weigand) + - glibc 2.3.x compile fix (Ulrich Weigand) + - socketcall endian fix (Ulrich Weigand) + - struct sockaddr endian fix (Ulrich Weigand) + - sendmsg/recvmsg endian fix (Ulrich Weigand) + - execve endian fix (Ulrich Weigand) + - fdset endian fix (Ulrich Weigand) + - partial setsockopt syscall support (Ulrich Weigand) + - more accurate pushf/popf emulation + - first partial vm86() syscall support (can be used with runcom example). + - added bound, cmpxchg8b, cpuid instructions + - added 16 bit addressing support/override for string operations + - poll() fix + +version 0.1.2: + + - compile fixes + - xlat instruction + - xchg instruction memory lock + - added simple vm86 example (not working with QEMU yet). The 54 byte + DOS executable 'pi_10.com' program was released by Bertram + Felgenhauer (more information at http://www.boo.net/~jasonp/pipage.html). + +version 0.1.1: + + - glibc 2.2 compilation fixes + - added -s and -L options + - binary distribution of x86 glibc and wine + - big endian fixes in ELF loader and getdents. + +version 0.1: + + - initial public release. diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/LICENSE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/LICENSE Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,12 @@ +The following points clarify the QEMU licenses: + +1) The QEMU virtual CPU core library (libqemu.a) and the QEMU PC + system emulator are released under the GNU Lesser General Public + License. + +2) The Linux user mode QEMU emulator is released under the GNU General + Public License. + +3) QEMU is a trademark of Fabrice Bellard. + +Fabrice Bellard. \ No newline at end of file diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/Makefile Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,149 @@ +XEN_ROOT=../.. +include $(XEN_ROOT)/tools/Rules.mk + +include config-host.mak + +CFLAGS+=-Wall -O2 -g -fno-strict-aliasing -I. +ifdef CONFIG_DARWIN +CFLAGS+= -mdynamic-no-pic +endif +LDFLAGS=-g +LIBS= +DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE +TOOLS=qemu-img$(EXESUF) +ifdef CONFIG_STATIC +LDFLAGS+=-static +endif +ifdef BUILD_DOCS +DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 +else +DOCS= +endif + +all: $(DOCS) + for d in $(TARGET_DIRS); do \ + $(MAKE) -C $$d $@ || exit 1 ; \ + done + +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 $@ $^ + +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 *.pod *~ */*~ + $(MAKE) -C tests clean + for d in $(TARGET_DIRS); do \ + $(MAKE) -C $$d $@ || exit 1 ; \ + done + +distclean: clean + rm -f config-host.mak config-host.h $(DOCS) + for d in $(TARGET_DIRS); do \ + 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 + +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 +test speed test2: all + $(MAKE) -C tests $@ + +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 + 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) +tar: + rm -rf /tmp/$(FILE) + cp -r . /tmp/$(FILE) + ( cd /tmp ; tar zcvf ~/$(FILE).tar.gz $(FILE) --exclude CVS ) + rm -rf /tmp/$(FILE) + +# generate a binary distribution +tarbin: + ( 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 diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/Makefile.target --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/Makefile.target Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,531 @@ +include config.mak + +XEN_ROOT=../../.. +include $(XEN_ROOT)/tools/Rules.mk + +TARGET_BASE_ARCH:=$(TARGET_ARCH) +ifeq ($(TARGET_ARCH), x86_64) +TARGET_BASE_ARCH:=i386 +endif +ifeq ($(TARGET_ARCH), ppc64) +TARGET_BASE_ARCH:=ppc +endif +ifeq ($(TARGET_ARCH), sparc64) +TARGET_BASE_ARCH:=sparc +endif +TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)$(TARGET_SUB) +VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio +DEFINES=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH) +DEFINES+= -I$(XEN_ROOT)/tools/libxc +DEFINES+= -I$(XEN_ROOT)/tools/xenstore +ifdef CONFIG_USER_ONLY +VPATH+=:$(SRC_PATH)/linux-user +DEFINES+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH) +endif +CFLAGS+=-Wall -O2 -g -fno-strict-aliasing +SSE2 := $(call test-gcc-flag,$(CC),-msse2) +ifeq ($(SSE2),-msse2) +CFLAGS += -DUSE_SSE2=1 -msse2 +endif +CFLAGS+= $(LOCAL_CFLAGS) +#CFLAGS+=-Werror +LDFLAGS=-g +LIBS= +HELPER_CFLAGS=$(CFLAGS) +DYNGEN=../dyngen$(EXESUF) +# user emulator name +TARGET_ARCH2=$(TARGET_ARCH) +ifeq ($(TARGET_ARCH),arm) + ifeq ($(TARGET_WORDS_BIGENDIAN),yes) + TARGET_ARCH2=armeb + endif +endif +ifeq ($(TARGET_ARCH),mips) + ifneq ($(TARGET_WORDS_BIGENDIAN),yes) + TARGET_ARCH2=mipsel + endif +endif +QEMU_USER=qemu-$(TARGET_ARCH2) +# system emulator name +ifdef CONFIG_SOFTMMU +ifeq ($(TARGET_ARCH), i386) +QEMU_SYSTEM=qemu$(EXESUF) +else +QEMU_SYSTEM=qemu-system-$(TARGET_ARCH2)$(EXESUF) +endif +else +QEMU_SYSTEM=qemu-fast +endif + +QEMU_SYSTEM=qemu-dm + +ifdef CONFIG_USER_ONLY +PROGS=$(QEMU_USER) +else +PROGS+=$(QEMU_SYSTEM) +ifndef CONFIG_SOFTMMU +CONFIG_STATIC=y +endif +endif # !CONFIG_USER_ONLY + +ifdef CONFIG_STATIC +LDFLAGS+=-static +endif + +ifeq ($(ARCH),i386) +CFLAGS+=-fomit-frame-pointer +OP_CFLAGS=$(CFLAGS) -mpreferred-stack-boundary=2 +ifeq ($(HAVE_GCC3_OPTIONS),yes) +OP_CFLAGS+= -falign-functions=0 -fno-gcse +else +OP_CFLAGS+= -malign-functions=0 +endif + +ifdef TARGET_GPROF +USE_I386_LD=y +endif +ifdef CONFIG_STATIC +USE_I386_LD=y +endif +ifdef USE_I386_LD +LDFLAGS+=-Wl,-T,$(SRC_PATH)/i386.ld +else +# WARNING: this LDFLAGS is _very_ tricky : qemu is an ELF shared object +# that the kernel ELF loader considers as an executable. I think this +# is the simplest way to make it self virtualizable! +LDFLAGS+=-Wl,-shared +endif +endif + +ifeq ($(ARCH),x86_64) +OP_CFLAGS=$(CFLAGS) -falign-functions=0 +LDFLAGS+=-Wl,-T,$(SRC_PATH)/x86_64.ld +endif + +ifeq ($(ARCH),ppc) +CFLAGS+= -D__powerpc__ +OP_CFLAGS=$(CFLAGS) +LDFLAGS+=-Wl,-T,$(SRC_PATH)/ppc.ld +endif + +ifeq ($(ARCH),s390) +OP_CFLAGS=$(CFLAGS) +LDFLAGS+=-Wl,-T,$(SRC_PATH)/s390.ld +endif + +ifeq ($(ARCH),sparc) +CFLAGS+=-m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6 +LDFLAGS+=-m32 +OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0 +HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat +# -static is used to avoid g1/g3 usage by the dynamic linker +LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc.ld -static +endif + +ifeq ($(ARCH),sparc64) +CFLAGS+=-m64 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6 +LDFLAGS+=-m64 +OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0 +endif + +ifeq ($(ARCH),alpha) +# -msmall-data is not used because we want two-instruction relocations +# for the constant constructions +OP_CFLAGS=-Wall -O2 -g +# Ensure there's only a single GP +CFLAGS += -msmall-data +LDFLAGS+=-Wl,-T,$(SRC_PATH)/alpha.ld +endif + +ifeq ($(ARCH),ia64) +CFLAGS += -mno-sdata +OP_CFLAGS=$(CFLAGS) +LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld +endif + +ifeq ($(ARCH),arm) +OP_CFLAGS=$(CFLAGS) -mno-sched-prolog -fno-omit-frame-pointer +LDFLAGS+=-Wl,-T,$(SRC_PATH)/arm.ld +endif + +ifeq ($(ARCH),m68k) +OP_CFLAGS=$(CFLAGS) -fomit-frame-pointer +LDFLAGS+=-Wl,-T,m68k.ld +endif + +ifeq ($(HAVE_GCC3_OPTIONS),yes) +# very important to generate a return at the end of every operation +OP_CFLAGS+=-fno-reorder-blocks -fno-optimize-sibling-calls +endif + +ifeq ($(CONFIG_DARWIN),yes) +OP_CFLAGS+= -mdynamic-no-pic +LIBS+=-lmx +endif + +######################################################### + +DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE +LIBS+=-lm +LIBS+=-L../../libxc -lxenctrl -lxenguest +LIBS+=-L../../xenstore -lxenstore +LIBS+=-lpthread +ifndef CONFIG_USER_ONLY +LIBS+=-lz +endif +ifdef CONFIG_WIN32 +LIBS+=-lwinmm -lws2_32 -liphlpapi +endif +ifdef CONFIG_SOLARIS +LIBS+=-lsocket -lnsl -lresolv +endif + +# profiling code +ifdef TARGET_GPROF +LDFLAGS+=-p +main.o: CFLAGS+=-p +endif + +OBJS= elfload.o main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o +ifeq ($(TARGET_ARCH), i386) +OBJS+= vm86.o +endif +ifeq ($(TARGET_ARCH), arm) +OBJS+=nwfpe/fpa11.o nwfpe/fpa11_cpdo.o \ +nwfpe/fpa11_cpdt.o nwfpe/fpa11_cprt.o nwfpe/fpopcode.o nwfpe/single_cpdo.o \ + nwfpe/double_cpdo.o nwfpe/extended_cpdo.o arm-semi.o +endif +SRCS:= $(OBJS:.o=.c) +OBJS+= libqemu.a + +# cpu emulator library +LIBOBJS=exec.o kqemu.o translate-op.o translate-all.o cpu-exec.o\ + translate.o op.o +ifdef CONFIG_SOFTFLOAT +LIBOBJS+=fpu/softfloat.o +else +LIBOBJS+=fpu/softfloat-native.o +endif +DEFINES+=-I$(SRC_PATH)/fpu + +ifeq ($(TARGET_ARCH), i386) +LIBOBJS+=helper.o helper2.o +ifeq ($(ARCH), i386) +LIBOBJS+=translate-copy.o +endif +endif + +ifeq ($(TARGET_ARCH), x86_64) +LIBOBJS+=helper.o helper2.o +endif + +ifeq ($(TARGET_BASE_ARCH), ppc) +LIBOBJS+= op_helper.o helper.o +endif + +ifeq ($(TARGET_ARCH), mips) +LIBOBJS+= op_helper.o helper.o +endif + +ifeq ($(TARGET_BASE_ARCH), sparc) +LIBOBJS+= op_helper.o helper.o +endif + +ifeq ($(TARGET_BASE_ARCH), arm) +LIBOBJS+= op_helper.o helper.o +endif + +ifeq ($(TARGET_BASE_ARCH), sh4) +LIBOBJS+= op_helper.o helper.o +endif + +# NOTE: the disassembler code is only needed for debugging +LIBOBJS+=disas.o +ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386) +USE_I386_DIS=y +endif +ifeq ($(findstring x86_64, $(TARGET_ARCH) $(ARCH)),x86_64) +USE_I386_DIS=y +endif +ifdef USE_I386_DIS +LIBOBJS+=i386-dis.o +endif +ifeq ($(findstring alpha, $(TARGET_ARCH) $(ARCH)),alpha) +LIBOBJS+=alpha-dis.o +endif +ifeq ($(findstring ppc, $(TARGET_BASE_ARCH) $(ARCH)),ppc) +LIBOBJS+=ppc-dis.o +endif +ifeq ($(findstring mips, $(TARGET_ARCH) $(ARCH)),mips) +LIBOBJS+=mips-dis.o +endif +ifeq ($(findstring sparc, $(TARGET_BASE_ARCH) $(ARCH)),sparc) +LIBOBJS+=sparc-dis.o +endif +ifeq ($(findstring arm, $(TARGET_ARCH) $(ARCH)),arm) +LIBOBJS+=arm-dis.o +endif +ifeq ($(findstring m68k, $(TARGET_ARCH) $(ARCH)),m68k) +LIBOBJS+=m68k-dis.o +endif +ifeq ($(findstring sh4, $(TARGET_ARCH) $(ARCH)),sh4) +LIBOBJS+=sh4-dis.o +endif + +ifdef CONFIG_GDBSTUB +OBJS+=gdbstub.o +endif + +# qemu-dm objects +LIBOBJS=helper2.o exec-dm.o i8259-dm.o + +all: $(PROGS) + +$(QEMU_USER): $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) +ifeq ($(ARCH),alpha) +# Mark as 32 bit binary, i. e. it will be mapped into the low 31 bit of +# the address space (31 bit so sign extending doesn't matter) + echo -ne '\001\000\000\000' | dd of=qemu bs=1 seek=48 count=4 conv=notrunc +endif + +# must use static linking to avoid leaving stuff in virtual address space +VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o +VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o +ifdef CONFIG_WIN32 +VL_OBJS+=tap-win32.o +endif + +SOUND_HW = sb16.o es1370.o +AUDIODRV = audio.o noaudio.o wavaudio.o +ifdef CONFIG_SDL +AUDIODRV += sdlaudio.o +endif +ifdef CONFIG_OSS +AUDIODRV += ossaudio.o +endif +ifdef CONFIG_COREAUDIO +AUDIODRV += coreaudio.o +endif +ifdef CONFIG_ALSA +AUDIODRV += alsaaudio.o +LIBS += -lasound +endif +ifdef CONFIG_DSOUND +AUDIODRV += dsoundaudio.o +LIBS += -lole32 -ldxguid +endif +ifdef CONFIG_FMOD +AUDIODRV += fmodaudio.o +audio.o fmodaudio.o: DEFINES := -I$(CONFIG_FMOD_INC) $(DEFINES) +LIBS += $(CONFIG_FMOD_LIB) +endif +ifdef CONFIG_ADLIB +SOUND_HW += fmopl.o adlib.o +endif + +# USB layer +VL_OBJS+= usb.o usb-hub.o usb-uhci.o usb-linux.o usb-hid.o + +# PCI network cards +VL_OBJS+= ne2000.o rtl8139.o + +ifeq ($(TARGET_BASE_ARCH), i386) +# Hardware support +VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV) +VL_OBJS+= fdc.o mc146818rtc.o serial.o pc.o +VL_OBJS+= cirrus_vga.o mixeng.o parallel.o +VL_OBJS+= piix4acpi.o +DEFINES += -DHAS_AUDIO +endif +ifeq ($(TARGET_BASE_ARCH), ppc) +VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV) +VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o +VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o +DEFINES += -DHAS_AUDIO +endif +ifeq ($(TARGET_ARCH), mips) +VL_OBJS+= mips_r4k.o dma.o vga.o serial.o i8254.o i8259.o +#VL_OBJS+= #ide.o pckbd.o fdc.o m48t59.o +endif +ifeq ($(TARGET_BASE_ARCH), sparc) +ifeq ($(TARGET_ARCH), sparc64) +VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o +VL_OBJS+= fdc.o mc146818rtc.o serial.o m48t59.o +VL_OBJS+= cirrus_vga.o parallel.o +else +VL_OBJS+= sun4m.o tcx.o lance.o iommu.o m48t59.o slavio_intctl.o +VL_OBJS+= slavio_timer.o slavio_serial.o slavio_misc.o fdc.o esp.o +endif +endif +ifeq ($(TARGET_BASE_ARCH), arm) +VL_OBJS+= integratorcp.o versatilepb.o ps2.o smc91c111.o arm_pic.o arm_timer.o +VL_OBJS+= arm_boot.o pl011.o pl050.o pl080.o pl110.o pl190.o +endif +ifeq ($(TARGET_BASE_ARCH), sh4) +VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o +endif +ifdef CONFIG_GDBSTUB +VL_OBJS+=gdbstub.o +endif +ifdef CONFIG_SDL +VL_OBJS+=sdl.o +endif +VL_OBJS+=vnc.o +ifdef CONFIG_COCOA +VL_OBJS+=cocoa.o +COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework IOKit +ifdef CONFIG_COREAUDIO +COCOA_LIBS+=-framework CoreAudio +endif +endif +ifdef CONFIG_SLIRP +DEFINES+=-I$(SRC_PATH)/slirp +SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \ +slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o \ +tcp_subr.o tcp_timer.o udp.o bootp.o debug.o tftp.o +VL_OBJS+=$(addprefix slirp/, $(SLIRP_OBJS)) +endif + +VL_LDFLAGS= +# specific flags are needed for non soft mmu emulator +ifdef CONFIG_STATIC +VL_LDFLAGS+=-static +endif +ifndef CONFIG_SOFTMMU +VL_LDFLAGS+=-Wl,-T,$(SRC_PATH)/i386-vl.ld +endif +ifndef CONFIG_DARWIN +ifndef CONFIG_WIN32 +ifndef CONFIG_SOLARIS +VL_LIBS=-lutil +endif +endif +endif +ifdef TARGET_GPROF +vl.o: CFLAGS+=-p +VL_LDFLAGS+=-p +endif + +ifeq ($(ARCH),ia64) +VL_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld +endif + +ifdef CONFIG_WIN32 +SDL_LIBS := $(filter-out -mwindows, $(SDL_LIBS)) -mconsole +endif + +$(QEMU_SYSTEM): $(VL_OBJS) libqemu.a + $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS) + +cocoa.o: cocoa.m + $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $< + +sdl.o: sdl.c keymaps.c sdl_keysym.h + $(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $< + +vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h + $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $< + +sdlaudio.o: sdlaudio.c + $(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $< + +depend: $(SRCS) + $(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend + +vldepend: $(VL_OBJS:.o=.c) + $(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend + +# libqemu + +libqemu.a: $(LIBOBJS) + rm -f $@ + $(AR) rcs $@ $(LIBOBJS) + +translate.o: translate.c gen-op.h opc.h cpu.h + +translate-all.o: translate-all.c opc.h cpu.h + +translate-op.o: translate-all.c op.h opc.h cpu.h + +op.h: op.o $(DYNGEN) + $(DYNGEN) -o $@ $< + +opc.h: op.o $(DYNGEN) + $(DYNGEN) -c -o $@ $< + +gen-op.h: op.o $(DYNGEN) + $(DYNGEN) -g -o $@ $< + +op.o: op.c + $(CC) $(OP_CFLAGS) $(DEFINES) -c -o $@ $< + +helper.o: helper.c + $(CC) $(HELPER_CFLAGS) $(DEFINES) -c -o $@ $< + +ifeq ($(TARGET_BASE_ARCH), i386) +op.o: op.c opreg_template.h ops_template.h ops_template_mem.h ops_mem.h ops_sse.h +endif + +ifeq ($(TARGET_ARCH), arm) +op.o: op.c op_template.h +pl110.o: pl110_template.h +endif + +ifeq ($(TARGET_BASE_ARCH), sparc) +op.o: op.c op_template.h op_mem.h fop_template.h fbranch_template.h +magic_load.o: elf_op.h +endif + +ifeq ($(TARGET_BASE_ARCH), ppc) +op.o: op.c op_template.h op_mem.h +op_helper.o: op_helper_mem.h +translate.o: translate.c translate_init.c +endif + +ifeq ($(TARGET_ARCH), mips) +op.o: op.c op_template.c op_mem.c +op_helper.o: op_helper_mem.c +endif + +loader.o: loader.c elf_ops.h + +ifeq ($(TARGET_ARCH), sh4) +op.o: op.c op_mem.c cpu.h +op_helper.o: op_helper.c exec.h cpu.h +helper.o: helper.c exec.h cpu.h +sh7750.o: sh7750.c sh7750_regs.h sh7750_regnames.h cpu.h +shix.o: shix.c sh7750_regs.h sh7750_regnames.h +sh7750_regnames.o: sh7750_regnames.c sh7750_regnames.h sh7750_regs.h +tc58128.o: tc58128.c +endif + +%.o: %.c + $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $< + +%.o: %.S + $(CC) $(DEFINES) -c -o $@ $< + +clean: + rm -f *.o *.a *~ $(PROGS) gen-op.h opc.h op.h nwfpe/*.o slirp/*.o fpu/*.o + +distclean: clean + rm -rf config.mak config.h + +install: all + mkdir -p "$(DESTDIR)$(bindir)" "$(DESTDIR)$(configdir)" +ifneq ($(PROGS),) + $(INSTALL) -m 755 -s $(PROGS) "$(DESTDIR)$(bindir)" +endif + install -m 755 $(TARGET_PATH)/qemu-dm.debug "$(DESTDIR)$(bindir)" + install -m 755 $(TARGET_PATH)/qemu-ifup "$(DESTDIR)$(configdir)" + +ifneq ($(wildcard .depend),) +include .depend +endif + +ifeq (1, 0) +audio.o sdlaudio.o dsoundaudio.o ossaudio.o wavaudio.o noaudio.o \ +fmodaudio.o alsaaudio.o mixeng.o sb16.o es1370.o gus.o adlib.o: \ +CFLAGS := $(CFLAGS) -Wall -Werror -W -Wsign-compare +endif diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/README Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,3 @@ +Read the documentation in qemu-doc.html. + +Fabrice Bellard. \ No newline at end of file diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/README.distrib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/README.distrib Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,16 @@ +Information about the various packages used to build the current qemu +x86 binary distribution: + +* gcc 2.95.2 was used for the build. A glibc 2.1.3 Debian distribution + was used to get most of the binary packages. + +* wine-20020411 tarball + + ./configure --prefix=/usr/local/wine-i386 + + All exe and libs were stripped. Some compile time tools and the + includes were deleted. + +* ldconfig was launched to build the library links: + + qemu-i386 /usr/gnemul/qemu-i386/bin/ldconfig-i386 -C /usr/gnemul/qemu-i386/etc/ld.so.cache diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/TODO --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/TODO Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,61 @@ +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 +- Precise VGA timings for old games/demos (malc patch) +- merge PIC spurious interrupt patch +- merge Solaris patch +- 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 +- 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. +- avoid looping if only exceptions +- cycle counter for all archs +- TLB code protection support for PPC +- see openMosix Doc +- disable SMC handling for ARM/SPARC/PPC (not finished) +- see undefined flags for BTx insn +- user/kernel PUSHL/POPL in helper.c +- keyboard output buffer filling timing emulation +- return UD exception if LOCK prefix incorrectly used +- test ldt limit < 7 ? +- tests for each target CPU +- fix CCOP optimisation +- 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) + +ppc specific: +------------ +- TLB invalidate not needed if msr_pr changes +- SPR_ENCODE() not useful +- enable shift optimizations ? + +linux-user specific: +------------------- +- add IPC syscalls +- handle rare page fault cases (in particular if page fault in helpers or + in syscall emulation code). +- 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. +- 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 bd68ce5a3f0c -r b450f21472a0 tools/ioemu/VERSION --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/VERSION Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,1 @@ +0.8.1 \ No newline at end of file diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/a.out.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/a.out.h Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,431 @@ +/* a.out.h + + Copyright 1997, 1998, 1999, 2001 Red Hat, Inc. + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#ifndef _A_OUT_H_ +#define _A_OUT_H_ + +#ifdef __cplusplus +extern "C" { +#endif +#define COFF_IMAGE_WITH_PE +#define COFF_LONG_SECTION_NAMES + +/*** coff information for Intel 386/486. */ + + +/********************** FILE HEADER **********************/ + +struct external_filehdr { + short f_magic; /* magic number */ + short f_nscns; /* number of sections */ + unsigned long f_timdat; /* time & date stamp */ + unsigned long f_symptr; /* file pointer to symtab */ + unsigned long f_nsyms; /* number of symtab entries */ + short f_opthdr; /* sizeof(optional hdr) */ + short f_flags; /* flags */ +}; + +/* Bits for f_flags: + * F_RELFLG relocation info stripped from file + * F_EXEC file is executable (no unresolved external references) + * F_LNNO line numbers stripped from file + * F_LSYMS local symbols stripped from file + * F_AR32WR file has byte ordering of an AR32WR machine (e.g. vax) + */ + +#define F_RELFLG (0x0001) +#define F_EXEC (0x0002) +#define F_LNNO (0x0004) +#define F_LSYMS (0x0008) + + + +#define I386MAGIC 0x14c +#define I386PTXMAGIC 0x154 +#define I386AIXMAGIC 0x175 + +/* This is Lynx's all-platform magic number for executables. */ + +#define LYNXCOFFMAGIC 0415 + +#define I386BADMAG(x) (((x).f_magic != I386MAGIC) \ + && (x).f_magic != I386AIXMAGIC \ + && (x).f_magic != I386PTXMAGIC \ + && (x).f_magic != LYNXCOFFMAGIC) + +#define FILHDR struct external_filehdr +#define FILHSZ 20 + + +/********************** AOUT "OPTIONAL HEADER"= + **********************/ + + +typedef struct +{ + unsigned short magic; /* type of file */ + unsigned short vstamp; /* version stamp */ + unsigned long tsize; /* text size in bytes, padded to FW bdry*/ + unsigned long dsize; /* initialized data " " */ + unsigned long bsize; /* uninitialized data " " */ + unsigned long entry; /* entry pt. */ + unsigned long text_start; /* base of text used for this file */ + unsigned long data_start; /* base of data used for this file= + */ +} +AOUTHDR; + +#define AOUTSZ 28 +#define AOUTHDRSZ 28 + +#define OMAGIC 0404 /* object files, eg as output */ +#define ZMAGIC 0413 /* demand load format, eg normal ld output */ +#define STMAGIC 0401 /* target shlib */ +#define SHMAGIC 0443 /* host shlib */ + + +/* define some NT default values */ +/* #define NT_IMAGE_BASE 0x400000 moved to internal.h */ +#define NT_SECTION_ALIGNMENT 0x1000 +#define NT_FILE_ALIGNMENT 0x200 +#define NT_DEF_RESERVE 0x100000 +#define NT_DEF_COMMIT 0x1000 + +/********************** SECTION HEADER **********************/ + + +struct external_scnhdr { + char s_name[8]; /* section name */ + unsigned long s_paddr; /* physical address, offset + of last addr in scn */ + unsigned long s_vaddr; /* virtual address */ + unsigned long s_size; /* section size */ + unsigned long s_scnptr; /* file ptr to raw data for section */ + unsigned long s_relptr; /* file ptr to relocation */ + unsigned long s_lnnoptr; /* file ptr to line numbers */ + unsigned short s_nreloc; /* number of relocation entries */ + unsigned short s_nlnno; /* number of line number entries*/ + unsigned long s_flags; /* flags */ +}; + +#define SCNHDR struct external_scnhdr +#define SCNHSZ 40 + +/* + * names of "special" sections + */ +#define _TEXT ".text" +#define _DATA ".data" +#define _BSS ".bss" +#define _COMMENT ".comment" +#define _LIB ".lib" + +/********************** LINE NUMBERS **********************/ + +/* 1 line number entry for every "breakpointable" source line in a section. + * Line numbers are grouped on a per function basis; first entry in a function + * grouping will have l_lnno = 0 and in place of physical address will be the + * symbol table index of the function name. + */ +struct external_lineno { + union { + unsigned long l_symndx; /* function name symbol index, iff l_lnno 0 */ + unsigned long l_paddr; /* (physical) address of line number */ + } l_addr; + unsigned short l_lnno; /* line number */ +}; + +#define LINENO struct external_lineno +#define LINESZ 6 + +/********************** SYMBOLS **********************/ + +#define E_SYMNMLEN 8 /* # characters in a symbol name */ +#define E_FILNMLEN 14 /* # characters in a file name */ +#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */ + +struct __attribute__((packed)) external_syment +{ + union { + char e_name[E_SYMNMLEN]; + struct { + unsigned long e_zeroes; + unsigned long e_offset; + } e; + } e; + unsigned long e_value; + unsigned short e_scnum; + unsigned short e_type; + char e_sclass[1]; + char e_numaux[1]; +}; + +#define N_BTMASK (0xf) +#define N_TMASK (0x30) +#define N_BTSHFT (4) +#define N_TSHIFT (2) + +union external_auxent { + struct { + unsigned long x_tagndx; /* str, un, or enum tag indx */ + union { + struct { + unsigned short x_lnno; /* declaration line number */ + unsigned short x_size; /* str/union/array size */ + } x_lnsz; + unsigned long x_fsize; /* size of function */ + } x_misc; + union { + struct { /* if ISFCN, tag, or .bb */ + unsigned long x_lnnoptr;/* ptr to fcn line # */ + unsigned long x_endndx; /* entry ndx past block end */ + } x_fcn; + struct { /* if ISARY, up to 4 dimen. */ + char x_dimen[E_DIMNUM][2]; + } x_ary; + } x_fcnary; + unsigned short x_tvndx; /* tv index */ + } x_sym; + + union { + char x_fname[E_FILNMLEN]; + struct { + unsigned long x_zeroes; + unsigned long x_offset; + } x_n; + } x_file; + + struct { + unsigned long x_scnlen; /* section length */ + unsigned short x_nreloc; /* # relocation entries */ + unsigned short x_nlinno; /* # line numbers */ + unsigned long x_checksum; /* section COMDAT checksum */ + unsigned short x_associated;/* COMDAT associated section index */ + char x_comdat[1]; /* COMDAT selection number */ + } x_scn; + + struct { + unsigned long x_tvfill; /* tv fill value */ + unsigned short x_tvlen; /* length of .tv */ + char x_tvran[2][2]; /* tv range */ + } x_tv; /* info about .tv section (in auxent of symbol .tv)) */ + +}; + +#define SYMENT struct external_syment +#define SYMESZ 18 +#define AUXENT union external_auxent +#define AUXESZ 18 + +#define _ETEXT "etext" + +/********************** RELOCATION DIRECTIVES **********************/ + +struct external_reloc { + char r_vaddr[4]; + char r_symndx[4]; + char r_type[2]; +}; + +#define RELOC struct external_reloc +#define RELSZ 10 + +/* end of coff/i386.h */ + +/* PE COFF header information */ + +#ifndef _PE_H +#define _PE_H + +/* NT specific file attributes */ +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 +#define IMAGE_FILE_32BIT_MACHINE 0x0100 +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 +#define IMAGE_FILE_SYSTEM 0x1000 +#define IMAGE_FILE_DLL 0x2000 +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 + +/* additional flags to be set for section headers to allow the NT loader to + read and write to the section data (to replace the addresses of data in + dlls for one thing); also to execute the section in .text's case= + */ +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define IMAGE_SCN_MEM_READ 0x40000000 +#define IMAGE_SCN_MEM_WRITE 0x80000000 + +/* + * Section characteristics added for ppc-nt + */ + +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* Reserved. */ + +#define IMAGE_SCN_CNT_CODE 0x00000020 /* Section contains code. */ +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* Section contains initialized data. */ +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* Section contains uninitialized data. */ + +#define IMAGE_SCN_LNK_OTHER 0x00000100 /* Reserved. */ +#define IMAGE_SCN_LNK_INFO 0x00000200 /* Section contains comments or some other type of information. */ +#define IMAGE_SCN_LNK_REMOVE 0x00000800 /* Section contents will not become part of image. */ +#define IMAGE_SCN_LNK_COMDAT 0x00001000 /* Section contents comdat. */ + +#define IMAGE_SCN_MEM_FARDATA 0x00008000 + +#define IMAGE_SCN_MEM_PURGEABLE 0x00020000 +#define IMAGE_SCN_MEM_16BIT 0x00020000 +#define IMAGE_SCN_MEM_LOCKED 0x00040000 +#define IMAGE_SCN_MEM_PRELOAD 0x00080000 + +#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 +#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 +#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 +#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 +#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 /* Default alignment if no others are specified. */ +#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 +#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 + + +#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 /* Section contains extended relocations. */ +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 /* Section is not cachable. */ +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 /* Section is not pageable. */ +#define IMAGE_SCN_MEM_SHARED 0x10000000 /* Section is shareable. */ + +/* COMDAT selection codes. */ + +#define IMAGE_COMDAT_SELECT_NODUPLICATES (1) /* Warn if duplicates. */ +#define IMAGE_COMDAT_SELECT_ANY (2) /* No warning. */ +#define IMAGE_COMDAT_SELECT_SAME_SIZE (3) /* Warn if different size. */ +#define IMAGE_COMDAT_SELECT_EXACT_MATCH (4) /* Warn if different. */ +#define IMAGE_COMDAT_SELECT_ASSOCIATIVE (5) /* Base on other section. */ + +/* Magic values that are true for all dos/nt implementations */ +#define DOSMAGIC 0x5a4d +#define NT_SIGNATURE 0x00004550 + +/* NT allows long filenames, we want to accommodate this. This may break + some of the bfd functions */ +#undef FILNMLEN +#define FILNMLEN 18 /* # characters in a file name */ + + +#ifdef COFF_IMAGE_WITH_PE +/* The filehdr is only weired in images */ + +#undef FILHDR +struct external_PE_filehdr +{ + /* DOS header fields */ + unsigned short e_magic; /* Magic number, 0x5a4d */ + unsigned short e_cblp; /* Bytes on last page of file, 0x90 */ + unsigned short e_cp; /* Pages in file, 0x3 */ + unsigned short e_crlc; /* Relocations, 0x0 */ + unsigned short e_cparhdr; /* Size of header in paragraphs, 0x4 */ + unsigned short e_minalloc; /* Minimum extra paragraphs needed, 0x0 */ + unsigned short e_maxalloc; /* Maximum extra paragraphs needed, 0xFFFF */ + unsigned short e_ss; /* Initial (relative) SS value, 0x0 */ + unsigned short e_sp; /* Initial SP value, 0xb8 */ + unsigned short e_csum; /* Checksum, 0x0 */ + unsigned short e_ip; /* Initial IP value, 0x0 */ + unsigned short e_cs; /* Initial (relative) CS value, 0x0 */ + unsigned short e_lfarlc; /* File address of relocation table, 0x40 */ + unsigned short e_ovno; /* Overlay number, 0x0 */ + char e_res[4][2]; /* Reserved words, all 0x0 */ + unsigned short e_oemid; /* OEM identifier (for e_oeminfo), 0x0 */ + unsigned short e_oeminfo; /* OEM information; e_oemid specific, 0x0 */ + char e_res2[10][2]; /* Reserved words, all 0x0 */ + unsigned long e_lfanew; /* File address of new exe header, 0x80 */ + char dos_message[16][4]; /* other stuff, always follow DOS header */ + unsigned int nt_signature; /* required NT signature, 0x4550 */ + + /* From standard header */ + + unsigned short f_magic; /* magic number */ + unsigned short f_nscns; /* number of sections */ + unsigned long f_timdat; /* time & date stamp */ + unsigned long f_symptr; /* file pointer to symtab */ + unsigned long f_nsyms; /* number of symtab entries */ + unsigned short f_opthdr; /* sizeof(optional hdr) */ + unsigned short f_flags; /* flags */ +}; + + +#define FILHDR struct external_PE_filehdr +#undef FILHSZ +#define FILHSZ 152 + +#endif + +typedef struct +{ + unsigned short magic; /* type of file */ + unsigned short vstamp; /* version stamp */ + unsigned long tsize; /* text size in bytes, padded to FW bdry*/ + unsigned long dsize; /* initialized data " " */ + unsigned long bsize; /* uninitialized data " " */ + unsigned long entry; /* entry pt. */ + unsigned long text_start; /* base of text used for this file */ + unsigned long data_start; /* base of all data used for this file */ + + /* NT extra fields; see internal.h for descriptions */ + unsigned long ImageBase; + unsigned long SectionAlignment; + unsigned long FileAlignment; + unsigned short MajorOperatingSystemVersion; + unsigned short MinorOperatingSystemVersion; + unsigned short MajorImageVersion; + unsigned short MinorImageVersion; + unsigned short MajorSubsystemVersion; + unsigned short MinorSubsystemVersion; + char Reserved1[4]; + unsigned long SizeOfImage; + unsigned long SizeOfHeaders; + unsigned long CheckSum; + unsigned short Subsystem; + unsigned short DllCharacteristics; + unsigned long SizeOfStackReserve; + unsigned long SizeOfStackCommit; + unsigned long SizeOfHeapReserve; + unsigned long SizeOfHeapCommit; + unsigned long LoaderFlags; + unsigned long NumberOfRvaAndSizes; + /* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; */ + char DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars */ + +} PEAOUTHDR; + + +#undef AOUTSZ +#define AOUTSZ (AOUTHDRSZ + 196) + +#undef E_FILNMLEN +#define E_FILNMLEN 18 /* # characters in a file name */ +#endif + +/* end of coff/pe.h */ + +#define DT_NON (0) /* no derived type */ +#define DT_PTR (1) /* pointer */ +#define DT_FCN (2) /* function */ +#define DT_ARY (3) /* array */ + +#define ISPTR(x) (((x) & N_TMASK) == (DT_PTR << N_BTSHFT)) +#define ISFCN(x) (((x) & N_TMASK) == (DT_FCN << N_BTSHFT)) +#define ISARY(x) (((x) & N_TMASK) == (DT_ARY << N_BTSHFT)) + +#ifdef __cplusplus +} +#endif + +#endif /* _A_OUT_H_ */ + diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/aes.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/aes.c Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,1317 @@ +/** + * + * aes.c - integrated in QEMU by Fabrice Bellard from the OpenSSL project. + */ +/* + * rijndael-alg-fst.c + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen <vincent.rijmen@xxxxxxxxxxxxxxxxxxx> + * @author Antoon Bosselaers <antoon.bosselaers@xxxxxxxxxxxxxxxxxxx> + * @author Paulo Barreto <paulo.barreto@xxxxxxxxxxxx> + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "vl.h" +#include "aes.h" + +#define NDEBUG +#include <assert.h> + +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; + +#define MAXKC (256/32) +#define MAXKB (256/8) +#define MAXNR 14 + +/* This controls loop-unrolling in aes_core.c */ +#undef FULL_UNROLL +# define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) +# define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } + +/* +Te0[x] = S [x].[02, 01, 01, 03]; +Te1[x] = S [x].[03, 02, 01, 01]; +Te2[x] = S [x].[01, 03, 02, 01]; +Te3[x] = S [x].[01, 01, 03, 02]; +Te4[x] = S [x].[01, 01, 01, 01]; + +Td0[x] = Si[x].[0e, 09, 0d, 0b]; +Td1[x] = Si[x].[0b, 0e, 09, 0d]; +Td2[x] = Si[x].[0d, 0b, 0e, 09]; +Td3[x] = Si[x].[09, 0d, 0b, 0e]; +Td4[x] = Si[x].[01, 01, 01, 01]; +*/ + +static const u32 Te0[256] = { + 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, + 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, + 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, + 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, + 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, + 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, + 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, + 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, + 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, + 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, + 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, + 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, + 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, + 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, + 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, + 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, + 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, + 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, + 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, + 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, + 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, + 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, + 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, + 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, + 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, + 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, + 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, + 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, + 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, + 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, + 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, + 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, + 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, + 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, + 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, + 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, + 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, + 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, + 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, + 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, + 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, + 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, + 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, + 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, + 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, + 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, + 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, + 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, + 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, + 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, + 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, + 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, + 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, + 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, + 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, + 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, + 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, + 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, + 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, + 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, + 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, + 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, + 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, + 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, +}; +static const u32 Te1[256] = { + 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, + 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, + 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, + 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, + 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, + 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, + 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, + 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, + 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, + 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, + 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, + 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, + 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, + 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, + 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, + 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, + 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, + 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, + 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, + 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, + 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, + 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, + 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, + 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, + 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, + 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, + 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, + 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, + 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, + 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, + 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, + 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, + 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, + 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, + 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, + 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, + 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, + 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, + 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, + 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, + 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, + 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, + 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, + 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, + 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, + 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, + 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, + 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, + 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, + 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, + 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, + 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, + 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, + 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, + 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, + 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, + 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, + 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, + 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, + 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, + 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, + 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, + 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, + 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, +}; +static const u32 Te2[256] = { + 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, + 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, + 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, + 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, + 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, + 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, + 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, + 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, + 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, + 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, + 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, + 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, + 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, + 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, + 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, + 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, + 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, + 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, + 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, + 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, + 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, + 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, + 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, + 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, + 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, + 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, + 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, + 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, + 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, + 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, + 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, + 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, + 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, + 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, + 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, + 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, + 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, + 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, + 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, + 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, + 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, + 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, + 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, + 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, + 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, + 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, + 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, + 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, + 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, + 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, + 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, + 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, + 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, + 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, + 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, + 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, + 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, + 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, + 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, + 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, + 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, + 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, + 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, + 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, +}; +static const u32 Te3[256] = { + + 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, + 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, + 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, + 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, + 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, + 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, + 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, + 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, + 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, + 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, + 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, + 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, + 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, + 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, + 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, + 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, + 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, + 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, + 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, + 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, + 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, + 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, + 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, + 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, + 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, + 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, + 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, + 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, + 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, + 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, + 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, + 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, + 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, + 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, + 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, + 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, + 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, + 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, + 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, + 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, + 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, + 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, + 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, + 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, + 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, + 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, + 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, + 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, + 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, + 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, + 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, + 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, + 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, + 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, + 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, + 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, + 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, + 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, + 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, + 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, + 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, + 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, + 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, + 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, +}; +static const u32 Te4[256] = { + 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, + 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, + 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, + 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, + 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, + 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, + 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, + 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, + 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, + 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, + 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, + 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, + 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, + 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, + 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, + 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, + 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, + 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, + 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, + 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, + 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, + 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, + 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, + 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, + 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, + 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, + 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, + 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, + 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, + 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, + 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, + 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, + 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, + 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, + 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, + 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, + 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, + 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, + 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, + 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, + 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, + 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, + 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, + 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, + 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, + 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, + 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, + 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, + 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, + 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, + 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, + 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, + 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, + 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, + 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, + 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, + 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, + 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, + 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, + 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, + 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, + 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, + 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, + 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, +}; +static const u32 Td0[256] = { + 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, + 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, + 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, + 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, + 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, + 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, + 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, + 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, + 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, + 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, + 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, + 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, + 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, + 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, + 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, + 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, + 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, + 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, + 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, + 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, + 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, + 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, + 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, + 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, + 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, + 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, + 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, + 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, + 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, + 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, + 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, + 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, + 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, + 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, + 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, + 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, + 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, + 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, + 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, + 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, + 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, + 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, + 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, + 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, + 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, + 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, + 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, + 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, + 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, + 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, + 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, + 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, + 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, + 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, + 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, + 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, + 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, + 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, + 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, + 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, + 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, + 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, + 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, + 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, +}; +static const u32 Td1[256] = { + 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, + 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, + 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, + 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, + 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, + 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, + 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, + 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, + 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, + 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, + 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, + 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, + 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, + 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, + 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, + 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, + 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, + 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, + 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, + 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, + 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, + 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, + 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, + 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, + 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, + 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, + 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, + 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, + 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, + 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, + 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, + 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, + 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, + 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, + 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, + 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, + 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, + 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, + 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, + 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, + 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, + 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, + 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, + 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, + 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, + 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, + 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, + 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, + 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, + 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, + 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, + 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, + 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, + 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, + 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, + 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, + 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, + 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, + 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, + 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, + 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, + 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, + 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, + 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, +}; +static const u32 Td2[256] = { + 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, + 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, + 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, + 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, + 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, + 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, + 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, + 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, + 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, + 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, + 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, + 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, + 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, + 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, + 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, + 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, + 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, + 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, + 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, + 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, + + 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, + 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, + 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, + 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, + 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, + 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, + 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, + 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, + 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, + 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, + 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, + 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, + 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, + 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, + 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, + 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, + 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, + 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, + 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, + 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, + 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, + 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, + 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, + 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, + 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, + 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, + 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, + 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, + 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, + 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, + 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, + 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, + 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, + 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, + 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, + 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, + 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, + 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, + 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, + 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, + 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, + 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, + 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, + 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, +}; +static const u32 Td3[256] = { + 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, + 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, + 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, + 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, + 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, + 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, + 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, + 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, + 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, + 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, + 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, + 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, + 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, + 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, + 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, + 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, + 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, + 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, + 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, + 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, + 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, + 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, + 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, + 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, + 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, + 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, + 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, + 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, + 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, + 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, + 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, + 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, + 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, + 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, + 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, + 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, + 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, + 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, + 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, + 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, + 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, + 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, + 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, + 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, + 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, + 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, + 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, + 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, + 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, + 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, + 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, + 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, + 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, + 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, + 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, + 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, + 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, + 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, + 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, + 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, + 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, + 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, + 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, + 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, +}; +static const u32 Td4[256] = { + 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, + 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, + 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, + 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, + 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, + 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, + 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, + 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, + 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, + 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, + 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, + 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, + 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, + 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, + 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, + 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, + 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, + 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, + 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, + 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, + 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, + 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, + 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, + 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, + 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, + 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, + 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, + 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, + 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, + 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, + 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, + 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, + 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, + 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, + 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, + 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, + 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, + 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, + 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, + 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, + 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, + 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, + 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, + 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, + 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, + 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, + 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, + 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, + 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, + 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, + 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, + 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, + 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, + 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, + 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, + 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, + 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, + 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, + 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, + 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, + 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, + 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, + 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, + 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, +}; +static const u32 rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +/** + * Expand the cipher key into the encryption key schedule. + */ +int AES_set_encrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key) { + + u32 *rk; + int i = 0; + u32 temp; + + if (!userKey || !key) + return -1; + if (bits != 128 && bits != 192 && bits != 256) + return -2; + + rk = key->rd_key; + + if (bits==128) + key->rounds = 10; + else if (bits==192) + key->rounds = 12; + else + key->rounds = 14; + + rk[0] = GETU32(userKey ); + rk[1] = GETU32(userKey + 4); + rk[2] = GETU32(userKey + 8); + rk[3] = GETU32(userKey + 12); + if (bits == 128) { + while (1) { + temp = rk[3]; + rk[4] = rk[0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + return 0; + } + rk += 4; + } + } + rk[4] = GETU32(userKey + 16); + rk[5] = GETU32(userKey + 20); + if (bits == 192) { + while (1) { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) { + return 0; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + } + rk[6] = GETU32(userKey + 24); + rk[7] = GETU32(userKey + 28); + if (bits == 256) { + while (1) { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) { + return 0; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ + (Te4[(temp >> 24) ] & 0xff000000) ^ + (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(temp ) & 0xff] & 0x000000ff); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + + rk += 8; + } + } + return 0; +} + +/** + * Expand the cipher key into the decryption key schedule. + */ +int AES_set_decrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key) { + + u32 *rk; + int i, j, status; + u32 temp; + + /* first, start with an encryption schedule */ + status = AES_set_encrypt_key(userKey, bits, key); + if (status < 0) + return status; + + rk = key->rd_key; + + /* invert the order of the round keys: */ + for (i = 0, j = 4*(key->rounds); i < j; i += 4, j -= 4) { + temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; + temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; + temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; + temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; + } + /* apply the inverse MixColumn transform to all round keys but the first and the last: */ + for (i = 1; i < (key->rounds); i++) { + rk += 4; + rk[0] = + Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[0] ) & 0xff] & 0xff]; + rk[1] = + Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[1] ) & 0xff] & 0xff]; + rk[2] = + Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[2] ) & 0xff] & 0xff]; + rk[3] = + Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[3] ) & 0xff] & 0xff]; + } + return 0; +} + +#ifndef AES_ASM +/* + * Encrypt a single block + * in and out can overlap + */ +void AES_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key) { + + const u32 *rk; + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + assert(in && out && key); + rk = key->rd_key; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(in ) ^ rk[0]; + s1 = GETU32(in + 4) ^ rk[1]; + s2 = GETU32(in + 8) ^ rk[2]; + s3 = GETU32(in + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; + if (key->rounds > 10) { + /* round 10: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; + if (key->rounds > 12) { + /* round 12: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; + } + } + rk += key->rounds << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = key->rounds >> 1; + for (;;) { + t0 = + Te0[(s0 >> 24) ] ^ + Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ + Te3[(s3 ) & 0xff] ^ + rk[4]; + t1 = + Te0[(s1 >> 24) ] ^ + Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ + Te3[(s0 ) & 0xff] ^ + rk[5]; + t2 = + Te0[(s2 >> 24) ] ^ + Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ + Te3[(s1 ) & 0xff] ^ + rk[6]; + t3 = + Te0[(s3 >> 24) ] ^ + Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ + Te3[(s2 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Te0[(t0 >> 24) ] ^ + Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ + Te3[(t3 ) & 0xff] ^ + rk[0]; + s1 = + Te0[(t1 >> 24) ] ^ + Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ + Te3[(t0 ) & 0xff] ^ + rk[1]; + s2 = + Te0[(t2 >> 24) ] ^ + Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ + Te3[(t1 ) & 0xff] ^ + rk[2]; + s3 = + Te0[(t3 >> 24) ] ^ + Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ + Te3[(t2 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Te4[(t0 >> 24) ] & 0xff000000) ^ + (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(out , s0); + s1 = + (Te4[(t1 >> 24) ] & 0xff000000) ^ + (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(out + 4, s1); + s2 = + (Te4[(t2 >> 24) ] & 0xff000000) ^ + (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(out + 8, s2); + s3 = + (Te4[(t3 >> 24) ] & 0xff000000) ^ + (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(out + 12, s3); +} + +/* + * Decrypt a single block + * in and out can overlap + */ +void AES_decrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key) { + + const u32 *rk; + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + assert(in && out && key); + rk = key->rd_key; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(in ) ^ rk[0]; + s1 = GETU32(in + 4) ^ rk[1]; + s2 = GETU32(in + 8) ^ rk[2]; + s3 = GETU32(in + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39]; + if (key->rounds > 10) { + /* round 10: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47]; + if (key->rounds > 12) { + /* round 12: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55]; + } + } + rk += key->rounds << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = key->rounds >> 1; + for (;;) { + t0 = + Td0[(s0 >> 24) ] ^ + Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ + Td3[(s1 ) & 0xff] ^ + rk[4]; + t1 = + Td0[(s1 >> 24) ] ^ + Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ + Td3[(s2 ) & 0xff] ^ + rk[5]; + t2 = + Td0[(s2 >> 24) ] ^ + Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ + Td3[(s3 ) & 0xff] ^ + rk[6]; + t3 = + Td0[(s3 >> 24) ] ^ + Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ + Td3[(s0 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Td0[(t0 >> 24) ] ^ + Td1[(t3 >> 16) & 0xff] ^ + Td2[(t2 >> 8) & 0xff] ^ + Td3[(t1 ) & 0xff] ^ + rk[0]; + s1 = + Td0[(t1 >> 24) ] ^ + Td1[(t0 >> 16) & 0xff] ^ + Td2[(t3 >> 8) & 0xff] ^ + Td3[(t2 ) & 0xff] ^ + rk[1]; + s2 = + Td0[(t2 >> 24) ] ^ + Td1[(t1 >> 16) & 0xff] ^ + Td2[(t0 >> 8) & 0xff] ^ + Td3[(t3 ) & 0xff] ^ + rk[2]; + s3 = + Td0[(t3 >> 24) ] ^ + Td1[(t2 >> 16) & 0xff] ^ + Td2[(t1 >> 8) & 0xff] ^ + Td3[(t0 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Td4[(t0 >> 24) ] & 0xff000000) ^ + (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(out , s0); + s1 = + (Td4[(t1 >> 24) ] & 0xff000000) ^ + (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(out + 4, s1); + s2 = + (Td4[(t2 >> 24) ] & 0xff000000) ^ + (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(out + 8, s2); + s3 = + (Td4[(t3 >> 24) ] & 0xff000000) ^ + (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(out + 12, s3); +} + +#endif /* AES_ASM */ + +void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, + const unsigned long length, const AES_KEY *key, + unsigned char *ivec, const int enc) +{ + + unsigned long n; + unsigned long len = length; + unsigned char tmp[AES_BLOCK_SIZE]; + + assert(in && out && key && ivec); + + if (enc) { + while (len >= AES_BLOCK_SIZE) { + for(n=0; n < AES_BLOCK_SIZE; ++n) + tmp[n] = in[n] ^ ivec[n]; + AES_encrypt(tmp, out, key); + memcpy(ivec, out, AES_BLOCK_SIZE); + len -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + if (len) { + for(n=0; n < len; ++n) + tmp[n] = in[n] ^ ivec[n]; + for(n=len; n < AES_BLOCK_SIZE; ++n) + tmp[n] = ivec[n]; + AES_encrypt(tmp, tmp, key); + memcpy(out, tmp, AES_BLOCK_SIZE); + memcpy(ivec, tmp, AES_BLOCK_SIZE); + } + } else { + while (len >= AES_BLOCK_SIZE) { + memcpy(tmp, in, AES_BLOCK_SIZE); + AES_decrypt(in, out, key); + for(n=0; n < AES_BLOCK_SIZE; ++n) + out[n] ^= ivec[n]; + memcpy(ivec, tmp, AES_BLOCK_SIZE); + len -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + if (len) { + memcpy(tmp, in, AES_BLOCK_SIZE); + AES_decrypt(tmp, tmp, key); + for(n=0; n < len; ++n) + out[n] = tmp[n] ^ ivec[n]; + memcpy(ivec, tmp, AES_BLOCK_SIZE); + } + } +} diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/aes.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/aes.h Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,26 @@ +#ifndef QEMU_AES_H +#define QEMU_AES_H + +#define AES_MAXNR 14 +#define AES_BLOCK_SIZE 16 + +struct aes_key_st { + uint32_t rd_key[4 *(AES_MAXNR + 1)]; + int rounds; +}; +typedef struct aes_key_st AES_KEY; + +int AES_set_encrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); +int AES_set_decrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); + +void AES_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); +void AES_decrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); +void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, + const unsigned long length, const AES_KEY *key, + unsigned char *ivec, const int enc); + +#endif diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/audio/CVS/Entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/audio/CVS/Entries Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,19 @@ +/alsaaudio.c/1.5/Sun Nov 20 18:53:05 2005//Trelease_0_8_1 +/audio.c/1.9/Thu May 25 18:22:31 2006//Trelease_0_8_1 +/audio.h/1.5/Thu May 25 18:22:31 2006//Trelease_0_8_1 +/audio_int.h/1.7/Thu May 25 18:22:31 2006//Trelease_0_8_1 +/audio_template.h/1.4/Sun Nov 20 16:24:34 2005//Trelease_0_8_1 +/coreaudio.c/1.5/Sun Nov 20 18:53:42 2005//Trelease_0_8_1 +/dsound_template.h/1.2/Sat Nov 5 18:55:27 2005//Trelease_0_8_1 +/dsoundaudio.c/1.2/Sat Nov 5 18:55:27 2005//Trelease_0_8_1 +/fmodaudio.c/1.5/Thu May 25 18:22:32 2006//Trelease_0_8_1 +/mixeng.c/1.4/Thu May 25 18:22:32 2006//Trelease_0_8_1 +/mixeng.h/1.2/Thu May 25 18:22:32 2006//Trelease_0_8_1 +/mixeng_template.h/1.2/Thu May 25 18:22:32 2006//Trelease_0_8_1 +/noaudio.c/1.4/Thu May 25 18:22:32 2006//Trelease_0_8_1 +/ossaudio.c/1.9/Thu May 25 18:22:32 2006//Trelease_0_8_1 +/rate_template.h/1.2/Sat Nov 5 18:55:27 2005//Trelease_0_8_1 +/sdlaudio.c/1.6/Thu May 25 18:22:32 2006//Trelease_0_8_1 +/sys-queue.h/1.1/Sun Oct 30 18:58:22 2005//Trelease_0_8_1 +/wavaudio.c/1.6/Thu May 25 18:22:32 2006//Trelease_0_8_1 +D diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/audio/CVS/Repository --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/audio/CVS/Repository Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,1 @@ +qemu/audio diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/audio/CVS/Root --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/audio/CVS/Root Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,1 @@ +:pserver:anonymous@xxxxxxxxxxxxxxxxxxxxxxx:/sources/qemu diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/audio/CVS/Tag --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/audio/CVS/Tag Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,1 @@ +Nrelease_0_8_1 diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/audio/alsaaudio.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/audio/alsaaudio.c Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,981 @@ +/* + * QEMU ALSA audio driver + * + * Copyright (c) 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 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include <alsa/asoundlib.h> +#include "vl.h" + +#define AUDIO_CAP "alsa" +#include "audio_int.h" + +typedef struct ALSAVoiceOut { + HWVoiceOut hw; + void *pcm_buf; + snd_pcm_t *handle; +} ALSAVoiceOut; + +typedef struct ALSAVoiceIn { + HWVoiceIn hw; + snd_pcm_t *handle; + void *pcm_buf; +} ALSAVoiceIn; + +static struct { + int size_in_usec_in; + int size_in_usec_out; + const char *pcm_name_in; + const char *pcm_name_out; + unsigned int buffer_size_in; + unsigned int period_size_in; + unsigned int buffer_size_out; + unsigned int period_size_out; + unsigned int threshold; + + int buffer_size_in_overriden; + int period_size_in_overriden; + + int buffer_size_out_overriden; + int period_size_out_overriden; + int verbose; +} conf = { +#ifdef HIGH_LATENCY + .size_in_usec_in = 1, + .size_in_usec_out = 1, +#endif + .pcm_name_out = "hw:0,0", + .pcm_name_in = "hw:0,0", +#ifdef HIGH_LATENCY + .buffer_size_in = 400000, + .period_size_in = 400000 / 4, + .buffer_size_out = 400000, + .period_size_out = 400000 / 4, +#else +#define DEFAULT_BUFFER_SIZE 1024 +#define DEFAULT_PERIOD_SIZE 256 + .buffer_size_in = DEFAULT_BUFFER_SIZE * 4, + .period_size_in = DEFAULT_PERIOD_SIZE * 4, + .buffer_size_out = DEFAULT_BUFFER_SIZE, + .period_size_out = DEFAULT_PERIOD_SIZE, + .buffer_size_in_overriden = 0, + .buffer_size_out_overriden = 0, + .period_size_in_overriden = 0, + .period_size_out_overriden = 0, +#endif + .threshold = 0, + .verbose = 0 +}; + +struct alsa_params_req { + int freq; + audfmt_e fmt; + int nchannels; + unsigned int buffer_size; + unsigned int period_size; +}; + +struct alsa_params_obt { + int freq; + audfmt_e fmt; + int nchannels; + snd_pcm_uframes_t samples; +}; + +static void GCC_FMT_ATTR (2, 3) alsa_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", snd_strerror (err)); +} + +static void GCC_FMT_ATTR (3, 4) alsa_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", snd_strerror (err)); +} + +static void alsa_anal_close (snd_pcm_t **handlep) +{ + int err = snd_pcm_close (*handlep); + if (err) { + alsa_logerr (err, "Failed to close PCM handle %p\n", *handlep); + } + *handlep = NULL; +} + +static int alsa_write (SWVoiceOut *sw, void *buf, int len) +{ + return audio_pcm_sw_write (sw, buf, len); +} + +static int aud_to_alsafmt (audfmt_e fmt) +{ + switch (fmt) { + case AUD_FMT_S8: + return SND_PCM_FORMAT_S8; + + case AUD_FMT_U8: + return SND_PCM_FORMAT_U8; + + case AUD_FMT_S16: + return SND_PCM_FORMAT_S16_LE; + + case AUD_FMT_U16: + return SND_PCM_FORMAT_U16_LE; + + default: + dolog ("Internal logic error: Bad audio format %d\n", fmt); +#ifdef DEBUG_AUDIO + abort (); +#endif + return SND_PCM_FORMAT_U8; + } +} + +static int alsa_to_audfmt (int alsafmt, audfmt_e *fmt, int *endianness) +{ + switch (alsafmt) { + case SND_PCM_FORMAT_S8: + *endianness = 0; + *fmt = AUD_FMT_S8; + break; + + case SND_PCM_FORMAT_U8: + *endianness = 0; + *fmt = AUD_FMT_U8; + break; + + case SND_PCM_FORMAT_S16_LE: + *endianness = 0; + *fmt = AUD_FMT_S16; + break; + + case SND_PCM_FORMAT_U16_LE: + *endianness = 0; + *fmt = AUD_FMT_U16; + break; + + case SND_PCM_FORMAT_S16_BE: + *endianness = 1; + *fmt = AUD_FMT_S16; + break; + + case SND_PCM_FORMAT_U16_BE: + *endianness = 1; + *fmt = AUD_FMT_U16; + break; + + default: + dolog ("Unrecognized audio format %d\n", alsafmt); + return -1; + } + + return 0; +} + +#if defined DEBUG_MISMATCHES || defined DEBUG +static void alsa_dump_info (struct alsa_params_req *req, + struct alsa_params_obt *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 ("frequency | %10d | %10d\n", req->freq, obt->freq); + dolog ("============================================\n"); + dolog ("requested: buffer size %d period size %d\n", + req->buffer_size, req->period_size); + dolog ("obtained: samples %ld\n", obt->samples); +} +#endif + +static void alsa_set_threshold (snd_pcm_t *handle, snd_pcm_uframes_t threshold) +{ + int err; + snd_pcm_sw_params_t *sw_params; + + snd_pcm_sw_params_alloca (&sw_params); + + err = snd_pcm_sw_params_current (handle, sw_params); + if (err < 0) { + dolog ("Could not fully initialize DAC\n"); + alsa_logerr (err, "Failed to get current software parameters\n"); + return; + } + + err = snd_pcm_sw_params_set_start_threshold (handle, sw_params, threshold); + if (err < 0) { + dolog ("Could not fully initialize DAC\n"); + alsa_logerr (err, "Failed to set software threshold to %ld\n", + threshold); + return; + } + + err = snd_pcm_sw_params (handle, sw_params); + if (err < 0) { + dolog ("Could not fully initialize DAC\n"); + alsa_logerr (err, "Failed to set software parameters\n"); + return; + } +} + +static int alsa_open (int in, struct alsa_params_req *req, + struct alsa_params_obt *obt, snd_pcm_t **handlep) +{ + snd_pcm_t *handle; + snd_pcm_hw_params_t *hw_params; + int err, freq, nchannels; + const char *pcm_name = in ? conf.pcm_name_in : conf.pcm_name_out; + unsigned int period_size, buffer_size; + snd_pcm_uframes_t obt_buffer_size; + const char *typ = in ? "ADC" : "DAC"; + + freq = req->freq; + period_size = req->period_size; + buffer_size = req->buffer_size; + nchannels = req->nchannels; + + snd_pcm_hw_params_alloca (&hw_params); + + err = snd_pcm_open ( + &handle, + pcm_name, + in ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, + SND_PCM_NONBLOCK + ); + if (err < 0) { + alsa_logerr2 (err, typ, "Failed to open `%s':\n", pcm_name); + return -1; + } + + err = snd_pcm_hw_params_any (handle, hw_params); + if (err < 0) { + alsa_logerr2 (err, typ, "Failed to initialize hardware parameters\n"); + goto err; + } + + err = snd_pcm_hw_params_set_access ( + handle, + hw_params, + SND_PCM_ACCESS_RW_INTERLEAVED + ); + if (err < 0) { + alsa_logerr2 (err, typ, "Failed to set access type\n"); + goto err; + } + + err = snd_pcm_hw_params_set_format (handle, hw_params, req->fmt); + if (err < 0) { + alsa_logerr2 (err, typ, "Failed to set format %d\n", req->fmt); + goto err; + } + + err = snd_pcm_hw_params_set_rate_near (handle, hw_params, &freq, 0); + if (err < 0) { + alsa_logerr2 (err, typ, "Failed to set frequency %d\n", req->freq); + goto err; + } + + err = snd_pcm_hw_params_set_channels_near ( + handle, + hw_params, + &nchannels + ); + if (err < 0) { + alsa_logerr2 (err, typ, "Failed to set number of channels %d\n", + req->nchannels); + goto err; + } + + if (nchannels != 1 && nchannels != 2) { + alsa_logerr2 (err, typ, + "Can not handle obtained number of channels %d\n", + nchannels); + goto err; + } + + if (!((in && conf.size_in_usec_in) || (!in && conf.size_in_usec_out))) { + if (!buffer_size) { + buffer_size = DEFAULT_BUFFER_SIZE; + period_size= DEFAULT_PERIOD_SIZE; + } + } + + if (buffer_size) { + if ((in && conf.size_in_usec_in) || (!in && conf.size_in_usec_out)) { + if (period_size) { + err = snd_pcm_hw_params_set_period_time_near ( + handle, + hw_params, + &period_size, + 0 + ); + if (err < 0) { + alsa_logerr2 (err, typ, + "Failed to set period time %d\n", + req->period_size); + goto err; + } + } + + err = snd_pcm_hw_params_set_buffer_time_near ( + handle, + hw_params, + &buffer_size, + 0 + ); + + if (err < 0) { + alsa_logerr2 (err, typ, + "Failed to set buffer time %d\n", + req->buffer_size); + goto err; + } + } + else { + int dir; + snd_pcm_uframes_t minval; + + if (period_size) { + minval = period_size; + dir = 0; + + err = snd_pcm_hw_params_get_period_size_min ( + hw_params, + &minval, + &dir + ); + if (err < 0) { + alsa_logerr ( + err, + "Could not get minmal period size for %s\n", + typ + ); + } + else { + if (period_size < minval) { + if ((in && conf.period_size_in_overriden) + || (!in && conf.period_size_out_overriden)) { + dolog ("%s period size(%d) is less " + "than minmal period size(%ld)\n", + typ, + period_size, + minval); + } + period_size = minval; + } + } + + err = snd_pcm_hw_params_set_period_size ( + handle, + hw_params, + period_size, + 0 + ); + if (err < 0) { + alsa_logerr2 (err, typ, "Failed to set period size %d\n", + req->period_size); + goto err; + } + } + + minval = buffer_size; + err = snd_pcm_hw_params_get_buffer_size_min ( + hw_params, + &minval + ); + if (err < 0) { + alsa_logerr (err, "Could not get minmal buffer size for %s\n", + typ); + } + else { + if (buffer_size < minval) { + if ((in && conf.buffer_size_in_overriden) + || (!in && conf.buffer_size_out_overriden)) { + dolog ( + "%s buffer size(%d) is less " + "than minimal buffer size(%ld)\n", + typ, + buffer_size, + minval + ); + } + buffer_size = minval; + } + } + + err = snd_pcm_hw_params_set_buffer_size ( + handle, + hw_params, + buffer_size + ); + if (err < 0) { + alsa_logerr2 (err, typ, "Failed to set buffer size %d\n", + req->buffer_size); + goto err; + } + } + } + else { + dolog ("warning: Buffer size is not set\n"); + } + + err = snd_pcm_hw_params (handle, hw_params); + if (err < 0) { + alsa_logerr2 (err, typ, "Failed to apply audio parameters\n"); + goto err; + } + + err = snd_pcm_hw_params_get_buffer_size (hw_params, &obt_buffer_size); + if (err < 0) { + alsa_logerr2 (err, typ, "Failed to get buffer size\n"); + goto err; + } + + err = snd_pcm_prepare (handle); + if (err < 0) { + alsa_logerr2 (err, typ, "Could not prepare handle %p\n", handle); + goto err; + } + + if (!in && conf.threshold) { + snd_pcm_uframes_t threshold; + int bytes_per_sec; + + bytes_per_sec = freq + << (nchannels == 2) + << (req->fmt == AUD_FMT_S16 || req->fmt == AUD_FMT_U16); + + threshold = (conf.threshold * bytes_per_sec) / 1000; + alsa_set_threshold (handle, threshold); + } + + obt->fmt = req->fmt; + obt->nchannels = nchannels; + obt->freq = freq; + obt->samples = obt_buffer_size; + *handlep = handle; + +#if defined DEBUG_MISMATCHES || defined DEBUG + if (obt->fmt != req->fmt || + obt->nchannels != req->nchannels || + obt->freq != req->freq) { + dolog ("Audio paramters mismatch for %s\n", typ); + alsa_dump_info (req, obt); + } +#endif + +#ifdef DEBUG + alsa_dump_info (req, obt); +#endif + return 0; + + err: + alsa_anal_close (&handle); + return -1; +} + +static int alsa_recover (snd_pcm_t *handle) +{ + int err = snd_pcm_prepare (handle); + if (err < 0) { + alsa_logerr (err, "Failed to prepare handle %p\n", handle); + return -1; + } + return 0; +} + +static snd_pcm_sframes_t alsa_get_avail (snd_pcm_t *handle) +{ + snd_pcm_sframes_t avail; + + avail = snd_pcm_avail_update (handle); + if (avail < 0) { + if (avail == -EPIPE) { + if (!alsa_recover (handle)) { + avail = snd_pcm_avail_update (handle); + } + } + + if (avail < 0) { + alsa_logerr (avail, + "Could not obtain number of available frames\n"); + return -1; + } + } + + return avail; +} + +static int alsa_run_out (HWVoiceOut *hw) +{ + ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; + int rpos, live, decr; + int samples; + uint8_t *dst; + st_sample_t *src; + snd_pcm_sframes_t avail; + + live = audio_pcm_hw_get_live_out (hw); + if (!live) { + return 0; + } + + avail = alsa_get_avail (alsa->handle); + if (avail < 0) { + dolog ("Could not get number of available playback frames\n"); + return 0; + } + + decr = audio_MIN (live, avail); + samples = decr; + rpos = hw->rpos; + while (samples) { + int left_till_end_samples = hw->samples - rpos; + int len = audio_MIN (samples, left_till_end_samples); + snd_pcm_sframes_t written; + + src = hw->mix_buf + rpos; + dst = advance (alsa->pcm_buf, rpos << hw->info.shift); + + hw->clip (dst, src, len); + + while (len) { + written = snd_pcm_writei (alsa->handle, dst, len); + + if (written <= 0) { + switch (written) { + case 0: + if (conf.verbose) { + dolog ("Failed to write %d frames (wrote zero)\n", len); + } + goto exit; + + case -EPIPE: + if (alsa_recover (alsa->handle)) { + alsa_logerr (written, "Failed to write %d frames\n", + len); + goto exit; + } + if (conf.verbose) { + dolog ("Recovering from playback xrun\n"); + } + continue; + + case -EAGAIN: + goto exit; + + default: + alsa_logerr (written, "Failed to write %d frames to %p\n", + len, dst); + goto exit; + } + } + + mixeng_clear (src, written); + rpos = (rpos + written) % hw->samples; + samples -= written; + len -= written; + dst = advance (dst, written << hw->info.shift); + src += written; + } + } + + exit: + hw->rpos = rpos; + return decr; +} + +static void alsa_fini_out (HWVoiceOut *hw) +{ + ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; + + ldebug ("alsa_fini\n"); + alsa_anal_close (&alsa->handle); + + if (alsa->pcm_buf) { + qemu_free (alsa->pcm_buf); + alsa->pcm_buf = NULL; + } +} + +static int alsa_init_out (HWVoiceOut *hw, audsettings_t *as) +{ + ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; + struct alsa_params_req req; + struct alsa_params_obt obt; + audfmt_e effective_fmt; + int endianness; + int err; + snd_pcm_t *handle; + audsettings_t obt_as; + + req.fmt = aud_to_alsafmt (as->fmt); + req.freq = as->freq; + req.nchannels = as->nchannels; + req.period_size = conf.period_size_out; + req.buffer_size = conf.buffer_size_out; + + if (alsa_open (0, &req, &obt, &handle)) { + return -1; + } + + err = alsa_to_audfmt (obt.fmt, &effective_fmt, &endianness); + if (err) { + alsa_anal_close (&handle); + 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) + ); + hw->samples = obt.samples; + + alsa->pcm_buf = audio_calloc (AUDIO_FUNC, obt.samples, 1 << hw->info.shift); + if (!alsa->pcm_buf) { + dolog ("Could not allocate DAC buffer (%d samples, each %d bytes)\n", + hw->samples, 1 << hw->info.shift); + alsa_anal_close (&handle); + return -1; + } + + alsa->handle = handle; + return 0; +} + +static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int pause) +{ + int err; + + if (pause) { + err = snd_pcm_drop (handle); + if (err < 0) { + alsa_logerr (err, "Could not stop %s\n", typ); + return -1; + } + } + else { + err = snd_pcm_prepare (handle); + if (err < 0) { + alsa_logerr (err, "Could not prepare handle for %s\n", typ); + return -1; + } + } + + return 0; +} + +static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...) +{ + ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; + + switch (cmd) { + case VOICE_ENABLE: + ldebug ("enabling voice\n"); + return alsa_voice_ctl (alsa->handle, "playback", 0); + + case VOICE_DISABLE: + ldebug ("disabling voice\n"); + return alsa_voice_ctl (alsa->handle, "playback", 1); + } + + return -1; +} + +static int alsa_init_in (HWVoiceIn *hw, audsettings_t *as) +{ + ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; + struct alsa_params_req req; + struct alsa_params_obt obt; + int endianness; + int err; + audfmt_e effective_fmt; + snd_pcm_t *handle; + audsettings_t obt_as; + + req.fmt = aud_to_alsafmt (as->fmt); + req.freq = as->freq; + req.nchannels = as->nchannels; + req.period_size = conf.period_size_in; + req.buffer_size = conf.buffer_size_in; + + if (alsa_open (1, &req, &obt, &handle)) { + return -1; + } + + err = alsa_to_audfmt (obt.fmt, &effective_fmt, &endianness); + if (err) { + alsa_anal_close (&handle); + 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) + ); + hw->samples = obt.samples; + + alsa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift); + if (!alsa->pcm_buf) { + dolog ("Could not allocate ADC buffer (%d samples, each %d bytes)\n", + hw->samples, 1 << hw->info.shift); + alsa_anal_close (&handle); + return -1; + } + + alsa->handle = handle; + return 0; +} + +static void alsa_fini_in (HWVoiceIn *hw) +{ + ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; + + alsa_anal_close (&alsa->handle); + + if (alsa->pcm_buf) { + qemu_free (alsa->pcm_buf); + alsa->pcm_buf = NULL; + } +} + +static int alsa_run_in (HWVoiceIn *hw) +{ + ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; + int hwshift = hw->info.shift; + int i; + int live = audio_pcm_hw_get_live_in (hw); + int dead = hw->samples - live; + int decr; + struct { + int add; + int len; + } bufs[2] = { + { hw->wpos, 0 }, + { 0, 0 } + }; + snd_pcm_sframes_t avail; + snd_pcm_uframes_t read_samples = 0; + + if (!dead) { + return 0; + } + + avail = alsa_get_avail (alsa->handle); + if (avail < 0) { + dolog ("Could not get number of captured frames\n"); + return 0; + } + + if (!avail && (snd_pcm_state (alsa->handle) == SND_PCM_STATE_PREPARED)) { + avail = hw->samples; + } + + decr = audio_MIN (dead, avail); + if (!decr) { + return 0; + } + + if (hw->wpos + decr > hw->samples) { + bufs[0].len = (hw->samples - hw->wpos); + bufs[1].len = (decr - (hw->samples - hw->wpos)); + } + else { + bufs[0].len = decr; + } + + for (i = 0; i < 2; ++i) { + void *src; + st_sample_t *dst; + snd_pcm_sframes_t nread; + snd_pcm_uframes_t len; + + len = bufs[i].len; + + src = advance (alsa->pcm_buf, bufs[i].add << hwshift); + dst = hw->conv_buf + bufs[i].add; + + while (len) { + nread = snd_pcm_readi (alsa->handle, src, len); + + if (nread <= 0) { + switch (nread) { + case 0: + if (conf.verbose) { + dolog ("Failed to read %ld frames (read zero)\n", len); + } + goto exit; + + case -EPIPE: + if (alsa_recover (alsa->handle)) { + alsa_logerr (nread, "Failed to read %ld frames\n", len); + goto exit; + } + if (conf.verbose) { + dolog ("Recovering from capture xrun\n"); + } + continue; + + case -EAGAIN: + goto exit; + + default: + alsa_logerr ( + nread, + "Failed to read %ld frames from %p\n", + len, + src + ); + goto exit; + } + } + + hw->conv (dst, src, nread, &nominal_volume); + + src = advance (src, nread << hwshift); + dst += nread; + + read_samples += nread; + len -= nread; + } + } + + exit: + hw->wpos = (hw->wpos + read_samples) % hw->samples; + return read_samples; +} + +static int alsa_read (SWVoiceIn *sw, void *buf, int size) +{ + return audio_pcm_sw_read (sw, buf, size); +} + +static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...) +{ + ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; + + switch (cmd) { + case VOICE_ENABLE: + ldebug ("enabling voice\n"); + return alsa_voice_ctl (alsa->handle, "capture", 0); + + case VOICE_DISABLE: + ldebug ("disabling voice\n"); + return alsa_voice_ctl (alsa->handle, "capture", 1); + } + + return -1; +} + +static void *alsa_audio_init (void) +{ + return &conf; +} + +static void alsa_audio_fini (void *opaque) +{ + (void) opaque; +} + +static struct audio_option alsa_options[] = { + {"DAC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_out, + "DAC period/buffer size in microseconds (otherwise in frames)", NULL, 0}, + {"DAC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_out, + "DAC period size", &conf.period_size_out_overriden, 0}, + {"DAC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_out, + "DAC buffer size", &conf.buffer_size_out_overriden, 0}, + + {"ADC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_in, + "ADC period/buffer size in microseconds (otherwise in frames)", NULL, 0}, + {"ADC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_in, + "ADC period size", &conf.period_size_in_overriden, 0}, + {"ADC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_in, + "ADC buffer size", &conf.buffer_size_in_overriden, 0}, + + {"THRESHOLD", AUD_OPT_INT, &conf.threshold, + "(undocumented)", NULL, 0}, + + {"DAC_DEV", AUD_OPT_STR, &conf.pcm_name_out, + "DAC device name (for instance dmix)", NULL, 0}, + + {"ADC_DEV", AUD_OPT_STR, &conf.pcm_name_in, + "ADC device name", NULL, 0}, + + {"VERBOSE", AUD_OPT_BOOL, &conf.verbose, + "Behave in a more verbose way", NULL, 0}, + + {NULL, 0, NULL, NULL, NULL, 0} +}; + +static struct audio_pcm_ops alsa_pcm_ops = { + alsa_init_out, + alsa_fini_out, + alsa_run_out, + alsa_write, + alsa_ctl_out, + + alsa_init_in, + alsa_fini_in, + alsa_run_in, + alsa_read, + alsa_ctl_in +}; + +struct audio_driver alsa_audio_driver = { + INIT_FIELD (name = ) "alsa", + INIT_FIELD (descr = ) "ALSA http://www.alsa-project.org", + INIT_FIELD (options = ) alsa_options, + INIT_FIELD (init = ) alsa_audio_init, + INIT_FIELD (fini = ) alsa_audio_fini, + INIT_FIELD (pcm_ops = ) &alsa_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 (ALSAVoiceOut), + INIT_FIELD (voice_size_in = ) sizeof (ALSAVoiceIn) +}; diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/audio/audio.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/audio/audio.c Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,1481 @@ +/* + * QEMU Audio subsystem + * + * 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 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +#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 + UINT_MAX, + UINT_MAX +#endif +}; + +/* http://www.df.lth.se/~john_e/gems/gem002d.html */ +/* http://www.multi-platforms.com/Tips/PopCount.htm */ +uint32_t popcount (uint32_t u) +{ + u = ((u&0x55555555) + ((u>>1)&0x55555555)); + u = ((u&0x33333333) + ((u>>2)&0x33333333)); + u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f)); + u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff)); + u = ( u&0x0000ffff) + (u>>16); + return u; +} + +inline uint32_t lsbindex (uint32_t u) +{ + return popcount ((u&-u)-1); +} + +#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; + } + 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) { + *defaultp = 1; + return defval; + } + 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; + + va_start (ap, fmt); + AUD_vlog (cap, fmt, ap); + va_end (ap); +} + +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; + } + return 0; +} + +static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as) +{ + 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; + } + 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; + } + + 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; + } +} + +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, total = 0; + + if (!sw) { + return size; + } + + hwsamples = sw->hw->samples; + + 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 = ((int64_t) dead << 32) / sw->ratio; + swlim = audio_MIN (swlim, samples); + 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) { + break; + } + isamp = swlim; + osamp = blck; + 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; + 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) { + /* 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; +} + +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; + } + + hw = sw->hw; + if (sw->active != on) { + SWVoiceOut *temp_sw; + + if (on) { + int total; + + hw->pending_disable = 0; + if (!hw->enabled) { + hw->enabled = 1; + 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->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) { + 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; + } + + if (nb_active == 1) { + hw->enabled = 0; + hw->pcm_ops->ctl_in (hw, VOICE_DISABLE); + } + } + } + sw->active = on; + } +} + +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 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 { + 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 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) +{ + 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) +{ + (void) f; + (void) opaque; + + if (version_id != 1) { + return -EINVAL; + } + + return 0; +} + +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; + 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 = !audio_driver_init (s, drvtab[i]); + found = 1; + break; + } + } + + if (!found) { + dolog ("Unknown audio driver `%s'\n", drvname); + 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 = !audio_driver_init (s, drvtab[i]); + } + } + } + + if (!done) { + 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 bd68ce5a3f0c -r b450f21472a0 tools/ioemu/audio/audio.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/audio/audio.h Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,133 @@ +/* + * QEMU Audio subsystem header + * + * 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 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef QEMU_AUDIO_H +#define QEMU_AUDIO_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 +} audfmt_e; + +typedef struct { + int freq; + int nchannels; + audfmt_e fmt; +} audsettings_t; + +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) +{ + uint8_t *d = p; + return (d + incr); +} + +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 bd68ce5a3f0c -r b450f21472a0 tools/ioemu/audio/audio_int.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/audio/audio_int.h Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,268 @@ +/* + * QEMU Audio subsystem header + * + * 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 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef QEMU_AUDIO_INT_H +#define QEMU_AUDIO_INT_H + +#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; + struct audio_pcm_info info; + + f_sample *clip; + + int rpos; + uint64_t ts_helper; + + st_sample_t *mix_buf; + + int samples; + 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 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 total_hw_samples_mixed; + int active; + int empty; + HWVoiceOut *hw; + char *name; + 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 bd68ce5a3f0c -r b450f21472a0 tools/ioemu/audio/audio_template.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/audio/audio_template.h Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,565 @@ +/* + * QEMU Audio subsystem header + * + * Copyright (c) 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 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifdef DAC +#define NAME "playback" +#define HWBUF hw->mix_buf +#define TYPE out +#define HW HWVoiceOut +#define SW SWVoiceOut +#else +#define NAME "capture" +#define TYPE in +#define HW HWVoiceIn +#define SW SWVoiceIn +#define HWBUF hw->conv_buf +#endif + +static void glue (audio_init_nb_voices_, TYPE) ( + AudioState *s, + struct audio_driver *drv + ) +{ + int max_voices = glue (drv->max_voices_, TYPE); + int voice_size = glue (drv->voice_size_, TYPE); + + if (glue (s->nb_hw_voices_, TYPE) > max_voices) { + if (!max_voices) { +#ifdef DAC + dolog ("Driver `%s' does not support " NAME "\n", drv->name); +#endif + } + else { + dolog ("Driver `%s' does not support %d " NAME " voices, max %d\n", + drv->name, + glue (s->nb_hw_voices_, TYPE), + max_voices); + } + glue (s->nb_hw_voices_, TYPE) = max_voices; + } + + if (audio_bug (AUDIO_FUNC, !voice_size && max_voices)) { + dolog ("drv=`%s' voice_size=0 max_voices=%d\n", + drv->name, max_voices); + glue (s->nb_hw_voices_, TYPE) = 0; + } + + if (audio_bug (AUDIO_FUNC, voice_size && !max_voices)) { + dolog ("drv=`%s' voice_size=%d max_voices=0\n", + drv->name, voice_size); + } +} + +static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw) +{ + if (HWBUF) { + qemu_free (HWBUF); + } + + HWBUF = NULL; +} + +static int glue (audio_pcm_hw_alloc_resources_, TYPE) (HW *hw) +{ + HWBUF = audio_calloc (AUDIO_FUNC, hw->samples, sizeof (st_sample_t)); + if (!HWBUF) { + dolog ("Could not allocate " NAME " buffer (%d samples)\n", + hw->samples); + return -1; + } + + return 0; +} + +static void glue (audio_pcm_sw_free_resources_, TYPE) (SW *sw) +{ + if (sw->buf) { + qemu_free (sw->buf); + } + + if (sw->rate) { + st_rate_stop (sw->rate); + } + + sw->buf = NULL; + sw->rate = NULL; +} + +static int glue (audio_pcm_sw_alloc_resources_, TYPE) (SW *sw) +{ + int samples; + +#ifdef DAC + samples = sw->hw->samples; +#else + samples = ((int64_t) sw->hw->samples << 32) / sw->ratio; +#endif + + sw->buf = audio_calloc (AUDIO_FUNC, samples, sizeof (st_sample_t)); + if (!sw->buf) { + dolog ("Could not allocate buffer for `%s' (%d samples)\n", + SW_NAME (sw), samples); + return -1; + } + +#ifdef DAC + sw->rate = st_rate_start (sw->info.freq, sw->hw->info.freq); +#else + sw->rate = st_rate_start (sw->hw->info.freq, sw->info.freq); +#endif + if (!sw->rate) { + qemu_free (sw->buf); + sw->buf = NULL; + return -1; + } + return 0; +} + +static int glue (audio_pcm_sw_init_, TYPE) ( + SW *sw, + HW *hw, + const char *name, + audsettings_t *as, + int endian + ) +{ + int err; + + audio_pcm_init_info (&sw->info, as, audio_need_to_swap_endian (endian)); + sw->hw = hw; + sw->active = 0; +#ifdef DAC + sw->ratio = ((int64_t) sw->hw->info.freq << 32) / sw->info.freq; + sw->total_hw_samples_mixed = 0; + sw->empty = 1; +#else + sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq; +#endif + +#ifdef DAC + sw->conv = mixeng_conv +#else + sw->clip = mixeng_clip +#endif + [sw->info.nchannels == 2] + [sw->info.sign] + [sw->info.swap_endian] + [sw->info.bits == 16]; + + sw->name = qemu_strdup (name); + err = glue (audio_pcm_sw_alloc_resources_, TYPE) (sw); + if (err) { + qemu_free (sw->name); + sw->name = NULL; + } + return err; +} + +static void glue (audio_pcm_sw_fini_, TYPE) (SW *sw) +{ + glue (audio_pcm_sw_free_resources_, TYPE) (sw); + if (sw->name) { + qemu_free (sw->name); + sw->name = NULL; + } +} + +static void glue (audio_pcm_hw_add_sw_, TYPE) (HW *hw, SW *sw) +{ + LIST_INSERT_HEAD (&hw->sw_head, sw, entries); +} + +static void glue (audio_pcm_hw_del_sw_, TYPE) (SW *sw) +{ + LIST_REMOVE (sw, entries); +} + +static void glue (audio_pcm_hw_gc_, TYPE) (AudioState *s, HW **hwp) +{ + HW *hw = *hwp; + + if (!hw->sw_head.lh_first) { + LIST_REMOVE (hw, entries); + glue (s->nb_hw_voices_, TYPE) += 1; + glue (audio_pcm_hw_free_resources_ ,TYPE) (hw); + glue (hw->pcm_ops->fini_, TYPE) (hw); + qemu_free (hw); + *hwp = NULL; + } +} + +static HW *glue (audio_pcm_hw_find_any_, TYPE) (AudioState *s, HW *hw) +{ + return hw ? hw->entries.le_next : s->glue (hw_head_, TYPE).lh_first; +} + +static HW *glue (audio_pcm_hw_find_any_enabled_, TYPE) (AudioState *s, HW *hw) +{ + while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (s, hw))) { + if (hw->enabled) { + return hw; + } + } + return NULL; +} + +static HW *glue (audio_pcm_hw_find_specific_, TYPE) ( + AudioState *s, + HW *hw, + audsettings_t *as + ) +{ + while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (s, hw))) { + if (audio_pcm_info_eq (&hw->info, as)) { + return hw; + } + } + return NULL; +} + +static HW *glue (audio_pcm_hw_add_new_, TYPE) (AudioState *s, audsettings_t *as) +{ + HW *hw; + struct audio_driver *drv = s->drv; + + if (!glue (s->nb_hw_voices_, TYPE)) { + return NULL; + } + + if (audio_bug (AUDIO_FUNC, !drv)) { + dolog ("No host audio driver\n"); + return NULL; + } + + if (audio_bug (AUDIO_FUNC, !drv->pcm_ops)) { + dolog ("Host audio driver without pcm_ops\n"); + return NULL; + } + + hw = audio_calloc (AUDIO_FUNC, 1, glue (drv->voice_size_, TYPE)); + if (!hw) { + dolog ("Can not allocate voice `%s' size %d\n", + drv->name, glue (drv->voice_size_, TYPE)); + return NULL; + } + + hw->pcm_ops = drv->pcm_ops; + LIST_INIT (&hw->sw_head); + + if (glue (hw->pcm_ops->init_, TYPE) (hw, as)) { + goto err0; + } + + if (audio_bug (AUDIO_FUNC, hw->samples <= 0)) { + dolog ("hw->samples=%d\n", hw->samples); + goto err1; + } + +#ifdef DAC + hw->clip = mixeng_clip +#else + hw->conv = mixeng_conv +#endif + [hw->info.nchannels == 2] + [hw->info.sign] + [hw->info.swap_endian] + [hw->info.bits == 16]; + + if (glue (audio_pcm_hw_alloc_resources_, TYPE) (hw)) { + goto err1; + } + + LIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries); + glue (s->nb_hw_voices_, TYPE) -= 1; + return hw; + + err1: + glue (hw->pcm_ops->fini_, TYPE) (hw); + err0: + qemu_free (hw); + return NULL; +} + +static HW *glue (audio_pcm_hw_add_, TYPE) (AudioState *s, audsettings_t *as) +{ + HW *hw; + + if (glue (conf.fixed_, TYPE).enabled && glue (conf.fixed_, TYPE).greedy) { + hw = glue (audio_pcm_hw_add_new_, TYPE) (s, as); + if (hw) { + return hw; + } + } + + hw = glue (audio_pcm_hw_find_specific_, TYPE) (s, NULL, as); + if (hw) { + return hw; + } + + hw = glue (audio_pcm_hw_add_new_, TYPE) (s, as); + if (hw) { + return hw; + } + + return glue (audio_pcm_hw_find_any_, TYPE) (s, NULL); +} + +static SW *glue (audio_pcm_create_voice_pair_, TYPE) ( + AudioState *s, + const char *sw_name, + audsettings_t *as, + int sw_endian + ) +{ + SW *sw; + HW *hw; + audsettings_t hw_as; + + if (glue (conf.fixed_, TYPE).enabled) { + hw_as = glue (conf.fixed_, TYPE).settings; + } + else { + hw_as = *as; + } + + sw = audio_calloc (AUDIO_FUNC, 1, sizeof (*sw)); + if (!sw) { + dolog ("Could not allocate soft voice `%s' (%zu bytes)\n", + sw_name ? sw_name : "unknown", sizeof (*sw)); + goto err1; + } + + hw = glue (audio_pcm_hw_add_, TYPE) (s, &hw_as); + if (!hw) { + goto err2; + } + + glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw); + + if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as, sw_endian)) { + goto err3; + } + + return sw; + +err3: + glue (audio_pcm_hw_del_sw_, TYPE) (sw); + glue (audio_pcm_hw_gc_, TYPE) (s, &hw); +err2: + qemu_free (sw); +err1: + return NULL; +} + +static void glue (audio_close_, TYPE) (AudioState *s, SW *sw) +{ + glue (audio_pcm_sw_fini_, TYPE) (sw); + glue (audio_pcm_hw_del_sw_, TYPE) (sw); + glue (audio_pcm_hw_gc_, TYPE) (s, &sw->hw); + qemu_free (sw); +} + +void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw) +{ + if (sw) { + if (audio_bug (AUDIO_FUNC, !card || !card->audio)) { + dolog ("card=%p card->audio=%p\n", + card, card ? card->audio : NULL); + return; + } + + glue (audio_close_, TYPE) (card->audio, sw); + } +} + +SW *glue (AUD_open_, TYPE) ( + QEMUSoundCard *card, + SW *sw, + const char *name, + void *callback_opaque , + audio_callback_fn_t callback_fn, + audsettings_t *as, + int sw_endian + ) +{ + AudioState *s; +#ifdef DAC + int live = 0; + SW *old_sw = NULL; +#endif + + ldebug ("open %s, freq %d, nchannels %d, fmt %d\n", + name, as->freq, as->nchannels, as->fmt); + + if (audio_bug (AUDIO_FUNC, + !card || !card->audio || !name || !callback_fn || !as)) { + dolog ("card=%p card->audio=%p name=%p callback_fn=%p as=%p\n", + card, card ? card->audio : NULL, name, callback_fn, as); + goto fail; + } + + s = card->audio; + + if (audio_bug (AUDIO_FUNC, audio_validate_settigs (as))) { + audio_print_settings (as); + goto fail; + } + + if (audio_bug (AUDIO_FUNC, !s->drv)) { + dolog ("Can not open `%s' (no host audio driver)\n", name); + goto fail; + } + + if (sw && audio_pcm_info_eq (&sw->info, as)) { + return sw; + } + +#ifdef DAC + if (conf.plive && sw && (!sw->active && !sw->empty)) { + live = sw->total_hw_samples_mixed; + +#ifdef DEBUG_PLIVE + dolog ("Replacing voice %s with %d live samples\n", SW_NAME (sw), live); + dolog ("Old %s freq %d, bits %d, channels %d\n", + SW_NAME (sw), sw->info.freq, sw->info.bits, sw->info.nchannels); + dolog ("New %s freq %d, bits %d, channels %d\n", + name, + freq, + (fmt == AUD_FMT_S16 || fmt == AUD_FMT_U16) ? 16 : 8, + nchannels); +#endif + + if (live) { + old_sw = sw; + old_sw->callback.fn = NULL; + sw = NULL; + } + } +#endif + + if (!glue (conf.fixed_, TYPE).enabled && sw) { + glue (AUD_close_, TYPE) (card, sw); + sw = NULL; + } + + if (sw) { + HW *hw = sw->hw; + + if (!hw) { + dolog ("Internal logic error voice `%s' has no hardware store\n", + SW_NAME (sw)); + goto fail; + } + + glue (audio_pcm_sw_fini_, TYPE) (sw); + if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as, sw_endian)) { + goto fail; + } + } + else { + sw = glue (audio_pcm_create_voice_pair_, TYPE) (s, name, as, sw_endian); + if (!sw) { + dolog ("Failed to create voice `%s'\n", name); + return NULL; + } + } + + if (sw) { + sw->vol = nominal_volume; + sw->callback.fn = callback_fn; + sw->callback.opaque = callback_opaque; + +#ifdef DAC + if (live) { + int mixed = + (live << old_sw->info.shift) + * old_sw->info.bytes_per_second + / sw->info.bytes_per_second; + +#ifdef DEBUG_PLIVE + dolog ("Silence will be mixed %d\n", mixed); +#endif + sw->total_hw_samples_mixed += mixed; + } +#endif + +#ifdef DEBUG_AUDIO + dolog ("%s\n", name); + audio_pcm_print_info ("hw", &sw->hw->info); + audio_pcm_print_info ("sw", &sw->info); +#endif + } + + return sw; + + fail: + glue (AUD_close_, TYPE) (card, sw); + return NULL; +} + +int glue (AUD_is_active_, TYPE) (SW *sw) +{ + return sw ? sw->active : 0; +} + +void glue (AUD_init_time_stamp_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts) +{ + if (!sw) { + return; + } + + ts->old_ts = sw->hw->ts_helper; +} + +uint64_t glue (AUD_get_elapsed_usec_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts) +{ + uint64_t delta, cur_ts, old_ts; + + if (!sw) { + return 0; + } + + cur_ts = sw->hw->ts_helper; + old_ts = ts->old_ts; + /* dolog ("cur %lld old %lld\n", cur_ts, old_ts); */ + + if (cur_ts >= old_ts) { + delta = cur_ts - old_ts; + } + else { + delta = UINT64_MAX - old_ts + cur_ts; + } + + if (!delta) { + return 0; + } + + return (delta * sw->hw->info.freq) / 1000000; +} + +#undef TYPE +#undef HW +#undef SW +#undef HWBUF +#undef NAME diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/audio/coreaudio.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/audio/coreaudio.c Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,564 @@ +/* + * QEMU OS X CoreAudio audio driver + * + * Copyright (c) 2005 Mike Kronenberg + * + * 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 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <CoreAudio/CoreAudio.h> +#include <string.h> /* strerror */ +#include <pthread.h> /* pthread_X */ + +#include "vl.h" + +#define AUDIO_CAP "coreaudio" +#include "audio_int.h" + +struct { + int buffer_frames; + int nbuffers; + int isAtexit; +} conf = { + .buffer_frames = 512, + .nbuffers = 4, + .isAtexit = 0 +}; + +typedef struct coreaudioVoiceOut { + HWVoiceOut hw; + pthread_mutex_t mutex; + int isAtexit; + AudioDeviceID outputDeviceID; + UInt32 audioDevicePropertyBufferFrameSize; + AudioStreamBasicDescription outputStreamBasicDescription; + int live; + int decr; + int rpos; +} coreaudioVoiceOut; + +static void coreaudio_logstatus (OSStatus status) +{ + char *str = "BUG"; + + switch(status) { + case kAudioHardwareNoError: + str = "kAudioHardwareNoError"; + break; + + case kAudioHardwareNotRunningError: + str = "kAudioHardwareNotRunningError"; + break; + + case kAudioHardwareUnspecifiedError: + str = "kAudioHardwareUnspecifiedError"; + break; + + case kAudioHardwareUnknownPropertyError: + str = "kAudioHardwareUnknownPropertyError"; + break; + + case kAudioHardwareBadPropertySizeError: + str = "kAudioHardwareBadPropertySizeError"; + break; + + case kAudioHardwareIllegalOperationError: + str = "kAudioHardwareIllegalOperationError"; + break; + + case kAudioHardwareBadDeviceError: + str = "kAudioHardwareBadDeviceError"; + break; + + case kAudioHardwareBadStreamError: + str = "kAudioHardwareBadStreamError"; + break; + + case kAudioHardwareUnsupportedOperationError: + str = "kAudioHardwareUnsupportedOperationError"; + break; + + case kAudioDeviceUnsupportedFormatError: + str = "kAudioDeviceUnsupportedFormatError"; + break; + + case kAudioDevicePermissionsError: + str = "kAudioDevicePermissionsError"; + break; + + default: + AUD_log (AUDIO_CAP, "Reason: status code %ld\n", status); + return; + } + + AUD_log (AUDIO_CAP, "Reason: %s\n", str); +} + +static void GCC_FMT_ATTR (2, 3) coreaudio_logerr ( + OSStatus status, + const char *fmt, + ... + ) +{ + va_list ap; + + va_start (ap, fmt); + AUD_log (AUDIO_CAP, fmt, ap); + va_end (ap); + + coreaudio_logstatus (status); +} + +static void GCC_FMT_ATTR (3, 4) coreaudio_logerr2 ( + OSStatus status, + 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); + + coreaudio_logstatus (status); +} + +static inline UInt32 isPlaying (AudioDeviceID outputDeviceID) +{ + OSStatus status; + UInt32 result = 0; + UInt32 propertySize = sizeof(outputDeviceID); + status = AudioDeviceGetProperty( + outputDeviceID, 0, 0, + kAudioDevicePropertyDeviceIsRunning, &propertySize, &result); + if (status != kAudioHardwareNoError) { + coreaudio_logerr(status, + "Could not determine whether Device is playing\n"); + } + return result; +} + +static void coreaudio_atexit (void) +{ + conf.isAtexit = 1; +} + +static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name) +{ + int err; + + err = pthread_mutex_lock (&core->mutex); + if (err) { + dolog ("Could not lock voice for %s\nReason: %s\n", + fn_name, strerror (err)); + return -1; + } + return 0; +} + +static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name) +{ + int err; + + err = pthread_mutex_unlock (&core->mutex); + if (err) { + dolog ("Could not unlock voice for %s\nReason: %s\n", + fn_name, strerror (err)); + return -1; + } + return 0; +} + +static int coreaudio_run_out (HWVoiceOut *hw) +{ + int live, decr; + coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; + + if (coreaudio_lock (core, "coreaudio_run_out")) { + return 0; + } + + live = audio_pcm_hw_get_live_out (hw); + + if (core->decr > live) { + ldebug ("core->decr %d live %d core->live %d\n", + core->decr, + live, + core->live); + } + + decr = audio_MIN (core->decr, live); + core->decr -= decr; + + core->live = live - decr; + hw->rpos = core->rpos; + + coreaudio_unlock (core, "coreaudio_run_out"); + return decr; +} + +/* callback to feed audiooutput buffer */ +static OSStatus audioDeviceIOProc( + AudioDeviceID inDevice, + const AudioTimeStamp* inNow, + const AudioBufferList* inInputData, + const AudioTimeStamp* inInputTime, + AudioBufferList* outOutputData, + const AudioTimeStamp* inOutputTime, + void* hwptr) +{ + UInt32 frame, frameCount; + float *out = outOutputData->mBuffers[0].mData; + HWVoiceOut *hw = hwptr; + coreaudioVoiceOut *core = (coreaudioVoiceOut *) hwptr; + int rpos, live; + st_sample_t *src; +#ifndef FLOAT_MIXENG +#ifdef RECIPROCAL + const float scale = 1.f / UINT_MAX; +#else + const float scale = UINT_MAX; +#endif +#endif + + if (coreaudio_lock (core, "audioDeviceIOProc")) { + inInputTime = 0; + return 0; + } + + frameCount = core->audioDevicePropertyBufferFrameSize; + live = core->live; + + /* if there are not enough samples, set signal and return */ + if (live < frameCount) { + inInputTime = 0; + coreaudio_unlock (core, "audioDeviceIOProc(empty)"); + return 0; + } + + rpos = core->rpos; + src = hw->mix_buf + rpos; + + /* fill buffer */ + for (frame = 0; frame < frameCount; frame++) { +#ifdef FLOAT_MIXENG + *out++ = src[frame].l; /* left channel */ + *out++ = src[frame].r; /* right channel */ +#else +#ifdef RECIPROCAL + *out++ = src[frame].l * scale; /* left channel */ + *out++ = src[frame].r * scale; /* right channel */ +#else + *out++ = src[frame].l / scale; /* left channel */ + *out++ = src[frame].r / scale; /* right channel */ +#endif +#endif + } + + /* cleanup */ + mixeng_clear (src, frameCount); + rpos = (rpos + frameCount) % hw->samples; + core->decr += frameCount; + core->rpos = rpos; + + coreaudio_unlock (core, "audioDeviceIOProc"); + return 0; +} + +static int coreaudio_write (SWVoiceOut *sw, void *buf, int len) +{ + return audio_pcm_sw_write (sw, buf, len); +} + +static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as) +{ + OSStatus status; + coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; + UInt32 propertySize; + int err; + int bits = 8; + int endianess = 0; + const char *typ = "playback"; + AudioValueRange frameRange; + + /* create mutex */ + err = pthread_mutex_init(&core->mutex, NULL); + if (err) { + dolog("Could not create mutex\nReason: %s\n", strerror (err)); + return -1; + } + + if (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) { + bits = 16; + endianess = 1; + } + + audio_pcm_init_info ( + &hw->info, + as, + /* Following is irrelevant actually since we do not use + mixengs clipping routines */ + audio_need_to_swap_endian (endianess) + ); + + /* open default output device */ + propertySize = sizeof(core->outputDeviceID); + status = AudioHardwareGetProperty( + kAudioHardwarePropertyDefaultOutputDevice, + &propertySize, + &core->outputDeviceID); + if (status != kAudioHardwareNoError) { + coreaudio_logerr2 (status, typ, + "Could not get default output Device\n"); + return -1; + } + if (core->outputDeviceID == kAudioDeviceUnknown) { + dolog ("Could not initialize %s - Unknown Audiodevice\n", typ); + return -1; + } + + /* get minimum and maximum buffer frame sizes */ + propertySize = sizeof(frameRange); + status = AudioDeviceGetProperty( + core->outputDeviceID, + 0, + 0, + kAudioDevicePropertyBufferFrameSizeRange, + &propertySize, + &frameRange); + if (status != kAudioHardwareNoError) { + coreaudio_logerr2 (status, typ, + "Could not get device buffer frame range\n"); + return -1; + } + + if (frameRange.mMinimum > conf.buffer_frames) { + core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMinimum; + dolog ("warning: Upsizing Buffer Frames to %f\n", frameRange.mMinimum); + } + else if (frameRange.mMaximum < conf.buffer_frames) { + core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMaximum; + dolog ("warning: Downsizing Buffer Frames to %f\n", frameRange.mMaximum); + } + else { + core->audioDevicePropertyBufferFrameSize = conf.buffer_frames; + } + + /* set Buffer Frame Size */ + propertySize = sizeof(core->audioDevicePropertyBufferFrameSize); + status = AudioDeviceSetProperty( + core->outputDeviceID, + NULL, + 0, + false, + kAudioDevicePropertyBufferFrameSize, + propertySize, + &core->audioDevicePropertyBufferFrameSize); + if (status != kAudioHardwareNoError) { + coreaudio_logerr2 (status, typ, + "Could not set device buffer frame size %ld\n", + core->audioDevicePropertyBufferFrameSize); + return -1; + } + + /* get Buffer Frame Size */ + propertySize = sizeof(core->audioDevicePropertyBufferFrameSize); + status = AudioDeviceGetProperty( + core->outputDeviceID, + 0, + false, + kAudioDevicePropertyBufferFrameSize, + &propertySize, + &core->audioDevicePropertyBufferFrameSize); + if (status != kAudioHardwareNoError) { + coreaudio_logerr2 (status, typ, + "Could not get device buffer frame size\n"); + return -1; + } + hw->samples = conf.nbuffers * core->audioDevicePropertyBufferFrameSize; + + /* get StreamFormat */ + propertySize = sizeof(core->outputStreamBasicDescription); + status = AudioDeviceGetProperty( + core->outputDeviceID, + 0, + false, + kAudioDevicePropertyStreamFormat, + &propertySize, + &core->outputStreamBasicDescription); + if (status != kAudioHardwareNoError) { + coreaudio_logerr2 (status, typ, + "Could not get Device Stream properties\n"); + core->outputDeviceID = kAudioDeviceUnknown; + return -1; + } + + /* set Samplerate */ + core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq; + propertySize = sizeof(core->outputStreamBasicDescription); + status = AudioDeviceSetProperty( + core->outputDeviceID, + 0, + 0, + 0, + kAudioDevicePropertyStreamFormat, + propertySize, + &core->outputStreamBasicDescription); + if (status != kAudioHardwareNoError) { + coreaudio_logerr2 (status, typ, "Could not set samplerate %d\n", + as->freq); + core->outputDeviceID = kAudioDeviceUnknown; + return -1; + } + + /* set Callback */ + status = AudioDeviceAddIOProc(core->outputDeviceID, audioDeviceIOProc, hw); + if (status != kAudioHardwareNoError) { + coreaudio_logerr2 (status, typ, "Could not set IOProc\n"); + core->outputDeviceID = kAudioDeviceUnknown; + return -1; + } + + /* start Playback */ + if (!isPlaying(core->outputDeviceID)) { + status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc); + if (status != kAudioHardwareNoError) { + coreaudio_logerr2 (status, typ, "Could not start playback\n"); + AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc); + core->outputDeviceID = kAudioDeviceUnknown; + return -1; + } + } + + return 0; +} + +static void coreaudio_fini_out (HWVoiceOut *hw) +{ + OSStatus status; + int err; + coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; + + if (!conf.isAtexit) { + /* stop playback */ + if (isPlaying(core->outputDeviceID)) { + status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc); + if (status != kAudioHardwareNoError) { + coreaudio_logerr (status, "Could not stop playback\n"); + } + } + + /* remove callback */ + status = AudioDeviceRemoveIOProc(core->outputDeviceID, + audioDeviceIOProc); + if (status != kAudioHardwareNoError) { + coreaudio_logerr (status, "Could not remove IOProc\n"); + } + } + core->outputDeviceID = kAudioDeviceUnknown; + + /* destroy mutex */ + err = pthread_mutex_destroy(&core->mutex); + if (err) { + dolog("Could not destroy mutex\nReason: %s\n", strerror (err)); + } +} + +static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...) +{ + OSStatus status; + coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; + + switch (cmd) { + case VOICE_ENABLE: + /* start playback */ + if (!isPlaying(core->outputDeviceID)) { + status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc); + if (status != kAudioHardwareNoError) { + coreaudio_logerr (status, "Could not resume playback\n"); + } + } + break; + + case VOICE_DISABLE: + /* stop playback */ + if (!conf.isAtexit) { + if (isPlaying(core->outputDeviceID)) { + status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc); + if (status != kAudioHardwareNoError) { + coreaudio_logerr (status, "Could not pause playback\n"); + } + } + } + break; + } + return 0; +} + +static void *coreaudio_audio_init (void) +{ + atexit(coreaudio_atexit); + return &coreaudio_audio_init; +} + +static void coreaudio_audio_fini (void *opaque) +{ + (void) opaque; +} + +static struct audio_option coreaudio_options[] = { + {"BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_frames, + "Size of the buffer in frames", NULL, 0}, + {"BUFFER_COUNT", AUD_OPT_INT, &conf.nbuffers, + "Number of buffers", NULL, 0}, + {NULL, 0, NULL, NULL, NULL, 0} +}; + +static struct audio_pcm_ops coreaudio_pcm_ops = { + coreaudio_init_out, + coreaudio_fini_out, + coreaudio_run_out, + coreaudio_write, + coreaudio_ctl_out, + + NULL, + NULL, + NULL, + NULL, + NULL +}; + +struct audio_driver coreaudio_audio_driver = { + INIT_FIELD (name = ) "coreaudio", + INIT_FIELD (descr = ) + "CoreAudio http://developer.apple.com/audio/coreaudio.html", + INIT_FIELD (options = ) coreaudio_options, + INIT_FIELD (init = ) coreaudio_audio_init, + INIT_FIELD (fini = ) coreaudio_audio_fini, + INIT_FIELD (pcm_ops = ) &coreaudio_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 (coreaudioVoiceOut), + INIT_FIELD (voice_size_in = ) 0 +}; diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/audio/dsound_template.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/audio/dsound_template.h Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,282 @@ +/* + * QEMU DirectSound audio driver header + * + * Copyright (c) 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 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifdef DSBTYPE_IN +#define NAME "capture buffer" +#define TYPE in +#define IFACE IDirectSoundCaptureBuffer +#define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER +#define FIELD dsound_capture_buffer +#else +#define NAME "playback buffer" +#define TYPE out +#define IFACE IDirectSoundBuffer +#define BUFPTR LPDIRECTSOUNDBUFFER +#define FIELD dsound_buffer +#endif + +static int glue (dsound_unlock_, TYPE) ( + BUFPTR buf, + LPVOID p1, + LPVOID p2, + DWORD blen1, + DWORD blen2 + ) +{ + HRESULT hr; + + hr = glue (IFACE, _Unlock) (buf, p1, blen1, p2, blen2); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not unlock " NAME "\n"); + return -1; + } + + return 0; +} + +static int glue (dsound_lock_, TYPE) ( + BUFPTR buf, + struct audio_pcm_info *info, + DWORD pos, + DWORD len, + LPVOID *p1p, + LPVOID *p2p, + DWORD *blen1p, + DWORD *blen2p, + int entire + ) +{ + HRESULT hr; + int i; + LPVOID p1 = NULL, p2 = NULL; + DWORD blen1 = 0, blen2 = 0; + + for (i = 0; i < conf.lock_retries; ++i) { + hr = glue (IFACE, _Lock) ( + buf, + pos, + len, + &p1, + &blen1, + &p2, + &blen2, + (entire +#ifdef DSBTYPE_IN + ? DSCBLOCK_ENTIREBUFFER +#else + ? DSBLOCK_ENTIREBUFFER +#endif + : 0) + ); + + if (FAILED (hr)) { +#ifndef DSBTYPE_IN + if (hr == DSERR_BUFFERLOST) { + if (glue (dsound_restore_, TYPE) (buf)) { + dsound_logerr (hr, "Could not lock " NAME "\n"); + goto fail; + } + continue; + } +#endif + dsound_logerr (hr, "Could not lock " NAME "\n"); + goto fail; + } + + break; + } + + if (i == conf.lock_retries) { + dolog ("%d attempts to lock " NAME " failed\n", i); + goto fail; + } + + if ((p1 && (blen1 & info->align)) || (p2 && (blen2 & info->align))) { + dolog ("DirectSound returned misaligned buffer %ld %ld\n", + blen1, blen2); + glue (dsound_unlock_, TYPE) (buf, p1, p2, blen1, blen2); + goto fail; + } + + if (!p1 && blen1) { + dolog ("warning: !p1 && blen1=%ld\n", blen1); + blen1 = 0; + } + + if (!p2 && blen2) { + dolog ("warning: !p2 && blen2=%ld\n", blen2); + blen2 = 0; + } + + *p1p = p1; + *p2p = p2; + *blen1p = blen1; + *blen2p = blen2; + return 0; + + fail: + *p1p = NULL - 1; + *p2p = NULL - 1; + *blen1p = -1; + *blen2p = -1; + return -1; +} + +#ifdef DSBTYPE_IN +static void dsound_fini_in (HWVoiceIn *hw) +#else +static void dsound_fini_out (HWVoiceOut *hw) +#endif +{ + HRESULT hr; +#ifdef DSBTYPE_IN + DSoundVoiceIn *ds = (DSoundVoiceIn *) hw; +#else + DSoundVoiceOut *ds = (DSoundVoiceOut *) hw; +#endif + + if (ds->FIELD) { + hr = glue (IFACE, _Stop) (ds->FIELD); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not stop " NAME "\n"); + } + + hr = glue (IFACE, _Release) (ds->FIELD); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not release " NAME "\n"); + } + ds->FIELD = NULL; + } +} + +#ifdef DSBTYPE_IN +static int dsound_init_in (HWVoiceIn *hw, audsettings_t *as) +#else +static int dsound_init_out (HWVoiceOut *hw, audsettings_t *as) +#endif +{ + int err; + HRESULT hr; + dsound *s = &glob_dsound; + WAVEFORMATEX wfx; + audsettings_t obt_as; +#ifdef DSBTYPE_IN + const char *typ = "ADC"; + DSoundVoiceIn *ds = (DSoundVoiceIn *) hw; + DSCBUFFERDESC bd; + DSCBCAPS bc; +#else + const char *typ = "DAC"; + DSoundVoiceOut *ds = (DSoundVoiceOut *) hw; + DSBUFFERDESC bd; + DSBCAPS bc; +#endif + + err = waveformat_from_audio_settings (&wfx, as); + if (err) { + return -1; + } + + memset (&bd, 0, sizeof (bd)); + bd.dwSize = sizeof (bd); + bd.lpwfxFormat = &wfx; +#ifdef DSBTYPE_IN + bd.dwBufferBytes = conf.bufsize_in; + hr = IDirectSoundCapture_CreateCaptureBuffer ( + s->dsound_capture, + &bd, + &ds->dsound_capture_buffer, + NULL + ); +#else + bd.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2; + bd.dwBufferBytes = conf.bufsize_out; + hr = IDirectSound_CreateSoundBuffer ( + s->dsound, + &bd, + &ds->dsound_buffer, + NULL + ); +#endif + + if (FAILED (hr)) { + dsound_logerr2 (hr, typ, "Could not create " NAME "\n"); + return -1; + } + + hr = glue (IFACE, _GetFormat) (ds->FIELD, &wfx, sizeof (wfx), NULL); + if (FAILED (hr)) { + dsound_logerr2 (hr, typ, "Could not get " NAME " format\n"); + goto fail0; + } + +#ifdef DEBUG_DSOUND + dolog (NAME "\n"); + print_wave_format (&wfx); +#endif + + memset (&bc, 0, sizeof (bc)); + bc.dwSize = sizeof (bc); + + hr = glue (IFACE, _GetCaps) (ds->FIELD, &bc); + if (FAILED (hr)) { + dsound_logerr2 (hr, typ, "Could not get " NAME " format\n"); + goto fail0; + } + + err = waveformat_to_audio_settings (&wfx, &obt_as); + if (err) { + goto fail0; + } + + ds->first_time = 1; + + audio_pcm_init_info (&hw->info, &obt_as, audio_need_to_swap_endian (0)); + + if (bc.dwBufferBytes & hw->info.align) { + dolog ( + "GetCaps returned misaligned buffer size %ld, alignment %d\n", + bc.dwBufferBytes, hw->info.align + 1 + ); + } + hw->samples = bc.dwBufferBytes >> hw->info.shift; + +#ifdef DEBUG_DSOUND + dolog ("caps %ld, desc %ld\n", + bc.dwBufferBytes, bd.dwBufferBytes); + + dolog ("bufsize %d, freq %d, chan %d, fmt %d\n", + hw->bufsize, settings.freq, settings.nchannels, settings.fmt); +#endif + return 0; + + fail0: + glue (dsound_fini_, TYPE) (hw); + return -1; +} + +#undef NAME +#undef TYPE +#undef IFACE +#undef BUFPTR +#undef FIELD diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/audio/dsoundaudio.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/audio/dsoundaudio.c Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,1076 @@ +/* + * QEMU DirectSound audio driver + * + * Copyright (c) 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 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* + * SEAL 1.07 by Carlos 'pel' Hasan was used as documentation + */ + +#include "vl.h" + +#define AUDIO_CAP "dsound" +#include "audio_int.h" + +#include <windows.h> +#include <objbase.h> +#include <dsound.h> + +/* #define DEBUG_DSOUND */ + +static struct { + int lock_retries; + int restore_retries; + int getstatus_retries; + int set_primary; + int bufsize_in; + int bufsize_out; + audsettings_t settings; + int latency_millis; +} conf = { + 1, + 1, + 1, + 0, + 16384, + 16384, + { + 44100, + 2, + AUD_FMT_S16 + }, + 10 +}; + +typedef struct { + LPDIRECTSOUND dsound; + LPDIRECTSOUNDCAPTURE dsound_capture; + LPDIRECTSOUNDBUFFER dsound_primary_buffer; + audsettings_t settings; +} dsound; + +static dsound glob_dsound; + +typedef struct { + HWVoiceOut hw; + LPDIRECTSOUNDBUFFER dsound_buffer; + DWORD old_pos; + int first_time; +#ifdef DEBUG_DSOUND + DWORD old_ppos; + DWORD played; + DWORD mixed; +#endif +} DSoundVoiceOut; + +typedef struct { + HWVoiceIn hw; + int first_time; + LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer; +} DSoundVoiceIn; + +static void dsound_log_hresult (HRESULT hr) +{ + const char *str = "BUG"; + + switch (hr) { + case DS_OK: + str = "The method succeeded"; + break; +#ifdef DS_NO_VIRTUALIZATION + case DS_NO_VIRTUALIZATION: + str = "The buffer was created, but another 3D algorithm was substituted"; + break; +#endif +#ifdef DS_INCOMPLETE + case DS_INCOMPLETE: + str = "The method succeeded, but not all the optional effects were obtained"; + break; +#endif +#ifdef DSERR_ACCESSDENIED + case DSERR_ACCESSDENIED: + str = "The request failed because access was denied"; + break; +#endif +#ifdef DSERR_ALLOCATED + case DSERR_ALLOCATED: + str = "The request failed because resources, such as a priority level, were already in use by another caller"; + break; +#endif +#ifdef DSERR_ALREADYINITIALIZED + case DSERR_ALREADYINITIALIZED: + str = "The object is already initialized"; + break; +#endif +#ifdef DSERR_BADFORMAT + case DSERR_BADFORMAT: + str = "The specified wave format is not supported"; + break; +#endif +#ifdef DSERR_BADSENDBUFFERGUID + case DSERR_BADSENDBUFFERGUID: + str = "The GUID specified in an audiopath file does not match a valid mix-in buffer"; + break; +#endif +#ifdef DSERR_BUFFERLOST + case DSERR_BUFFERLOST: + str = "The buffer memory has been lost and must be restored"; + break; +#endif +#ifdef DSERR_BUFFERTOOSMALL + case DSERR_BUFFERTOOSMALL: + str = "The buffer size is not great enough to enable effects processing"; + break; +#endif +#ifdef DSERR_CONTROLUNAVAIL + case DSERR_CONTROLUNAVAIL: + str = "The buffer control (volume, pan, and so on) requested by the caller is not available. Controls must be specified when the buffer is created, using the dwFlags member of DSBUFFERDESC"; + break; +#endif +#ifdef DSERR_DS8_REQUIRED + case DSERR_DS8_REQUIRED: + str = "A DirectSound object of class CLSID_DirectSound8 or later is required for the requested functionality. For more information, see IDirectSound8 Interface"; + break; +#endif +#ifdef DSERR_FXUNAVAILABLE + case DSERR_FXUNAVAILABLE: + str = "The effects requested could not be found on the system, or they are in the wrong order or in the wrong location; for example, an effect expected in hardware was found in software"; + break; +#endif +#ifdef DSERR_GENERIC + case DSERR_GENERIC : + str = "An undetermined error occurred inside the DirectSound subsystem"; + break; +#endif +#ifdef DSERR_INVALIDCALL + case DSERR_INVALIDCALL: + str = "This function is not valid for the current state of this object"; + break; +#endif +#ifdef DSERR_INVALIDPARAM + case DSERR_INVALIDPARAM: + str = "An invalid parameter was passed to the returning function"; + break; +#endif +#ifdef DSERR_NOAGGREGATION + case DSERR_NOAGGREGATION: + str = "The object does not support aggregation"; + break; +#endif +#ifdef DSERR_NODRIVER + case DSERR_NODRIVER: + str = "No sound driver is available for use, or the given GUID is not a valid DirectSound device ID"; + break; +#endif +#ifdef DSERR_NOINTERFACE + case DSERR_NOINTERFACE: + str = "The requested COM interface is not available"; + break; +#endif +#ifdef DSERR_OBJECTNOTFOUND + case DSERR_OBJECTNOTFOUND: + str = "The requested object was not found"; + break; +#endif +#ifdef DSERR_OTHERAPPHASPRIO + case DSERR_OTHERAPPHASPRIO: + str = "Another application has a higher priority level, preventing this call from succeeding"; + break; +#endif +#ifdef DSERR_OUTOFMEMORY + case DSERR_OUTOFMEMORY: + str = "The DirectSound subsystem could not allocate sufficient memory to complete the caller's request"; + break; +#endif +#ifdef DSERR_PRIOLEVELNEEDED + case DSERR_PRIOLEVELNEEDED: + str = "A cooperative level of DSSCL_PRIORITY or higher is required"; + break; +#endif +#ifdef DSERR_SENDLOOP + case DSERR_SENDLOOP: + str = "A circular loop of send effects was detected"; + break; +#endif +#ifdef DSERR_UNINITIALIZED + case DSERR_UNINITIALIZED: + str = "The Initialize method has not been called or has not been called successfully before other methods were called"; + break; +#endif +#ifdef DSERR_UNSUPPORTED + case DSERR_UNSUPPORTED: + str = "The function called is not supported at this time"; + break; +#endif + default: + AUD_log (AUDIO_CAP, "Reason: Unknown (HRESULT %#lx)\n", hr); + return; + } + + AUD_log (AUDIO_CAP, "Reason: %s\n", str); +} + +static void GCC_FMT_ATTR (2, 3) dsound_logerr ( + HRESULT hr, + const char *fmt, + ... + ) +{ + va_list ap; + + va_start (ap, fmt); + AUD_vlog (AUDIO_CAP, fmt, ap); + va_end (ap); + + dsound_log_hresult (hr); +} + +static void GCC_FMT_ATTR (3, 4) dsound_logerr2 ( + HRESULT hr, + 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); + + dsound_log_hresult (hr); +} + +static DWORD millis_to_bytes (struct audio_pcm_info *info, DWORD millis) +{ + return (millis * info->bytes_per_second) / 1000; +} + +#ifdef DEBUG_DSOUND +static void print_wave_format (WAVEFORMATEX *wfx) +{ + dolog ("tag = %d\n", wfx->wFormatTag); + dolog ("nChannels = %d\n", wfx->nChannels); + dolog ("nSamplesPerSec = %ld\n", wfx->nSamplesPerSec); + dolog ("nAvgBytesPerSec = %ld\n", wfx->nAvgBytesPerSec); + dolog ("nBlockAlign = %d\n", wfx->nBlockAlign); + dolog ("wBitsPerSample = %d\n", wfx->wBitsPerSample); + dolog ("cbSize = %d\n", wfx->cbSize); +} +#endif + +static int dsound_restore_out (LPDIRECTSOUNDBUFFER dsb) +{ + HRESULT hr; + int i; + + for (i = 0; i < conf.restore_retries; ++i) { + hr = IDirectSoundBuffer_Restore (dsb); + + switch (hr) { + case DS_OK: + return 0; + + case DSERR_BUFFERLOST: + continue; + + default: + dsound_logerr (hr, "Could not restore playback buffer\n"); + return -1; + } + } + + dolog ("%d attempts to restore playback buffer failed\n", i); + return -1; +} + +static int waveformat_from_audio_settings (WAVEFORMATEX *wfx, audsettings_t *as) +{ + memset (wfx, 0, sizeof (*wfx)); + + wfx->wFormatTag = WAVE_FORMAT_PCM; + wfx->nChannels = as->nchannels; + wfx->nSamplesPerSec = as->freq; + wfx->nAvgBytesPerSec = as->freq << (as->nchannels == 2); + wfx->nBlockAlign = 1 << (as->nchannels == 2); + wfx->cbSize = 0; + + switch (as->fmt) { + case AUD_FMT_S8: + wfx->wBitsPerSample = 8; + break; + + case AUD_FMT_U8: + wfx->wBitsPerSample = 8; + break; + + case AUD_FMT_S16: + wfx->wBitsPerSample = 16; + wfx->nAvgBytesPerSec <<= 1; + wfx->nBlockAlign <<= 1; + break; + + case AUD_FMT_U16: + wfx->wBitsPerSample = 16; + wfx->nAvgBytesPerSec <<= 1; + wfx->nBlockAlign <<= 1; + break; + + default: + dolog ("Internal logic error: Bad audio format %d\n", as->freq); + return -1; + } + + return 0; +} + +static int waveformat_to_audio_settings (WAVEFORMATEX *wfx, audsettings_t *as) +{ + if (wfx->wFormatTag != WAVE_FORMAT_PCM) { + dolog ("Invalid wave format, tag is not PCM, but %d\n", + wfx->wFormatTag); + return -1; + } + + if (!wfx->nSamplesPerSec) { + dolog ("Invalid wave format, frequency is zero\n"); + return -1; + } + as->freq = wfx->nSamplesPerSec; + + switch (wfx->nChannels) { + case 1: + as->nchannels = 1; + break; + + case 2: + as->nchannels = 2; + break; + + default: + dolog ( + "Invalid wave format, number of channels is not 1 or 2, but %d\n", + wfx->nChannels + ); + return -1; + } + + switch (wfx->wBitsPerSample) { + case 8: + as->fmt = AUD_FMT_U8; + break; + + case 16: + as->fmt = AUD_FMT_S16; + break; + + default: + dolog ("Invalid wave format, bits per sample is not 8 or 16, but %d\n", + wfx->wBitsPerSample); + return -1; + } + + return 0; +} + +#include "dsound_template.h" +#define DSBTYPE_IN +#include "dsound_template.h" +#undef DSBTYPE_IN + +static int dsound_get_status_out (LPDIRECTSOUNDBUFFER dsb, DWORD *statusp) +{ + HRESULT hr; + int i; + + for (i = 0; i < conf.getstatus_retries; ++i) { + hr = IDirectSoundBuffer_GetStatus (dsb, statusp); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not get playback buffer status\n"); + return -1; + } + + if (*statusp & DSERR_BUFFERLOST) { + if (dsound_restore_out (dsb)) { + return -1; + } + continue; + } + break; + } + + return 0; +} + +static int dsound_get_status_in (LPDIRECTSOUNDCAPTUREBUFFER dscb, + DWORD *statusp) +{ + HRESULT hr; + + hr = IDirectSoundCaptureBuffer_GetStatus (dscb, statusp); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not get capture buffer status\n"); + return -1; + } + + return 0; +} + +static void dsound_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len) +{ + int src_len1 = dst_len; + int src_len2 = 0; + int pos = hw->rpos + dst_len; + st_sample_t *src1 = hw->mix_buf + hw->rpos; + st_sample_t *src2 = NULL; + + if (pos > hw->samples) { + src_len1 = hw->samples - hw->rpos; + src2 = hw->mix_buf; + src_len2 = dst_len - src_len1; + pos = src_len2; + } + + if (src_len1) { + hw->clip (dst, src1, src_len1); + mixeng_clear (src1, src_len1); + } + + if (src_len2) { + dst = advance (dst, src_len1 << hw->info.shift); + hw->clip (dst, src2, src_len2); + mixeng_clear (src2, src_len2); + } + + hw->rpos = pos % hw->samples; +} + +static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb) +{ + int err; + LPVOID p1, p2; + DWORD blen1, blen2, len1, len2; + + err = dsound_lock_out ( + dsb, + &hw->info, + 0, + hw->samples << hw->info.shift, + &p1, &p2, + &blen1, &blen2, + 1 + ); + if (err) { + return; + } + + len1 = blen1 >> hw->info.shift; + len2 = blen2 >> hw->info.shift; + +#ifdef DEBUG_DSOUND + dolog ("clear %p,%ld,%ld %p,%ld,%ld\n", + p1, blen1, len1, + p2, blen2, len2); +#endif + + if (p1 && len1) { + audio_pcm_info_clear_buf (&hw->info, p1, len1); + } + + if (p2 && len2) { + audio_pcm_info_clear_buf (&hw->info, p2, len2); + } + + dsound_unlock_out (dsb, p1, p2, blen1, blen2); +} + +static void dsound_close (dsound *s) +{ + HRESULT hr; + + if (s->dsound_primary_buffer) { + hr = IDirectSoundBuffer_Release (s->dsound_primary_buffer); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not release primary buffer\n"); + } + s->dsound_primary_buffer = NULL; + } +} + +static int dsound_open (dsound *s) +{ + int err; + HRESULT hr; + WAVEFORMATEX wfx; + DSBUFFERDESC dsbd; + HWND hwnd; + + hwnd = GetForegroundWindow (); + hr = IDirectSound_SetCooperativeLevel ( + s->dsound, + hwnd, + DSSCL_PRIORITY + ); + + if (FAILED (hr)) { + dsound_logerr (hr, "Could not set cooperative level for window %p\n", + hwnd); + return -1; + } + + if (!conf.set_primary) { + return 0; + } + + err = waveformat_from_audio_settings (&wfx, &conf.settings); + if (err) { + return -1; + } + + memset (&dsbd, 0, sizeof (dsbd)); + dsbd.dwSize = sizeof (dsbd); + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsbd.dwBufferBytes = 0; + dsbd.lpwfxFormat = NULL; + + hr = IDirectSound_CreateSoundBuffer ( + s->dsound, + &dsbd, + &s->dsound_primary_buffer, + NULL + ); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not create primary playback buffer\n"); + return -1; + } + + hr = IDirectSoundBuffer_SetFormat (s->dsound_primary_buffer, &wfx); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not set primary playback buffer format\n"); + } + + hr = IDirectSoundBuffer_GetFormat ( + s->dsound_primary_buffer, + &wfx, + sizeof (wfx), + NULL + ); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not get primary playback buffer format\n"); + goto fail0; + } + +#ifdef DEBUG_DSOUND + dolog ("Primary\n"); + print_wave_format (&wfx); +#endif + + err = waveformat_to_audio_settings (&wfx, &s->settings); + if (err) { + goto fail0; + } + + return 0; + + fail0: + dsound_close (s); + return -1; +} + +static int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...) +{ + HRESULT hr; + DWORD status; + DSoundVoiceOut *ds = (DSoundVoiceOut *) hw; + LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer; + + if (!dsb) { + dolog ("Attempt to control voice without a buffer\n"); + return 0; + } + + switch (cmd) { + case VOICE_ENABLE: + if (dsound_get_status_out (dsb, &status)) { + return -1; + } + + if (status & DSBSTATUS_PLAYING) { + dolog ("warning: Voice is already playing\n"); + return 0; + } + + dsound_clear_sample (hw, dsb); + + hr = IDirectSoundBuffer_Play (dsb, 0, 0, DSBPLAY_LOOPING); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not start playing buffer\n"); + return -1; + } + break; + + case VOICE_DISABLE: + if (dsound_get_status_out (dsb, &status)) { + return -1; + } + + if (status & DSBSTATUS_PLAYING) { + hr = IDirectSoundBuffer_Stop (dsb); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not stop playing buffer\n"); + return -1; + } + } + else { + dolog ("warning: Voice is not playing\n"); + } + break; + } + return 0; +} + +static int dsound_write (SWVoiceOut *sw, void *buf, int len) +{ + return audio_pcm_sw_write (sw, buf, len); +} + +static int dsound_run_out (HWVoiceOut *hw) +{ + int err; + HRESULT hr; + DSoundVoiceOut *ds = (DSoundVoiceOut *) hw; + LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer; + int live, len, hwshift; + DWORD blen1, blen2; + DWORD len1, len2; + DWORD decr; + DWORD wpos, ppos, old_pos; + LPVOID p1, p2; + int bufsize; + + if (!dsb) { + dolog ("Attempt to run empty with playback buffer\n"); + return 0; + } + + hwshift = hw->info.shift; + bufsize = hw->samples << hwshift; + + live = audio_pcm_hw_get_live_out (hw); + + hr = IDirectSoundBuffer_GetCurrentPosition ( + dsb, + &ppos, + ds->first_time ? &wpos : NULL + ); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not get playback buffer position\n"); + return 0; + } + + len = live << hwshift; + + if (ds->first_time) { + if (conf.latency_millis) { + DWORD cur_blat; + + cur_blat = audio_ring_dist (wpos, ppos, bufsize); + ds->first_time = 0; + old_pos = wpos; + old_pos += + millis_to_bytes (&hw->info, conf.latency_millis) - cur_blat; + old_pos %= bufsize; + old_pos &= ~hw->info.align; + } + else { + old_pos = wpos; + } +#ifdef DEBUG_DSOUND + ds->played = 0; + ds->mixed = 0; +#endif + } + else { + if (ds->old_pos == ppos) { +#ifdef DEBUG_DSOUND + dolog ("old_pos == ppos\n"); +#endif + return 0; + } + +#ifdef DEBUG_DSOUND + ds->played += audio_ring_dist (ds->old_pos, ppos, hw->bufsize); +#endif + old_pos = ds->old_pos; + } + + if ((old_pos < ppos) && ((old_pos + len) > ppos)) { + len = ppos - old_pos; + } + else { + if ((old_pos > ppos) && ((old_pos + len) > (ppos + bufsize))) { + len = bufsize - old_pos + ppos; + } + } + + if (audio_bug (AUDIO_FUNC, len < 0 || len > bufsize)) { + dolog ("len=%d bufsize=%d old_pos=%ld ppos=%ld\n", + len, bufsize, old_pos, ppos); + return 0; + } + + len &= ~hw->info.align; + if (!len) { + return 0; + } + +#ifdef DEBUG_DSOUND + ds->old_ppos = ppos; +#endif + err = dsound_lock_out ( + dsb, + &hw->info, + old_pos, + len, + &p1, &p2, + &blen1, &blen2, + 0 + ); + if (err) { + return 0; + } + + len1 = blen1 >> hwshift; + len2 = blen2 >> hwshift; + decr = len1 + len2; + + if (p1 && len1) { + dsound_write_sample (hw, p1, len1); + } + + if (p2 && len2) { + dsound_write_sample (hw, p2, len2); + } + + dsound_unlock_out (dsb, p1, p2, blen1, blen2); + ds->old_pos = (old_pos + (decr << hwshift)) % bufsize; + +#ifdef DEBUG_DSOUND + ds->mixed += decr << hwshift; + + dolog ("played %lu mixed %lu diff %ld sec %f\n", + ds->played, + ds->mixed, + ds->mixed - ds->played, + abs (ds->mixed - ds->played) / (double) hw->info.bytes_per_second); +#endif + return decr; +} + +static int dsound_ctl_in (HWVoiceIn *hw, int cmd, ...) +{ + HRESULT hr; + DWORD status; + DSoundVoiceIn *ds = (DSoundVoiceIn *) hw; + LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer; + + if (!dscb) { + dolog ("Attempt to control capture voice without a buffer\n"); + return -1; + } + + switch (cmd) { + case VOICE_ENABLE: + if (dsound_get_status_in (dscb, &status)) { + return -1; + } + + if (status & DSCBSTATUS_CAPTURING) { + dolog ("warning: Voice is already capturing\n"); + return 0; + } + + /* clear ?? */ + + hr = IDirectSoundCaptureBuffer_Start (dscb, DSCBSTART_LOOPING); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not start capturing\n"); + return -1; + } + break; + + case VOICE_DISABLE: + if (dsound_get_status_in (dscb, &status)) { + return -1; + } + + if (status & DSCBSTATUS_CAPTURING) { + hr = IDirectSoundCaptureBuffer_Stop (dscb); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not stop capturing\n"); + return -1; + } + } + else { + dolog ("warning: Voice is not capturing\n"); + } + break; + } + return 0; +} + +static int dsound_read (SWVoiceIn *sw, void *buf, int len) +{ + return audio_pcm_sw_read (sw, buf, len); +} + +static int dsound_run_in (HWVoiceIn *hw) +{ + int err; + HRESULT hr; + DSoundVoiceIn *ds = (DSoundVoiceIn *) hw; + LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer; + int live, len, dead; + DWORD blen1, blen2; + DWORD len1, len2; + DWORD decr; + DWORD cpos, rpos; + LPVOID p1, p2; + int hwshift; + + if (!dscb) { + dolog ("Attempt to run without capture buffer\n"); + return 0; + } + + hwshift = hw->info.shift; + + live = audio_pcm_hw_get_live_in (hw); + dead = hw->samples - live; + if (!dead) { + return 0; + } + + hr = IDirectSoundCaptureBuffer_GetCurrentPosition ( + dscb, + &cpos, + ds->first_time ? &rpos : NULL + ); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not get capture buffer position\n"); + return 0; + } + + if (ds->first_time) { + ds->first_time = 0; + if (rpos & hw->info.align) { + ldebug ("warning: Misaligned capture read position %ld(%d)\n", + rpos, hw->info.align); + } + hw->wpos = rpos >> hwshift; + } + + if (cpos & hw->info.align) { + ldebug ("warning: Misaligned capture position %ld(%d)\n", + cpos, hw->info.align); + } + cpos >>= hwshift; + + len = audio_ring_dist (cpos, hw->wpos, hw->samples); + if (!len) { + return 0; + } + len = audio_MIN (len, dead); + + err = dsound_lock_in ( + dscb, + &hw->info, + hw->wpos << hwshift, + len << hwshift, + &p1, + &p2, + &blen1, + &blen2, + 0 + ); + if (err) { + return 0; + } + + len1 = blen1 >> hwshift; + len2 = blen2 >> hwshift; + decr = len1 + len2; + + if (p1 && len1) { + hw->conv (hw->conv_buf + hw->wpos, p1, len1, &nominal_volume); + } + + if (p2 && len2) { + hw->conv (hw->conv_buf, p2, len2, &nominal_volume); + } + + dsound_unlock_in (dscb, p1, p2, blen1, blen2); + hw->wpos = (hw->wpos + decr) % hw->samples; + return decr; +} + +static void dsound_audio_fini (void *opaque) +{ + HRESULT hr; + dsound *s = opaque; + + if (!s->dsound) { + return; + } + + hr = IDirectSound_Release (s->dsound); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not release DirectSound\n"); + } + s->dsound = NULL; + + if (!s->dsound_capture) { + return; + } + + hr = IDirectSoundCapture_Release (s->dsound_capture); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not release DirectSoundCapture\n"); + } + s->dsound_capture = NULL; +} + +static void *dsound_audio_init (void) +{ + int err; + HRESULT hr; + dsound *s = &glob_dsound; + + hr = CoInitialize (NULL); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not initialize COM\n"); + return NULL; + } + + hr = CoCreateInstance ( + &CLSID_DirectSound, + NULL, + CLSCTX_ALL, + &IID_IDirectSound, + (void **) &s->dsound + ); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not create DirectSound instance\n"); + return NULL; + } + + hr = IDirectSound_Initialize (s->dsound, NULL); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not initialize DirectSound\n"); + return NULL; + } + + hr = CoCreateInstance ( + &CLSID_DirectSoundCapture, + NULL, + CLSCTX_ALL, + &IID_IDirectSoundCapture, + (void **) &s->dsound_capture + ); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not create DirectSoundCapture instance\n"); + } + else { + hr = IDirectSoundCapture_Initialize (s->dsound_capture, NULL); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not initialize DirectSoundCapture\n"); + + hr = IDirectSoundCapture_Release (s->dsound_capture); + if (FAILED (hr)) { + dsound_logerr (hr, "Could not release DirectSoundCapture\n"); + } + s->dsound_capture = NULL; + } + } + + err = dsound_open (s); + if (err) { + dsound_audio_fini (s); + return NULL; + } + + return s; +} + +static struct audio_option dsound_options[] = { + {"LOCK_RETRIES", AUD_OPT_INT, &conf.lock_retries, + "Number of times to attempt locking the buffer", NULL, 0}, + {"RESTOURE_RETRIES", AUD_OPT_INT, &conf.restore_retries, + "Number of times to attempt restoring the buffer", NULL, 0}, + {"GETSTATUS_RETRIES", AUD_OPT_INT, &conf.getstatus_retries, + "Number of times to attempt getting status of the buffer", NULL, 0}, + {"SET_PRIMARY", AUD_OPT_BOOL, &conf.set_primary, + "Set the parameters of primary buffer", NULL, 0}, + {"LATENCY_MILLIS", AUD_OPT_INT, &conf.latency_millis, + "(undocumented)", NULL, 0}, + {"PRIMARY_FREQ", AUD_OPT_INT, &conf.settings.freq, + "Primary buffer frequency", NULL, 0}, + {"PRIMARY_CHANNELS", AUD_OPT_INT, &conf.settings.nchannels, + "Primary buffer number of channels (1 - mono, 2 - stereo)", NULL, 0}, + {"PRIMARY_FMT", AUD_OPT_FMT, &conf.settings.fmt, + "Primary buffer format", NULL, 0}, + {"BUFSIZE_OUT", AUD_OPT_INT, &conf.bufsize_out, + "(undocumented)", NULL, 0}, + {"BUFSIZE_IN", AUD_OPT_INT, &conf.bufsize_in, + "(undocumented)", NULL, 0}, + {NULL, 0, NULL, NULL, NULL, 0} +}; + +static struct audio_pcm_ops dsound_pcm_ops = { + dsound_init_out, + dsound_fini_out, + dsound_run_out, + dsound_write, + dsound_ctl_out, + + dsound_init_in, + dsound_fini_in, + dsound_run_in, + dsound_read, + dsound_ctl_in +}; + +struct audio_driver dsound_audio_driver = { + INIT_FIELD (name = ) "dsound", + INIT_FIELD (descr = ) + "DirectSound http://wikipedia.org/wiki/DirectSound", + INIT_FIELD (options = ) dsound_options, + INIT_FIELD (init = ) dsound_audio_init, + INIT_FIELD (fini = ) dsound_audio_fini, + INIT_FIELD (pcm_ops = ) &dsound_pcm_ops, + INIT_FIELD (can_be_default = ) 1, + INIT_FIELD (max_voices_out = ) INT_MAX, + INIT_FIELD (max_voices_in = ) 1, + INIT_FIELD (voice_size_out = ) sizeof (DSoundVoiceOut), + INIT_FIELD (voice_size_in = ) sizeof (DSoundVoiceIn) +}; diff -r bd68ce5a3f0c -r b450f21472a0 tools/ioemu/audio/fmodaudio.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/audio/fmodaudio.c Wed Jul 12 19:16:10 2006 +0100 @@ -0,0 +1,683 @@ +/* + * QEMU FMOD 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 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include <fmod.h> +#include <fmod_errors.h> +#include "vl.h" + +#define AUDIO_CAP "fmod" +#include "audio_int.h" + +typedef struct FMODVoiceOut { + HWVoiceOut hw; + unsigned int old_pos; + FSOUND_SAMPLE *fmod_sample; + int channel; +} FMODVoiceOut; + +typedef struct FMODVoiceIn { + HWVoiceIn hw; + FSOUND_SAMPLE *fmod_sample; +} FMODVoiceIn; + +static struct { + const char *drvname; + int nb_samples; + int freq; + int nb_channels; + int bufsize; + int threshold; + int broken_adc; +} conf = { + NULL, + 2048 * 2, + 44100, + 2, + 0, + 0, + 0 +}; + +static void GCC_FMT_ATTR (1, 2) fmod_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", + FMOD_ErrorString (FSOUND_GetError ())); +} + +static void GCC_FMT_ATTR (2, 3) fmod_logerr2 ( + 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", + FMOD_ErrorString (FSOUND_GetError ())); +} + +static int fmod_write (SWVoiceOut *sw, void *buf, int len) +{ + return audio_pcm_sw_write (sw, buf, len); +} + +static void fmod_clear_sample (FMODVoiceOut *fmd) +{ + HWVoiceOut *hw = &fmd->hw; + int status; + void *p1 = 0, *p2 = 0; + unsigned int len1 = 0, len2 = 0; + + status = FSOUND_Sample_Lock ( + fmd->fmod_sample, + 0, + hw->samples << hw->info.shift, + &p1, + &p2, + &len1, + &len2 + ); + + if (!status) { + fmod_logerr ("Failed to lock sample\n"); + return; + } + + if ((len1 & hw->info.align) || (len2 & hw->info.align)) { + dolog ("Lock returned misaligned length %d, %d, alignment %d\n", + len1, len2, hw->info.align + 1); + goto fail; + } + + if ((len1 + len2) - (hw->samples << hw->info.shift)) { + dolog ("Lock returned incomplete length %d, %d\n", + len1 + len2, hw->samples << hw->info.shift); + goto fail; + } + + audio_pcm_info_clear_buf (&hw->info, p1, hw->samples); + + fail: + status = FSOUND_Sample_Unlock (fmd->fmod_sample, p1, p2, len1, len2); + if (!status) { + fmod_logerr ("Failed to unlock sample\n"); + } +} + +static void fmod_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len) +{ + int src_len1 = dst_len; + int src_len2 = 0; + int pos = hw->rpos + dst_len; + st_sample_t *src1 = hw->mix_buf + hw->rpos; + st_sample_t *src2 = NULL; + + if (pos > hw->samples) { + src_len1 = hw->samples - hw->rpos; + src2 = hw->mix_buf; + src_len2 = dst_len - src_len1; + pos = src_len2; + } + + if (src_len1) { + hw->clip (dst, src1, src_len1); + mixeng_clear (src1, src_len1); + } + + if (src_len2) { + dst = advance (dst, src_len1 << hw->info.shift); + hw->clip (dst, src2, src_len2); + mixeng_clear (src2, src_len2); + } + + hw->rpos = pos % hw->samples; +} + +static int fmod_unlock_sample (FSOUND_SAMPLE *sample, void *p1, void *p2, + unsigned int blen1, unsigned int blen2) +{ + int status = FSOUND_Sample_Unlock (sample, p1, p2, blen1, blen2); + if (!status) { + fmod_logerr ("Failed to unlock sample\n"); + return -1; + } + return 0; +} + +static int fmod_lock_sample ( + FSOUND_SAMPLE *sample, + struct audio_pcm_info *info, + int pos, + int len, + void **p1, + void **p2, + unsigned int *blen1, + unsigned int *blen2 + ) +{ + int status; + + status = FSOUND_Sample_Lock ( + sample, + pos << info->shift, + len << info->shift, + p1, + p2, + blen1, + blen2 + ); + + if (!status) { + fmod_logerr ("Failed to lock sample\n"); + return -1; + } + + if ((*blen1 & info->align) || (*blen2 & info->align)) { + dolog ("Lock returned misaligned length %d, %d, alignment %d\n", + *blen1, *blen2, info->align + 1); + + fmod_unlock_sample (sample, *p1, *p2, *blen1, *blen2); + + *p1 = NULL - 1; + *p2 = NULL - 1; + *blen1 = ~0U; + *blen2 = ~0U; + return -1; + } + + if (!*p1 && *blen1) { + dolog ("warning: !p1 && blen1=%d\n", *blen1); + *blen1 = 0; + } + + if (!p2 && *blen2) { + dolog ("warning: !p2 && blen2=%d\n", *blen2); + *blen2 = 0; + } + + return 0; +} _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |