r1948 - in trunk/src/host/qemu-neo1973: . audio darwin-user fpu hw keymaps linux-user linux-user/alpha linux-user/i386 linux-user/mips linux-user/ppc linux-user/ppc64 linux-user/x86_64 openmoko pc-bios slirp target-alpha target-arm target-i386 target-m68k target-mips target-ppc target-sh4 target-sparc tests

andrew at sita.openmoko.org andrew at sita.openmoko.org
Sat May 12 01:47:21 CEST 2007


Author: andrew
Date: 2007-05-12 01:44:50 +0200 (Sat, 12 May 2007)
New Revision: 1948

Added:
   trunk/src/host/qemu-neo1973/arm-semi.c
   trunk/src/host/qemu-neo1973/darwin-user/
   trunk/src/host/qemu-neo1973/darwin-user/commpage.c
   trunk/src/host/qemu-neo1973/darwin-user/ioctls.h
   trunk/src/host/qemu-neo1973/darwin-user/ioctls_types.h
   trunk/src/host/qemu-neo1973/darwin-user/machload.c
   trunk/src/host/qemu-neo1973/darwin-user/main.c
   trunk/src/host/qemu-neo1973/darwin-user/mmap.c
   trunk/src/host/qemu-neo1973/darwin-user/qemu.h
   trunk/src/host/qemu-neo1973/darwin-user/signal.c
   trunk/src/host/qemu-neo1973/darwin-user/syscall.c
   trunk/src/host/qemu-neo1973/darwin-user/syscalls.h
   trunk/src/host/qemu-neo1973/hostregs_helper.h
   trunk/src/host/qemu-neo1973/hw/alpha_palcode.c
   trunk/src/host/qemu-neo1973/hw/ds1225y.c
   trunk/src/host/qemu-neo1973/hw/eepro100.c
   trunk/src/host/qemu-neo1973/hw/eeprom93xx.c
   trunk/src/host/qemu-neo1973/hw/eeprom93xx.h
   trunk/src/host/qemu-neo1973/hw/gt64xxx.c
   trunk/src/host/qemu-neo1973/hw/i2c.c
   trunk/src/host/qemu-neo1973/hw/irq.c
   trunk/src/host/qemu-neo1973/hw/irq.h
   trunk/src/host/qemu-neo1973/hw/mips_int.c
   trunk/src/host/qemu-neo1973/hw/mips_malta.c
   trunk/src/host/qemu-neo1973/hw/mips_pica61.c
   trunk/src/host/qemu-neo1973/hw/pl181.c
   trunk/src/host/qemu-neo1973/hw/ppc405.h
   trunk/src/host/qemu-neo1973/hw/ppc405_boards.c
   trunk/src/host/qemu-neo1973/hw/ppc405_uc.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx.c
   trunk/src/host/qemu-neo1973/hw/smbus.c
   trunk/src/host/qemu-neo1973/hw/smbus.h
   trunk/src/host/qemu-neo1973/hw/smbus_eeprom.c
   trunk/src/host/qemu-neo1973/hw/vmmouse.c
   trunk/src/host/qemu-neo1973/hw/vmware_vga.c
   trunk/src/host/qemu-neo1973/linux-user/alpha/
   trunk/src/host/qemu-neo1973/linux-user/alpha/syscall.h
   trunk/src/host/qemu-neo1973/linux-user/alpha/syscall_nr.h
   trunk/src/host/qemu-neo1973/linux-user/alpha/termbits.h
   trunk/src/host/qemu-neo1973/linux-user/i386/
   trunk/src/host/qemu-neo1973/linux-user/i386/syscall.h
   trunk/src/host/qemu-neo1973/linux-user/i386/syscall_nr.h
   trunk/src/host/qemu-neo1973/linux-user/i386/termbits.h
   trunk/src/host/qemu-neo1973/linux-user/ppc64/
   trunk/src/host/qemu-neo1973/linux-user/ppc64/syscall.h
   trunk/src/host/qemu-neo1973/linux-user/ppc64/syscall_nr.h
   trunk/src/host/qemu-neo1973/linux-user/ppc64/termbits.h
   trunk/src/host/qemu-neo1973/linux-user/x86_64/
   trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall.h
   trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall_nr.h
   trunk/src/host/qemu-neo1973/linux-user/x86_64/termbits.h
   trunk/src/host/qemu-neo1973/pc-bios/openbios-sparc64
   trunk/src/host/qemu-neo1973/target-alpha/
   trunk/src/host/qemu-neo1973/target-alpha/cpu.h
   trunk/src/host/qemu-neo1973/target-alpha/exec.h
   trunk/src/host/qemu-neo1973/target-alpha/helper.c
   trunk/src/host/qemu-neo1973/target-alpha/op.c
   trunk/src/host/qemu-neo1973/target-alpha/op_helper.c
   trunk/src/host/qemu-neo1973/target-alpha/op_helper.h
   trunk/src/host/qemu-neo1973/target-alpha/op_helper_mem.h
   trunk/src/host/qemu-neo1973/target-alpha/op_mem.h
   trunk/src/host/qemu-neo1973/target-alpha/op_template.h
   trunk/src/host/qemu-neo1973/target-alpha/translate.c
   trunk/src/host/qemu-neo1973/target-arm/op_iwmmxt.c
   trunk/src/host/qemu-neo1973/target-mips/TODO
   trunk/src/host/qemu-neo1973/target-mips/translate_init.c
   trunk/src/host/qemu-neo1973/target-ppc/STATUS
   trunk/src/host/qemu-neo1973/target-ppc/mfrom_table.c
   trunk/src/host/qemu-neo1973/target-ppc/mfrom_table_gen.c
   trunk/src/host/qemu-neo1973/target-ppc/op_helper.h
   trunk/src/host/qemu-neo1973/uboot_image.h
   trunk/src/host/qemu-neo1973/x_keymap.c
Removed:
   trunk/src/host/qemu-neo1973/README.distrib
   trunk/src/host/qemu-neo1973/hw/md.c
   trunk/src/host/qemu-neo1973/keymaps/zaurus
   trunk/src/host/qemu-neo1973/linux-2.6.9-qemu-fast.patch
   trunk/src/host/qemu-neo1973/linux-user/arm-semi.c
Modified:
   trunk/src/host/qemu-neo1973/Changelog
   trunk/src/host/qemu-neo1973/LICENSE
   trunk/src/host/qemu-neo1973/Makefile
   trunk/src/host/qemu-neo1973/Makefile.target
   trunk/src/host/qemu-neo1973/VERSION
   trunk/src/host/qemu-neo1973/a.out.h
   trunk/src/host/qemu-neo1973/audio/alsaaudio.c
   trunk/src/host/qemu-neo1973/audio/audio.c
   trunk/src/host/qemu-neo1973/audio/audio.h
   trunk/src/host/qemu-neo1973/audio/audio_template.h
   trunk/src/host/qemu-neo1973/audio/coreaudio.c
   trunk/src/host/qemu-neo1973/audio/mixeng.c
   trunk/src/host/qemu-neo1973/audio/mixeng.h
   trunk/src/host/qemu-neo1973/audio/ossaudio.c
   trunk/src/host/qemu-neo1973/audio/wavaudio.c
   trunk/src/host/qemu-neo1973/audio/wavcapture.c
   trunk/src/host/qemu-neo1973/block-qcow2.c
   trunk/src/host/qemu-neo1973/block-raw.c
   trunk/src/host/qemu-neo1973/block-vmdk.c
   trunk/src/host/qemu-neo1973/block.c
   trunk/src/host/qemu-neo1973/configure
   trunk/src/host/qemu-neo1973/console.c
   trunk/src/host/qemu-neo1973/cpu-all.h
   trunk/src/host/qemu-neo1973/cpu-defs.h
   trunk/src/host/qemu-neo1973/cpu-exec.c
   trunk/src/host/qemu-neo1973/dis-asm.h
   trunk/src/host/qemu-neo1973/disas.c
   trunk/src/host/qemu-neo1973/dyngen-exec.h
   trunk/src/host/qemu-neo1973/dyngen.c
   trunk/src/host/qemu-neo1973/dyngen.h
   trunk/src/host/qemu-neo1973/ecc.h
   trunk/src/host/qemu-neo1973/elf.h
   trunk/src/host/qemu-neo1973/elf_ops.h
   trunk/src/host/qemu-neo1973/exec-all.h
   trunk/src/host/qemu-neo1973/exec.c
   trunk/src/host/qemu-neo1973/fpu/softfloat-native.c
   trunk/src/host/qemu-neo1973/fpu/softfloat-native.h
   trunk/src/host/qemu-neo1973/fpu/softfloat.c
   trunk/src/host/qemu-neo1973/fpu/softfloat.h
   trunk/src/host/qemu-neo1973/gdbstub.c
   trunk/src/host/qemu-neo1973/gdbstub.h
   trunk/src/host/qemu-neo1973/hw/acpi.c
   trunk/src/host/qemu-neo1973/hw/adlib.c
   trunk/src/host/qemu-neo1973/hw/ads7846.c
   trunk/src/host/qemu-neo1973/hw/apb_pci.c
   trunk/src/host/qemu-neo1973/hw/apic.c
   trunk/src/host/qemu-neo1973/hw/arm_boot.c
   trunk/src/host/qemu-neo1973/hw/arm_gic.c
   trunk/src/host/qemu-neo1973/hw/arm_pic.c
   trunk/src/host/qemu-neo1973/hw/arm_pic.h
   trunk/src/host/qemu-neo1973/hw/arm_sysctl.c
   trunk/src/host/qemu-neo1973/hw/arm_timer.c
   trunk/src/host/qemu-neo1973/hw/cirrus_vga.c
   trunk/src/host/qemu-neo1973/hw/cs4231.c
   trunk/src/host/qemu-neo1973/hw/cuda.c
   trunk/src/host/qemu-neo1973/hw/es1370.c
   trunk/src/host/qemu-neo1973/hw/esp.c
   trunk/src/host/qemu-neo1973/hw/fdc.c
   trunk/src/host/qemu-neo1973/hw/grackle_pci.c
   trunk/src/host/qemu-neo1973/hw/heathrow_pic.c
   trunk/src/host/qemu-neo1973/hw/i2c.h
   trunk/src/host/qemu-neo1973/hw/i8254.c
   trunk/src/host/qemu-neo1973/hw/i8259.c
   trunk/src/host/qemu-neo1973/hw/ide.c
   trunk/src/host/qemu-neo1973/hw/integratorcp.c
   trunk/src/host/qemu-neo1973/hw/lsi53c895a.c
   trunk/src/host/qemu-neo1973/hw/m48t59.c
   trunk/src/host/qemu-neo1973/hw/m48t59.h
   trunk/src/host/qemu-neo1973/hw/max111x.c
   trunk/src/host/qemu-neo1973/hw/max7310.c
   trunk/src/host/qemu-neo1973/hw/mc146818rtc.c
   trunk/src/host/qemu-neo1973/hw/mips_r4k.c
   trunk/src/host/qemu-neo1973/hw/mips_timer.c
   trunk/src/host/qemu-neo1973/hw/modem.c
   trunk/src/host/qemu-neo1973/hw/nand.c
   trunk/src/host/qemu-neo1973/hw/ne2000.c
   trunk/src/host/qemu-neo1973/hw/neo1973.c
   trunk/src/host/qemu-neo1973/hw/openpic.c
   trunk/src/host/qemu-neo1973/hw/parallel.c
   trunk/src/host/qemu-neo1973/hw/pc.c
   trunk/src/host/qemu-neo1973/hw/pcf5060x.c
   trunk/src/host/qemu-neo1973/hw/pci.c
   trunk/src/host/qemu-neo1973/hw/pckbd.c
   trunk/src/host/qemu-neo1973/hw/pcnet.c
   trunk/src/host/qemu-neo1973/hw/pcspk.c
   trunk/src/host/qemu-neo1973/hw/pflash_cfi02.c
   trunk/src/host/qemu-neo1973/hw/piix_pci.c
   trunk/src/host/qemu-neo1973/hw/pl011.c
   trunk/src/host/qemu-neo1973/hw/pl050.c
   trunk/src/host/qemu-neo1973/hw/pl080.c
   trunk/src/host/qemu-neo1973/hw/pl110.c
   trunk/src/host/qemu-neo1973/hw/pl190.c
   trunk/src/host/qemu-neo1973/hw/ppc.c
   trunk/src/host/qemu-neo1973/hw/ppc_chrp.c
   trunk/src/host/qemu-neo1973/hw/ppc_prep.c
   trunk/src/host/qemu-neo1973/hw/prep_pci.c
   trunk/src/host/qemu-neo1973/hw/ps2.c
   trunk/src/host/qemu-neo1973/hw/pxa.h
   trunk/src/host/qemu-neo1973/hw/pxa2xx_dma.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx_gpio.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx_lcd.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx_mmci.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx_pcmcia.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx_pic.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx_timer.c
   trunk/src/host/qemu-neo1973/hw/realview.c
   trunk/src/host/qemu-neo1973/hw/rtl8139.c
   trunk/src/host/qemu-neo1973/hw/s3c.h
   trunk/src/host/qemu-neo1973/hw/s3c2410.c
   trunk/src/host/qemu-neo1973/hw/s3c24xx_gpio.c
   trunk/src/host/qemu-neo1973/hw/s3c24xx_lcd.c
   trunk/src/host/qemu-neo1973/hw/s3c24xx_mmci.c
   trunk/src/host/qemu-neo1973/hw/s3c24xx_rtc.c
   trunk/src/host/qemu-neo1973/hw/s3c24xx_udc.c
   trunk/src/host/qemu-neo1973/hw/sb16.c
   trunk/src/host/qemu-neo1973/hw/scsi-disk.c
   trunk/src/host/qemu-neo1973/hw/sd.c
   trunk/src/host/qemu-neo1973/hw/sd.h
   trunk/src/host/qemu-neo1973/hw/serial.c
   trunk/src/host/qemu-neo1973/hw/sh7750.c
   trunk/src/host/qemu-neo1973/hw/shix.c
   trunk/src/host/qemu-neo1973/hw/slavio_intctl.c
   trunk/src/host/qemu-neo1973/hw/slavio_misc.c
   trunk/src/host/qemu-neo1973/hw/slavio_serial.c
   trunk/src/host/qemu-neo1973/hw/slavio_timer.c
   trunk/src/host/qemu-neo1973/hw/smc91c111.c
   trunk/src/host/qemu-neo1973/hw/sparc32_dma.c
   trunk/src/host/qemu-neo1973/hw/spitz.c
   trunk/src/host/qemu-neo1973/hw/sun4m.c
   trunk/src/host/qemu-neo1973/hw/sun4u.c
   trunk/src/host/qemu-neo1973/hw/tcx.c
   trunk/src/host/qemu-neo1973/hw/unin_pci.c
   trunk/src/host/qemu-neo1973/hw/usb-hid.c
   trunk/src/host/qemu-neo1973/hw/usb-msd.c
   trunk/src/host/qemu-neo1973/hw/usb-net.c
   trunk/src/host/qemu-neo1973/hw/usb-ohci.c
   trunk/src/host/qemu-neo1973/hw/usb-uhci.c
   trunk/src/host/qemu-neo1973/hw/usb.h
   trunk/src/host/qemu-neo1973/hw/versatile_pci.c
   trunk/src/host/qemu-neo1973/hw/versatilepb.c
   trunk/src/host/qemu-neo1973/hw/vga.c
   trunk/src/host/qemu-neo1973/hw/vga_int.h
   trunk/src/host/qemu-neo1973/hw/wm8750.c
   trunk/src/host/qemu-neo1973/hw/wm8753.c
   trunk/src/host/qemu-neo1973/keymaps.c
   trunk/src/host/qemu-neo1973/kqemu.c
   trunk/src/host/qemu-neo1973/linux-user/elfload.c
   trunk/src/host/qemu-neo1973/linux-user/flatload.c
   trunk/src/host/qemu-neo1973/linux-user/main.c
   trunk/src/host/qemu-neo1973/linux-user/mips/syscall_nr.h
   trunk/src/host/qemu-neo1973/linux-user/ppc/termbits.h
   trunk/src/host/qemu-neo1973/linux-user/qemu.h
   trunk/src/host/qemu-neo1973/linux-user/signal.c
   trunk/src/host/qemu-neo1973/linux-user/syscall.c
   trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h
   trunk/src/host/qemu-neo1973/loader.c
   trunk/src/host/qemu-neo1973/monitor.c
   trunk/src/host/qemu-neo1973/openmoko/download.sh
   trunk/src/host/qemu-neo1973/openmoko/flash.sh
   trunk/src/host/qemu-neo1973/osdep.c
   trunk/src/host/qemu-neo1973/osdep.h
   trunk/src/host/qemu-neo1973/pc-bios/README
   trunk/src/host/qemu-neo1973/pc-bios/bios.bin
   trunk/src/host/qemu-neo1973/pc-bios/bios.diff
   trunk/src/host/qemu-neo1973/pc-bios/openbios-sparc32
   trunk/src/host/qemu-neo1973/ppc.ld
   trunk/src/host/qemu-neo1973/qemu-binfmt-conf.sh
   trunk/src/host/qemu-neo1973/qemu-doc.texi
   trunk/src/host/qemu-neo1973/qemu-img.c
   trunk/src/host/qemu-neo1973/qemu-tech.texi
   trunk/src/host/qemu-neo1973/sdl.c
   trunk/src/host/qemu-neo1973/slirp/bootp.c
   trunk/src/host/qemu-neo1973/slirp/tftp.c
   trunk/src/host/qemu-neo1973/slirp/tftp.h
   trunk/src/host/qemu-neo1973/slirp/udp.c
   trunk/src/host/qemu-neo1973/softmmu_header.h
   trunk/src/host/qemu-neo1973/sparc.ld
   trunk/src/host/qemu-neo1973/target-arm/cpu.h
   trunk/src/host/qemu-neo1973/target-arm/exec.h
   trunk/src/host/qemu-neo1973/target-arm/helper.c
   trunk/src/host/qemu-neo1973/target-arm/op.c
   trunk/src/host/qemu-neo1973/target-arm/translate.c
   trunk/src/host/qemu-neo1973/target-i386/cpu.h
   trunk/src/host/qemu-neo1973/target-i386/helper.c
   trunk/src/host/qemu-neo1973/target-i386/helper2.c
   trunk/src/host/qemu-neo1973/target-i386/op.c
   trunk/src/host/qemu-neo1973/target-i386/ops_sse.h
   trunk/src/host/qemu-neo1973/target-i386/translate.c
   trunk/src/host/qemu-neo1973/target-m68k/cpu.h
   trunk/src/host/qemu-neo1973/target-m68k/translate.c
   trunk/src/host/qemu-neo1973/target-mips/cpu.h
   trunk/src/host/qemu-neo1973/target-mips/exec.h
   trunk/src/host/qemu-neo1973/target-mips/fop_template.c
   trunk/src/host/qemu-neo1973/target-mips/helper.c
   trunk/src/host/qemu-neo1973/target-mips/mips-defs.h
   trunk/src/host/qemu-neo1973/target-mips/op.c
   trunk/src/host/qemu-neo1973/target-mips/op_helper.c
   trunk/src/host/qemu-neo1973/target-mips/op_helper_mem.c
   trunk/src/host/qemu-neo1973/target-mips/op_mem.c
   trunk/src/host/qemu-neo1973/target-mips/op_template.c
   trunk/src/host/qemu-neo1973/target-mips/translate.c
   trunk/src/host/qemu-neo1973/target-ppc/cpu.h
   trunk/src/host/qemu-neo1973/target-ppc/exec.h
   trunk/src/host/qemu-neo1973/target-ppc/helper.c
   trunk/src/host/qemu-neo1973/target-ppc/op.c
   trunk/src/host/qemu-neo1973/target-ppc/op_helper.c
   trunk/src/host/qemu-neo1973/target-ppc/op_helper_mem.h
   trunk/src/host/qemu-neo1973/target-ppc/op_mem.h
   trunk/src/host/qemu-neo1973/target-ppc/op_template.h
   trunk/src/host/qemu-neo1973/target-ppc/translate.c
   trunk/src/host/qemu-neo1973/target-ppc/translate_init.c
   trunk/src/host/qemu-neo1973/target-sh4/cpu.h
   trunk/src/host/qemu-neo1973/target-sh4/helper.c
   trunk/src/host/qemu-neo1973/target-sh4/op.c
   trunk/src/host/qemu-neo1973/target-sh4/translate.c
   trunk/src/host/qemu-neo1973/target-sparc/cpu.h
   trunk/src/host/qemu-neo1973/target-sparc/exec.h
   trunk/src/host/qemu-neo1973/target-sparc/op.c
   trunk/src/host/qemu-neo1973/target-sparc/op_helper.c
   trunk/src/host/qemu-neo1973/target-sparc/translate.c
   trunk/src/host/qemu-neo1973/tests/Makefile
   trunk/src/host/qemu-neo1973/tests/test-arm-iwmmxt.s
   trunk/src/host/qemu-neo1973/tests/test-i386.c
   trunk/src/host/qemu-neo1973/translate-all.c
   trunk/src/host/qemu-neo1973/vl.c
   trunk/src/host/qemu-neo1973/vl.h
   trunk/src/host/qemu-neo1973/vnc.c
Log:
Merge changes from cvs.savannah.nongnu.org:/sources/qemu.
Merge Paul Brook's I2C/SMBus framework and drop our own I2C fwk.
Rewrite interrupt handling to use the new framework.
Update MMC host to use the new APIs.  Update CPU selection to the new API.
Rewrite GPIO handling to use only the IRQ fwk.
Convert memory mapping to the Fabrice Bellard's new API.  Convert I2C slaves and S3C2410 I2C master to new API.
Correct a ton of bugs spotted during the update.  (a basic test was done but things may still be broken because the update)


Modified: trunk/src/host/qemu-neo1973/Changelog
===================================================================
--- trunk/src/host/qemu-neo1973/Changelog	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/Changelog	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,5 +1,13 @@
-version 0.8.3:
+  - TFTP booting from host directory (Anthony Liguori, Erwan Velu)
+  - Tap device emulation for Solaris (Sittichai Palanisong)
+  - Monitor multiplexing to several I/O channels (Jason Wessel)
+  - ds1225y nvram support (Herve Poussineau)
+  - CPU model selection support (J. Mayer, Paul Brook, Herve Poussineau)
+  - Several Sparc fixes (Aurelien Jarno, Blue Swirl)
+  - MIPS 64-bit FPU support (Thiemo Seufer)
 
+version 0.9.0:
+
   - Support for relative paths in backing files for disk images
   - Async file I/O API
   - New qcow2 disk image format
@@ -7,6 +15,14 @@
   - Linux: specific host CDROM and floppy support
   - SMM support
   - Moved PCI init, MP table init and ACPI table init to Bochs BIOS
+  - Support for MIPS32 Release 2 instruction set (Thiemo Seufer)
+  - MIPS Malta system emulation (Aurelien Jarno, Stefan Weil)
+  - Darwin userspace emulation (Pierre d'Herbemont)
+  - m68k user support (Paul Brook)
+  - several x86 and x86_64 emulation fixes
+  - Mouse relative offset VNC extension (Anthony Liguori)
+  - PXE boot support (Anthony Liguori)
+  - '-daemonize' option (Anthony Liguori)
 
 version 0.8.2:
 
@@ -15,7 +31,7 @@
   - switch to OpenBios for SPARC targets (Blue Swirl)
   - VNC server fixes
   - MIPS FPU support (Marius Groeger)
-  - Solaris/SPARC host support (Ben Taylor)
+  - Solaris/SPARC host support (Juergen Keil)
   - PPC breakpoints and single stepping (Jason Wessel)
   - USB updates (Paul Brook)
   - UDP/TCP/telnet character devices (Jason Wessel)
@@ -34,7 +50,7 @@
   - PC speaker support (Joachim Henke)
   - IDE LBA48 support (Jens Axboe)
   - SSE3 support
-  - Solaris port (Ben Taylor)
+  - Solaris port (Juergen Keil)
   - Preliminary SH4 target (Samuel Tardieu)
   - VNC server (Anthony Liguori)
   - slirp fixes (Ed Swierk et al.)

Modified: trunk/src/host/qemu-neo1973/LICENSE
===================================================================
--- trunk/src/host/qemu-neo1973/LICENSE	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/LICENSE	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,12 +1,15 @@
-The following points clarify the QEMU licenses:
+The following points clarify the QEMU license:
 
-1) The QEMU virtual CPU core library (libqemu.a) and the QEMU PC
-   system emulator are released under the GNU Lesser General Public
-   License.
+1) QEMU as a whole is released under the GNU General Public License
 
-2) The Linux user mode QEMU emulator is released under the GNU General
-   Public License.
+2) Parts of QEMU have specific licenses which are compatible with the
+GNU General Public License. Hence each source file contains its own
+licensing information.
 
+In particular, the QEMU virtual CPU core library (libqemu.a) is
+released under the GNU Lesser General Public License. Many hardware
+device emulation sources are released under the BSD license.
+
 3) QEMU is a trademark of Fabrice Bellard.
 
 Fabrice Bellard.
\ No newline at end of file

Modified: trunk/src/host/qemu-neo1973/Makefile
===================================================================
--- trunk/src/host/qemu-neo1973/Makefile	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/Makefile	2007-05-11 23:44:50 UTC (rev 1948)
@@ -8,10 +8,9 @@
 BASE_CFLAGS=
 BASE_LDFLAGS=
 
-BASE_CFLAGS += $(OS_CFLAGS)
-ifeq ($(ARCH),sparc)
-BASE_CFLAGS += -mcpu=ultrasparc
-endif
+BASE_CFLAGS += $(OS_CFLAGS) $(ARCH_CFLAGS)
+BASE_LDFLAGS += $(OS_LDFLAGS) $(ARCH_LDFLAGS)
+
 CPPFLAGS += -I. -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
 LIBS=
 TOOLS=qemu-img$(EXESUF) raw2flash$(EXESUF) flash2raw$(EXESUF)
@@ -135,7 +134,8 @@
 
 html: qemu-doc.html qemu-tech.html
 
-FILE=qemu-$(shell cat VERSION)
+VERSION ?= $(shell cat VERSION)
+FILE = qemu-$(VERSION)
 
 # tar release (use 'make -k tar' on a checkouted tree)
 tar:
@@ -149,18 +149,24 @@
 	( cd / ; tar zcvf ~/qemu-$(VERSION)-i386.tar.gz \
 	$(bindir)/qemu \
 	$(bindir)/qemu-system-ppc \
+	$(bindir)/qemu-system-ppc64 \
+	$(bindir)/qemu-system-ppcemb \
 	$(bindir)/qemu-system-sparc \
 	$(bindir)/qemu-system-x86_64 \
 	$(bindir)/qemu-system-mips \
 	$(bindir)/qemu-system-mipsel \
+	$(bindir)/qemu-system-mips64 \
+	$(bindir)/qemu-system-mips64el \
 	$(bindir)/qemu-system-arm \
 	$(bindir)/qemu-i386 \
         $(bindir)/qemu-arm \
         $(bindir)/qemu-armeb \
         $(bindir)/qemu-sparc \
         $(bindir)/qemu-ppc \
+        $(bindir)/qemu-ppc64 \
         $(bindir)/qemu-mips \
         $(bindir)/qemu-mipsel \
+        $(bindir)/qemu-alpha \
         $(bindir)/qemu-img \
 	$(datadir)/bios.bin \
 	$(datadir)/vgabios.bin \
@@ -169,6 +175,9 @@
 	$(datadir)/video.x \
 	$(datadir)/openbios-sparc32 \
 	$(datadir)/linux_boot.bin \
+        $(datadir)/pxe-ne2k_pci.bin \
+	$(datadir)/pxe-rtl8139.bin \
+        $(datadir)/pxe-pcnet.bin \
 	$(docdir)/qemu-doc.html \
 	$(docdir)/qemu-tech.html \
 	$(mandir)/man1/qemu.1 $(mandir)/man1/qemu-img.1 )

Modified: trunk/src/host/qemu-neo1973/Makefile.target
===================================================================
--- trunk/src/host/qemu-neo1973/Makefile.target	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/Makefile.target	2007-05-11 23:44:50 UTC (rev 1948)
@@ -4,16 +4,26 @@
 ifeq ($(TARGET_ARCH), x86_64)
 TARGET_BASE_ARCH:=i386
 endif
+ifeq ($(TARGET_ARCH), mips64)
+TARGET_BASE_ARCH:=mips
+endif
 ifeq ($(TARGET_ARCH), ppc64)
 TARGET_BASE_ARCH:=ppc
 endif
+ifeq ($(TARGET_ARCH), ppcemb)
+TARGET_BASE_ARCH:=ppc
+endif
 ifeq ($(TARGET_ARCH), sparc64)
 TARGET_BASE_ARCH:=sparc
 endif
 TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)
 VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio
 CPPFLAGS=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH)
-ifdef CONFIG_USER_ONLY
+ifdef CONFIG_DARWIN_USER
+VPATH+=:$(SRC_PATH)/darwin-user
+CPPFLAGS+=-I$(SRC_PATH)/darwin-user -I$(SRC_PATH)/darwin-user/$(TARGET_ARCH)
+endif
+ifdef CONFIG_LINUX_USER
 VPATH+=:$(SRC_PATH)/linux-user
 CPPFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH)
 endif
@@ -40,6 +50,11 @@
     TARGET_ARCH2=mipsel
   endif
 endif
+ifeq ($(TARGET_ARCH),mips64)
+  ifneq ($(TARGET_WORDS_BIGENDIAN),yes)
+    TARGET_ARCH2=mips64el
+  endif
+endif
 QEMU_USER=qemu-$(TARGET_ARCH2)
 # system emulator name
 ifdef CONFIG_SOFTMMU
@@ -61,17 +76,31 @@
 endif
 endif # !CONFIG_USER_ONLY
 
+ifdef CONFIG_STATIC
+BASE_LDFLAGS+=-static
+endif
+
 # We require -O2 to avoid the stack setup prologue in EXIT_TB
-OP_CFLAGS = -Wall -O2 -g -fno-strict-aliasing
+OP_CFLAGS := -Wall -O2 -g -fno-strict-aliasing
 
+# cc-option
+# Usage: OP_CFLAGS+=$(call cc-option, -falign-functions=0, -malign-functions=0)
+
+cc-option = $(shell if $(CC) $(OP_CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
+              > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
+
+OP_CFLAGS+=$(call cc-option, -fno-reorder-blocks, "")
+OP_CFLAGS+=$(call cc-option, -fno-gcse, "")
+OP_CFLAGS+=$(call cc-option, -fno-tree-ch, "")
+OP_CFLAGS+=$(call cc-option, -fno-optimize-sibling-calls, "")
+OP_CFLAGS+=$(call cc-option, -fno-crossjumping, "")
+OP_CFLAGS+=$(call cc-option, -fno-align-labels, "")
+OP_CFLAGS+=$(call cc-option, -fno-align-jumps, "")
+OP_CFLAGS+=$(call cc-option, -fno-align-functions, $(call cc-option, -malign-functions=0, ""))
+
 ifeq ($(ARCH),i386)
 HELPER_CFLAGS+=-fomit-frame-pointer
 OP_CFLAGS+=-mpreferred-stack-boundary=2 -fomit-frame-pointer
-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
@@ -81,47 +110,50 @@
 ifdef USE_I386_LD
 BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
 else
+ifdef CONFIG_LINUX_USER
 # 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!
 BASE_LDFLAGS+=-Wl,-shared
 endif
 endif
+endif
 
 ifeq ($(ARCH),x86_64)
-HELPER_CFLAGS+=-fomit-frame-pointer
 BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
 endif
 
 ifeq ($(ARCH),ppc)
 CPPFLAGS+= -D__powerpc__
+ifdef CONFIG_LINUX_USER
 BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
 endif
+endif
 
 ifeq ($(ARCH),s390)
 BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
 endif
 
 ifeq ($(ARCH),sparc)
-ifeq ($(CONFIG_SOLARIS),yes)
-BASE_CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g2 -ffixed-g3
-BASE_LDFLAGS+=-m32
-OP_CFLAGS+=-fno-delayed-branch -fno-omit-frame-pointer -ffixed-i0
-else
-BASE_CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
-BASE_LDFLAGS+=-m32
-OP_CFLAGS+=-fno-delayed-branch -ffixed-i0
-HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat
-# -static is used to avoid g1/g3 usage by the dynamic linker
-BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld -static
+  BASE_CFLAGS+=-ffixed-g2 -ffixed-g3
+  OP_CFLAGS+=-fno-delayed-branch -ffixed-i0
+  ifeq ($(CONFIG_SOLARIS),yes)
+    OP_CFLAGS+=-fno-omit-frame-pointer
+  else
+    BASE_CFLAGS+=-ffixed-g1 -ffixed-g6
+    HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat
+    # -static is used to avoid g1/g3 usage by the dynamic linker
+    BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld -static
+  endif
 endif
-endif
 
 ifeq ($(ARCH),sparc64)
-BASE_CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7
-BASE_LDFLAGS+=-m64
-BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
-OP_CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7 -fno-delayed-branch -ffixed-i0
+  BASE_CFLAGS+=-ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7
+  OP_CFLAGS+=-mcpu=ultrasparc -m64 -fno-delayed-branch -ffixed-i0
+  ifneq ($(CONFIG_SOLARIS),yes)
+    BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
+    OP_CFLAGS+=-ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7
+  endif
 endif
 
 ifeq ($(ARCH),alpha)
@@ -149,20 +181,37 @@
 endif
 
 ifeq ($(ARCH),mips)
+OP_CFLAGS+=-mabi=32 -G0 -fno-PIC -mno-abicalls -fomit-frame-pointer -fno-delayed-branch -Wa,-O0
+ifeq ($(WORDS_BIGENDIAN),yes)
 BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
+else
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH)el.ld
 endif
+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
+ifeq ($(ARCH),mips64)
+OP_CFLAGS+=-mabi=n32 -G0 -fno-PIC -mno-abicalls -fomit-frame-pointer -fno-delayed-branch -Wa,-O0
+ifeq ($(WORDS_BIGENDIAN),yes)
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
+else
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH)el.ld
 endif
+endif
 
 ifeq ($(CONFIG_DARWIN),yes)
 LIBS+=-lmx
 endif
 
-OP_CFLAGS+=$(OS_CFLAGS)
+ifdef CONFIG_DARWIN_USER
+# Leave some space for the regular program loading zone
+BASE_LDFLAGS+=-Wl,-segaddr,__STD_PROG_ZONE,0x1000 -image_base 0x0e000000
+endif
 
+BASE_CFLAGS+=$(OS_CFLAGS) $(ARCH_CFLAGS)
+BASE_LDFLAGS+=$(OS_LDFLAGS) $(ARCH_LDFLAGS)
+OP_CFLAGS+=$(OS_CFLAGS) $(ARCH_CFLAGS)
+OP_LDFLAGS+=$(OS_LDFLAGS) $(ARCH_LDFLAGS)
+
 #########################################################
 
 CPPFLAGS+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
@@ -175,7 +224,13 @@
 endif
 ifdef CONFIG_SOLARIS
 LIBS+=-lsocket -lnsl -lresolv
+ifdef NEEDS_LIBSUNMATH
+LIBS+=-lsunmath
+LDFLAGS+=-L/opt/SUNWspro/prod/lib -R/opt/SUNWspro/prod/lib
+OP_CFLAGS+=-I/opt/SUNWspro/prod/include/cc
+BASE_CFLAGS+=-I/opt/SUNWspro/prod/include/cc
 endif
+endif
 
 # profiling code
 ifdef TARGET_GPROF
@@ -183,8 +238,10 @@
 main.o: BASE_CFLAGS+=-p
 endif
 
+ifdef CONFIG_LINUX_USER
 OBJS= main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o \
       elfload.o linuxload.o
+LIBS+= $(AIOLIBS)
 ifdef TARGET_HAS_BFLT
 OBJS+= flatload.o
 endif
@@ -200,6 +257,12 @@
 ifeq ($(TARGET_ARCH), m68k)
 OBJS+= m68k-sim.o m68k-semi.o
 endif
+endif #CONFIG_LINUX_USER
+
+ifdef CONFIG_DARWIN_USER
+OBJS= main.o commpage.o machload.o mmap.o osdep.o signal.o syscall.o thunk.o
+endif
+
 SRCS:= $(OBJS:.o=.c)
 OBJS+= libqemu.a
 
@@ -228,7 +291,7 @@
 LIBOBJS+= op_helper.o helper.o
 endif
 
-ifeq ($(TARGET_ARCH), mips)
+ifeq ($(TARGET_BASE_ARCH), mips)
 LIBOBJS+= op_helper.o helper.o
 endif
 
@@ -248,6 +311,10 @@
 LIBOBJS+= helper.o
 endif
 
+ifeq ($(TARGET_BASE_ARCH), alpha)
+LIBOBJS+= op_helper.o helper.o alpha_palcode.o
+endif
+
 # NOTE: the disassembler code is only needed for debugging
 LIBOBJS+=disas.o 
 ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
@@ -265,7 +332,7 @@
 ifeq ($(findstring ppc, $(TARGET_BASE_ARCH) $(ARCH)),ppc)
 LIBOBJS+=ppc-dis.o
 endif
-ifeq ($(findstring mips, $(TARGET_ARCH) $(ARCH)),mips)
+ifeq ($(findstring mips, $(TARGET_BASE_ARCH) $(ARCH)),mips)
 LIBOBJS+=mips-dis.o
 endif
 ifeq ($(findstring sparc, $(TARGET_BASE_ARCH) $(ARCH)),sparc)
@@ -300,6 +367,7 @@
 VL_OBJS+=cutils.o
 VL_OBJS+=block.o block-raw.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 block-qcow2.o
+VL_OBJS+=irq.o
 ifdef CONFIG_WIN32
 VL_OBJS+=tap-win32.o
 endif
@@ -333,6 +401,8 @@
 endif
 AUDIODRV+= wavcapture.o
 
+VL_OBJS += i2c.o smbus.o
+
 # SCSI layer
 VL_OBJS+= scsi-disk.o cdrom.o lsi53c895a.o
 
@@ -340,27 +410,36 @@
 VL_OBJS+= usb.o usb-hub.o usb-linux.o usb-hid.o usb-ohci.o usb-msd.o usb-net.o
 VL_OBJS+= usb-linux-gadget.o
 
+# EEPROM emulation
+VL_OBJS += eeprom93xx.o
+
 # PCI network cards
-VL_OBJS+= ne2000.o rtl8139.o pcnet.o
+VL_OBJS += eepro100.o
+VL_OBJS += ne2000.o
+VL_OBJS += pcnet.o
+VL_OBJS += 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 i8259.o i8254.o pcspk.o pc.o
 VL_OBJS+= cirrus_vga.o apic.o parallel.o acpi.o piix_pci.o
-VL_OBJS+= usb-uhci.o
+VL_OBJS+= usb-uhci.o smbus_eeprom.o vmmouse.o vmware_vga.o
 CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
 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+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o pflash_cfi02.o
 VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o
-VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o
+VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o ppc405_uc.o ppc405_boards.o
 CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
 endif
-ifeq ($(TARGET_ARCH), mips)
-VL_OBJS+= mips_r4k.o mips_timer.o dma.o vga.o serial.o i8254.o i8259.o ide.o
-VL_OBJS+= mc146818rtc.o #pckbd.o fdc.o m48t59.o
+ifeq ($(TARGET_BASE_ARCH), mips)
+VL_OBJS+= mips_r4k.o mips_malta.o mips_pica61.o
+VL_OBJS+= mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o
+VL_OBJS+= ide.o gt64xxx.o pckbd.o ps2.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o
+VL_OBJS+= piix_pci.o parallel.o mixeng.o cirrus_vga.o $(SOUND_HW) $(AUDIODRV)
+CPPFLAGS += -DHAS_AUDIO
 endif
 ifeq ($(TARGET_BASE_ARCH), sparc)
 ifeq ($(TARGET_ARCH), sparc64)
@@ -375,12 +454,13 @@
 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
-VL_OBJS+= versatile_pci.o
+VL_OBJS+= arm_boot.o pl011.o pl050.o pl080.o pl110.o pl181.o pl190.o
+VL_OBJS+= versatile_pci.o sd.o
 VL_OBJS+= arm_gic.o realview.o arm_sysctl.o
-VL_OBJS+= pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o spitz.o
+VL_OBJS+= arm-semi.o
+VL_OBJS+= pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
 VL_OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o max111x.o max7310.o
-VL_OBJS+= ads7846.o sd.o ide.o serial.o nand.o $(AUDIODRV) wm8750.o wm8753.o
+VL_OBJS+= spitz.o ads7846.o ide.o serial.o nand.o $(AUDIODRV) wm8750.o wm8753.o
 VL_OBJS+= s3c2410.o s3c24xx_gpio.o s3c24xx_lcd.o s3c24xx_mmci.o s3c24xx_rtc.o
 VL_OBJS+= s3c24xx_udc.o neo1973.o pcf5060x.o jbt6k74.o modem.o
 CPPFLAGS += -DHAS_AUDIO
@@ -392,7 +472,7 @@
 VL_OBJS+=gdbstub.o 
 endif
 ifdef CONFIG_SDL
-VL_OBJS+=sdl.o
+VL_OBJS+=sdl.o x_keymap.o
 endif
 VL_OBJS+=vnc.o
 ifdef CONFIG_COCOA
@@ -436,8 +516,10 @@
 endif
 
 ifeq ($(ARCH),sparc64)
-VL_LDFLAGS+=-m64
-VL_LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc64.ld
+  VL_LDFLAGS+=-m64
+  ifneq ($(CONFIG_SOLARIS),yes)
+    VL_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
+  endif
 endif
 
 ifdef CONFIG_WIN32
@@ -445,7 +527,7 @@
 endif
 
 $(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
-	$(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
+	$(CC) $(VL_LDFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
 
 cocoa.o: cocoa.m
 	$(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
@@ -528,9 +610,11 @@
 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
+ifeq ($(TARGET_BASE_ARCH), mips)
+helper.o: cpu.h exec-all.h
+op.o: op_template.c fop_template.c op_mem.c exec.h
+op_helper.o: op_helper_mem.c exec.h softmmu_template.h
+translate.o: translate_init.c exec-all.h disas.h
 endif
 
 loader.o: loader.c elf_ops.h
@@ -545,6 +629,11 @@
 tc58128.o: tc58128.c
 endif
 
+ifeq ($(TARGET_BASE_ARCH), alpha)
+op.o: op.c op_template.h op_mem.h
+op_helper.o: op_helper_mem.h
+endif
+
 $(OBJS) $(LIBOBJS) $(VL_OBJS): config.h ../config-host.h
 
 %.o: %.c

Deleted: trunk/src/host/qemu-neo1973/README.distrib
===================================================================
--- trunk/src/host/qemu-neo1973/README.distrib	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/README.distrib	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,16 +0,0 @@
-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

Modified: trunk/src/host/qemu-neo1973/VERSION
===================================================================
--- trunk/src/host/qemu-neo1973/VERSION	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/VERSION	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1 +1 @@
-0.8.2
\ No newline at end of file
+0.9.0
\ No newline at end of file

Modified: trunk/src/host/qemu-neo1973/a.out.h
===================================================================
--- trunk/src/host/qemu-neo1973/a.out.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/a.out.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -25,9 +25,9 @@
 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	*/
+  host_ulong f_timdat;	/* time & date stamp		*/
+  host_ulong f_symptr;	/* file pointer to symtab	*/
+  host_ulong f_nsyms;	/* number of symtab entries	*/
   short f_opthdr;	/* sizeof(optional hdr)		*/
   short f_flags;	/* flags			*/
 };
@@ -72,12 +72,12 @@
 {
   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=
+  host_ulong	tsize;		/* text size in bytes, padded to FW bdry*/
+  host_ulong	dsize;		/* initialized data "  "		*/
+  host_ulong	bsize;		/* uninitialized data "   "		*/
+  host_ulong	entry;		/* entry pt.				*/
+  host_ulong text_start;	/* base of text used for this file */
+  host_ulong data_start;	/* base of data used for this file=
  */
 }
 AOUTHDR;
@@ -103,16 +103,16 @@
 
 struct external_scnhdr {
   char		s_name[8];	/* section name			*/
-  unsigned long	s_paddr;	/* physical address, offset
+  host_ulong	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	*/
+  host_ulong	s_vaddr;	/* virtual address		*/
+  host_ulong	s_size;		/* section size			*/
+  host_ulong	s_scnptr;	/* file ptr to raw data for section */
+  host_ulong	s_relptr;	/* file ptr to relocation	*/
+  host_ulong	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			*/
+  host_ulong	s_flags;	/* flags			*/
 };
 
 #define	SCNHDR	struct external_scnhdr
@@ -136,8 +136,8 @@
  */
 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	*/
+    host_ulong l_symndx; /* function name symbol index, iff l_lnno 0 */
+    host_ulong l_paddr;	/* (physical) address of line number	*/
   } l_addr;
   unsigned short l_lnno;	/* line number		*/
 };
@@ -156,11 +156,11 @@
   union {
     char e_name[E_SYMNMLEN];
     struct {
-      unsigned long e_zeroes;
-      unsigned long e_offset;
+      host_ulong e_zeroes;
+      host_ulong e_offset;
     } e;
   } e;
-  unsigned long e_value;
+  host_ulong e_value;
   unsigned short e_scnum;
   unsigned short e_type;
   char e_sclass[1];
@@ -174,18 +174,18 @@
 
 union external_auxent {
   struct {
-    unsigned long x_tagndx;	/* str, un, or enum tag indx */
+    host_ulong 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 */
+      host_ulong 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 */
+	host_ulong x_lnnoptr;/* ptr to fcn line # */
+	host_ulong x_endndx;	/* entry ndx past block end */
       } x_fcn;
       struct {			/* if ISARY, up to 4 dimen. */
 	char x_dimen[E_DIMNUM][2];
@@ -197,22 +197,22 @@
   union {
     char x_fname[E_FILNMLEN];
     struct {
-      unsigned long x_zeroes;
-      unsigned long x_offset;
+      host_ulong x_zeroes;
+      host_ulong x_offset;
     } x_n;
   } x_file;
 
   struct {
-    unsigned long x_scnlen;	/* section length */
+    host_ulong x_scnlen;	/* section length */
     unsigned short x_nreloc;	/* # relocation entries */
     unsigned short x_nlinno;	/* # line numbers */
-    unsigned long x_checksum;	/* section COMDAT checksum */
+    host_ulong 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 */
+    host_ulong 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)) */
@@ -344,7 +344,7 @@
   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 */
+  host_ulong 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 */
 
@@ -352,9 +352,9 @@
 
   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	*/
+  host_ulong f_timdat;	/* time & date stamp		*/
+  host_ulong f_symptr;	/* file pointer to symtab	*/
+  host_ulong f_nsyms;	/* number of symtab entries	*/
   unsigned short f_opthdr;	/* sizeof(optional hdr)		*/
   unsigned short f_flags;	/* flags			*/
 };
@@ -370,17 +370,17 @@
 {
   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 */
+  host_ulong	tsize;		/* text size in bytes, padded to FW bdry*/
+  host_ulong	dsize;		/* initialized data "  "		*/
+  host_ulong	bsize;		/* uninitialized data "   "		*/
+  host_ulong	entry;		/* entry pt.				*/
+  host_ulong text_start;	/* base of text used for this file */
+  host_ulong 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;
+  host_ulong  ImageBase;
+  host_ulong  SectionAlignment;
+  host_ulong  FileAlignment;
   unsigned short  MajorOperatingSystemVersion;
   unsigned short  MinorOperatingSystemVersion;
   unsigned short  MajorImageVersion;
@@ -388,17 +388,17 @@
   unsigned short  MajorSubsystemVersion;
   unsigned short  MinorSubsystemVersion;
   char  Reserved1[4];
-  unsigned long  SizeOfImage;
-  unsigned long  SizeOfHeaders;
-  unsigned long  CheckSum;
+  host_ulong  SizeOfImage;
+  host_ulong  SizeOfHeaders;
+  host_ulong  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;
+  host_ulong  SizeOfStackReserve;
+  host_ulong  SizeOfStackCommit;
+  host_ulong  SizeOfHeapReserve;
+  host_ulong  SizeOfHeapCommit;
+  host_ulong  LoaderFlags;
+  host_ulong  NumberOfRvaAndSizes;
   /* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; */
   char  DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars */
 

Added: trunk/src/host/qemu-neo1973/arm-semi.c
===================================================================
--- trunk/src/host/qemu-neo1973/arm-semi.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/arm-semi.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,458 @@
+/*
+ *  Arm "Angel" semihosting syscalls
+ * 
+ *  Copyright (c) 2005, 2007 CodeSourcery.
+ *  Written by Paul Brook.
+ *
+ *  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.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "cpu.h"
+#ifdef CONFIG_USER_ONLY
+#include "qemu.h"
+
+#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
+#else
+#include "vl.h"
+#endif
+
+#define SYS_OPEN        0x01
+#define SYS_CLOSE       0x02
+#define SYS_WRITEC      0x03
+#define SYS_WRITE0      0x04
+#define SYS_WRITE       0x05
+#define SYS_READ        0x06
+#define SYS_READC       0x07
+#define SYS_ISTTY       0x09
+#define SYS_SEEK        0x0a
+#define SYS_FLEN        0x0c
+#define SYS_TMPNAM      0x0d
+#define SYS_REMOVE      0x0e
+#define SYS_RENAME      0x0f
+#define SYS_CLOCK       0x10
+#define SYS_TIME        0x11
+#define SYS_SYSTEM      0x12
+#define SYS_ERRNO       0x13
+#define SYS_GET_CMDLINE 0x15
+#define SYS_HEAPINFO    0x16
+#define SYS_EXIT        0x18
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#define GDB_O_RDONLY  0x000
+#define GDB_O_WRONLY  0x001
+#define GDB_O_RDWR    0x002
+#define GDB_O_APPEND  0x008
+#define GDB_O_CREAT   0x200
+#define GDB_O_TRUNC   0x400
+#define GDB_O_BINARY  0
+
+static int gdb_open_modeflags[12] = {
+    GDB_O_RDONLY,
+    GDB_O_RDONLY | GDB_O_BINARY,
+    GDB_O_RDWR,
+    GDB_O_RDWR | GDB_O_BINARY,
+    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC,
+    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
+    GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC,
+    GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
+    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND,
+    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY,
+    GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND,
+    GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY
+};
+
+static int open_modeflags[12] = {
+    O_RDONLY,
+    O_RDONLY | O_BINARY,
+    O_RDWR,
+    O_RDWR | O_BINARY,
+    O_WRONLY | O_CREAT | O_TRUNC,
+    O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
+    O_RDWR | O_CREAT | O_TRUNC,
+    O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
+    O_WRONLY | O_CREAT | O_APPEND,
+    O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
+    O_RDWR | O_CREAT | O_APPEND,
+    O_RDWR | O_CREAT | O_APPEND | O_BINARY
+};
+
+#ifdef CONFIG_USER_ONLY
+static inline uint32_t set_swi_errno(TaskState *ts, uint32_t code)
+{
+    if (code == (uint32_t)-1)
+        ts->swi_errno = errno;
+    return code;
+}
+#else
+static inline uint32_t set_swi_errno(CPUState *env, uint32_t code)
+{
+    return code;
+}
+
+static uint32_t softmmu_tget32(CPUState *env, uint32_t addr)
+{
+    uint32_t val;
+
+    cpu_memory_rw_debug(env, addr, (uint8_t *)&val, 4, 0);
+    return tswap32(val);
+}
+static uint32_t softmmu_tget8(CPUState *env, uint32_t addr)
+{
+    uint8_t val;
+
+    cpu_memory_rw_debug(env, addr, &val, 1, 0);
+    return val;
+}
+#define tget32(p) softmmu_tget32(env, p)
+#define tget8(p) softmmu_tget8(env, p)
+
+static void *softmmu_lock_user(CPUState *env, uint32_t addr, uint32_t len,
+                               int copy)
+{
+    char *p;
+    /* TODO: Make this something that isn't fixed size.  */
+    p = malloc(len);
+    if (copy)
+        cpu_memory_rw_debug(env, addr, p, len, 0);
+    return p;
+}
+#define lock_user(p, len, copy) softmmu_lock_user(env, p, len, copy)
+static char *softmmu_lock_user_string(CPUState *env, uint32_t addr)
+{
+    char *p;
+    char *s;
+    uint8_t c;
+    /* TODO: Make this something that isn't fixed size.  */
+    s = p = malloc(1024);
+    do {
+        cpu_memory_rw_debug(env, addr, &c, 1, 0);
+        addr++;
+        *(p++) = c;
+    } while (c);
+    return s;
+}
+#define lock_user_string(p) softmmu_lock_user_string(env, p)
+static void softmmu_unlock_user(CPUState *env, void *p, target_ulong addr,
+                                target_ulong len)
+{
+    if (len)
+        cpu_memory_rw_debug(env, addr, p, len, 1);
+    free(p);
+}
+#define unlock_user(s, args, len) softmmu_unlock_user(env, s, args, len)
+#endif
+
+static target_ulong arm_semi_syscall_len;
+
+static void arm_semi_cb(CPUState *env, target_ulong ret, target_ulong err)
+{
+#ifdef CONFIG_USER_ONLY
+    TaskState *ts = env->opaque;
+#endif
+    if (ret == (target_ulong)-1) {
+#ifdef CONFIG_USER_ONLY
+        ts->swi_errno = err;
+#endif
+        env->regs[0] = ret;
+    } else {
+        /* Fixup syscalls that use nonstardard return conventions.  */
+        switch (env->regs[0]) {
+        case SYS_WRITE:
+        case SYS_READ:
+            env->regs[0] = arm_semi_syscall_len - ret;
+            break;
+        case SYS_SEEK:
+            env->regs[0] = 0;
+            break;
+        default:
+            env->regs[0] = ret;
+            break;
+        }
+    }
+}
+
+#define ARG(n) tget32(args + (n) * 4)
+#define SET_ARG(n, val) tput32(args + (n) * 4,val)
+uint32_t do_arm_semihosting(CPUState *env)
+{
+    target_ulong args;
+    char * s;
+    int nr;
+    uint32_t ret;
+    uint32_t len;
+#ifdef CONFIG_USER_ONLY
+    TaskState *ts = env->opaque;
+#else
+    CPUState *ts = env;
+#endif
+
+    nr = env->regs[0];
+    args = env->regs[1];
+    switch (nr) {
+    case SYS_OPEN:
+        s = lock_user_string(ARG(0));
+        if (ARG(1) >= 12)
+          return (uint32_t)-1;
+        if (strcmp(s, ":tt") == 0) {
+            if (ARG(1) < 4)
+                return STDIN_FILENO;
+            else
+                return STDOUT_FILENO;
+        }
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0), (int)ARG(2),
+                           gdb_open_modeflags[ARG(1)]);
+            return env->regs[0];
+        } else {
+            ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644));
+        }
+        unlock_user(s, ARG(0), 0);
+        return ret;
+    case SYS_CLOSE:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "close,%x", ARG(0));
+            return env->regs[0];
+        } else {
+            return set_swi_errno(ts, close(ARG(0)));
+        }
+    case SYS_WRITEC:
+        {
+          char c = tget8(args);
+          /* Write to debug console.  stderr is near enough.  */
+          if (use_gdb_syscalls()) {
+                gdb_do_syscall(arm_semi_cb, "write,2,%x,1", args);
+                return env->regs[0];
+          } else {
+                return write(STDERR_FILENO, &c, 1);
+          }
+        }
+    case SYS_WRITE0:
+        s = lock_user_string(args);
+        len = strlen(s);
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "write,2,%x,%x\n", args, len);
+            ret = env->regs[0];
+        } else {
+            ret = write(STDERR_FILENO, s, len);
+        }
+        unlock_user(s, args, 0);
+        return ret;
+    case SYS_WRITE:
+        len = ARG(2);
+        if (use_gdb_syscalls()) {
+            arm_semi_syscall_len = len;
+            gdb_do_syscall(arm_semi_cb, "write,%x,%x,%x", ARG(0), ARG(1), len);
+            return env->regs[0];
+        } else {
+            s = lock_user(ARG(1), len, 1);
+            ret = set_swi_errno(ts, write(ARG(0), s, len));
+            unlock_user(s, ARG(1), 0);
+            if (ret == (uint32_t)-1)
+                return -1;
+            return len - ret;
+        }
+    case SYS_READ:
+        len = ARG(2);
+        if (use_gdb_syscalls()) {
+            arm_semi_syscall_len = len;
+            gdb_do_syscall(arm_semi_cb, "read,%x,%x,%x", ARG(0), ARG(1), len);
+            return env->regs[0];
+        } else {
+            s = lock_user(ARG(1), len, 0);
+            do
+              ret = set_swi_errno(ts, read(ARG(0), s, len));
+            while (ret == -1 && errno == EINTR);
+            unlock_user(s, ARG(1), len);
+            if (ret == (uint32_t)-1)
+                return -1;
+            return len - ret;
+        }
+    case SYS_READC:
+       /* XXX: Read from debug cosole. Not implemented.  */
+        return 0;
+    case SYS_ISTTY:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "isatty,%x", ARG(0));
+            return env->regs[0];
+        } else {
+            return isatty(ARG(0));
+        }
+    case SYS_SEEK:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "fseek,%x,%x,0", ARG(0), ARG(1));
+            return env->regs[0];
+        } else {
+            ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET));
+            if (ret == (uint32_t)-1)
+              return -1;
+            return 0;
+        }
+    case SYS_FLEN:
+        if (use_gdb_syscalls()) {
+            /* TODO: Use stat syscall.  */
+            return -1;
+        } else {
+            struct stat buf;
+            ret = set_swi_errno(ts, fstat(ARG(0), &buf));
+            if (ret == (uint32_t)-1)
+                return -1;
+            return buf.st_size;
+        }
+    case SYS_TMPNAM:
+        /* XXX: Not implemented.  */
+        return -1;
+    case SYS_REMOVE:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1));
+            ret = env->regs[0];
+        } else {
+            s = lock_user_string(ARG(0));
+            ret =  set_swi_errno(ts, remove(s));
+            unlock_user(s, ARG(0), 0);
+        }
+        return ret;
+    case SYS_RENAME:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "rename,%s,%s",
+                           ARG(0), (int)ARG(1), ARG(2), (int)ARG(3));
+            return env->regs[0];
+        } else {
+            char *s2;
+            s = lock_user_string(ARG(0));
+            s2 = lock_user_string(ARG(2));
+            ret = set_swi_errno(ts, rename(s, s2));
+            unlock_user(s2, ARG(2), 0);
+            unlock_user(s, ARG(0), 0);
+            return ret;
+        }
+    case SYS_CLOCK:
+        return clock() / (CLOCKS_PER_SEC / 100);
+    case SYS_TIME:
+        return set_swi_errno(ts, time(NULL));
+    case SYS_SYSTEM:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1));
+            return env->regs[0];
+        } else {
+            s = lock_user_string(ARG(0));
+            ret = set_swi_errno(ts, system(s));
+            unlock_user(s, ARG(0), 0);
+        }
+    case SYS_ERRNO:
+#ifdef CONFIG_USER_ONLY
+        return ts->swi_errno;
+#else
+        return 0;
+#endif
+    case SYS_GET_CMDLINE:
+#ifdef CONFIG_USER_ONLY
+        /* Build a commandline from the original argv.  */
+        {
+            char **arg = ts->info->host_argv;
+            int len = ARG(1);
+            /* lock the buffer on the ARM side */
+            char *cmdline_buffer = (char*)lock_user(ARG(0), len, 0);
+
+            s = cmdline_buffer;
+            while (*arg && len > 2) {
+                int n = strlen(*arg);
+
+                if (s != cmdline_buffer) {
+                    *(s++) = ' ';
+                    len--;
+                }
+                if (n >= len)
+                    n = len - 1;
+                memcpy(s, *arg, n);
+                s += n;
+                len -= n;
+                arg++;
+            }
+            /* Null terminate the string.  */
+            *s = 0;
+            len = s - cmdline_buffer;
+
+            /* Unlock the buffer on the ARM side.  */
+            unlock_user(cmdline_buffer, ARG(0), len);
+
+            /* Adjust the commandline length argument.  */
+            SET_ARG(1, len);
+
+            /* Return success if commandline fit into buffer.  */
+            return *arg ? -1 : 0;
+        }
+#else
+      return -1;
+#endif
+    case SYS_HEAPINFO:
+        {
+            uint32_t *ptr;
+            uint32_t limit;
+
+#ifdef CONFIG_USER_ONLY
+            /* Some C libraries assume the heap immediately follows .bss, so
+               allocate it using sbrk.  */
+            if (!ts->heap_limit) {
+                long ret;
+
+                ts->heap_base = do_brk(0);
+                limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
+                /* Try a big heap, and reduce the size if that fails.  */
+                for (;;) {
+                    ret = do_brk(limit);
+                    if (ret != -1)
+                        break;
+                    limit = (ts->heap_base >> 1) + (limit >> 1);
+                }
+                ts->heap_limit = limit;
+            }
+              
+            ptr = lock_user(ARG(0), 16, 0);
+            ptr[0] = tswap32(ts->heap_base);
+            ptr[1] = tswap32(ts->heap_limit);
+            ptr[2] = tswap32(ts->stack_base);
+            ptr[3] = tswap32(0); /* Stack limit.  */
+            unlock_user(ptr, ARG(0), 16);
+#else
+            limit = ram_size;
+            ptr = lock_user(ARG(0), 16, 0);
+            /* TODO: Make this use the limit of the loaded application.  */
+            ptr[0] = tswap32(limit / 2);
+            ptr[1] = tswap32(limit);
+            ptr[2] = tswap32(limit); /* Stack base */
+            ptr[3] = tswap32(0); /* Stack limit.  */
+            unlock_user(ptr, ARG(0), 16);
+#endif
+            return 0;
+        }
+    case SYS_EXIT:
+        exit(0);
+    default:
+        fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
+        cpu_dump_state(env, stderr, fprintf, 0);
+        abort();
+    }
+}

Modified: trunk/src/host/qemu-neo1973/audio/alsaaudio.c
===================================================================
--- trunk/src/host/qemu-neo1973/audio/alsaaudio.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/alsaaudio.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -157,6 +157,12 @@
     case AUD_FMT_U16:
         return SND_PCM_FORMAT_U16_LE;
 
+    case AUD_FMT_S32:
+        return SND_PCM_FORMAT_S32_LE;
+
+    case AUD_FMT_U32:
+        return SND_PCM_FORMAT_U32_LE;
+
     default:
         dolog ("Internal logic error: Bad audio format %d\n", fmt);
 #ifdef DEBUG_AUDIO
@@ -199,6 +205,26 @@
         *fmt = AUD_FMT_U16;
         break;
 
+    case SND_PCM_FORMAT_S32_LE:
+        *endianness = 0;
+        *fmt = AUD_FMT_S32;
+        break;
+
+    case SND_PCM_FORMAT_U32_LE:
+        *endianness = 0;
+        *fmt = AUD_FMT_U32;
+        break;
+
+    case SND_PCM_FORMAT_S32_BE:
+        *endianness = 1;
+        *fmt = AUD_FMT_S32;
+        break;
+
+    case SND_PCM_FORMAT_U32_BE:
+        *endianness = 1;
+        *fmt = AUD_FMT_U32;
+        break;
+
     default:
         dolog ("Unrecognized audio format %d\n", alsafmt);
         return -1;

Modified: trunk/src/host/qemu-neo1973/audio/audio.c
===================================================================
--- trunk/src/host/qemu-neo1973/audio/audio.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/audio.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -80,7 +80,8 @@
         {
             44100,              /* freq */
             2,                  /* nchannels */
-            AUD_FMT_S16         /* fmt */
+            AUD_FMT_S16,        /* fmt */
+            AUDIO_HOST_ENDIANNESS
         }
     },
 
@@ -91,7 +92,8 @@
         {
             44100,              /* freq */
             2,                  /* nchannels */
-            AUD_FMT_S16         /* fmt */
+            AUD_FMT_S16,        /* fmt */
+            AUDIO_HOST_ENDIANNESS
         }
     },
 
@@ -166,6 +168,25 @@
 }
 #endif
 
+static inline int audio_bits_to_index (int bits)
+{
+    switch (bits) {
+    case 8:
+        return 0;
+
+    case 16:
+        return 1;
+
+    case 32:
+        return 2;
+
+    default:
+        audio_bug ("bits_to_index", 1);
+        AUD_log (NULL, "invalid bits %d\n", bits);
+        return 0;
+    }
+}
+
 void *audio_calloc (const char *funcname, int nmemb, size_t size)
 {
     int cond;
@@ -227,6 +248,12 @@
 
     case AUD_FMT_S16:
         return "S16";
+
+    case AUD_FMT_U32:
+        return "U32";
+
+    case AUD_FMT_S32:
+        return "S32";
     }
 
     dolog ("Bogus audfmt %d returning S16\n", fmt);
@@ -243,6 +270,10 @@
         *defaultp = 0;
         return AUD_FMT_U16;
     }
+    else if (!strcasecmp (s, "u32")) {
+        *defaultp = 0;
+        return AUD_FMT_U32;
+    }
     else if (!strcasecmp (s, "s8")) {
         *defaultp = 0;
         return AUD_FMT_S8;
@@ -251,6 +282,10 @@
         *defaultp = 0;
         return AUD_FMT_S16;
     }
+    else if (!strcasecmp (s, "s32")) {
+        *defaultp = 0;
+        return AUD_FMT_S32;
+    }
     else {
         dolog ("Bogus audio format `%s' using %s\n",
                s, audio_audfmt_to_string (defval));
@@ -538,6 +573,8 @@
     case AUD_FMT_U8:
     case AUD_FMT_S16:
     case AUD_FMT_U16:
+    case AUD_FMT_S32:
+    case AUD_FMT_U32:
         break;
     default:
         invalid = 1;
@@ -563,6 +600,12 @@
     case AUD_FMT_U16:
         bits = 16;
         break;
+
+    case AUD_FMT_S32:
+        sign = 1;
+    case AUD_FMT_U32:
+        bits = 32;
+        break;
     }
     return info->freq == as->freq
         && info->nchannels == as->nchannels
@@ -573,7 +616,7 @@
 
 void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as)
 {
-    int bits = 8, sign = 0;
+    int bits = 8, sign = 0, shift = 0;
 
     switch (as->fmt) {
     case AUD_FMT_S8:
@@ -585,14 +628,22 @@
         sign = 1;
     case AUD_FMT_U16:
         bits = 16;
+        shift = 1;
         break;
+
+    case AUD_FMT_S32:
+        sign = 1;
+    case AUD_FMT_U32:
+        bits = 32;
+        shift = 2;
+        break;
     }
 
     info->freq = as->freq;
     info->bits = bits;
     info->sign = sign;
     info->nchannels = as->nchannels;
-    info->shift = (as->nchannels == 2) + (bits == 16);
+    info->shift = (as->nchannels == 2) + shift;
     info->align = (1 << info->shift) - 1;
     info->bytes_per_second = info->freq << info->shift;
     info->swap_endianness = (as->endianness != AUDIO_HOST_ENDIANNESS);
@@ -608,22 +659,49 @@
         memset (buf, 0x00, len << info->shift);
     }
     else {
-        if (info->bits == 8) {
+        switch (info->bits) {
+        case 8:
             memset (buf, 0x80, len << info->shift);
-        }
-        else {
-            int i;
-            uint16_t *p = buf;
-            int shift = info->nchannels - 1;
-            short s = INT16_MAX;
+            break;
 
-            if (info->swap_endianness) {
-                s = bswap16 (s);
+        case 16:
+            {
+                int i;
+                uint16_t *p = buf;
+                int shift = info->nchannels - 1;
+                short s = INT16_MAX;
+
+                if (info->swap_endianness) {
+                    s = bswap16 (s);
+                }
+
+                for (i = 0; i < len << shift; i++) {
+                    p[i] = s;
+                }
             }
+            break;
 
-            for (i = 0; i < len << shift; i++) {
-                p[i] = s;
+        case 32:
+            {
+                int i;
+                uint32_t *p = buf;
+                int shift = info->nchannels - 1;
+                int32_t s = INT32_MAX;
+
+                if (info->swap_endianness) {
+                    s = bswap32 (s);
+                }
+
+                for (i = 0; i < len << shift; i++) {
+                    p[i] = s;
+                }
             }
+            break;
+
+        default:
+            AUD_log (NULL, "audio_pcm_info_clear_buf: invalid bits %d\n",
+                     info->bits);
+            break;
         }
     }
 }
@@ -1811,7 +1889,7 @@
             [hw->info.nchannels == 2]
             [hw->info.sign]
             [hw->info.swap_endianness]
-            [hw->info.bits == 16];
+            [audio_bits_to_index (hw->info.bits)];
 
         LIST_INSERT_HEAD (&s->cap_head, cap, entries);
         LIST_INSERT_HEAD (&cap->cb_head, cb, entries);

Modified: trunk/src/host/qemu-neo1973/audio/audio.h
===================================================================
--- trunk/src/host/qemu-neo1973/audio/audio.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/audio.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -33,7 +33,9 @@
     AUD_FMT_U8,
     AUD_FMT_S8,
     AUD_FMT_U16,
-    AUD_FMT_S16
+    AUD_FMT_S16,
+    AUD_FMT_U32,
+    AUD_FMT_S32
 } audfmt_e;
 
 #ifdef WORDS_BIGENDIAN

Modified: trunk/src/host/qemu-neo1973/audio/audio_template.h
===================================================================
--- trunk/src/host/qemu-neo1973/audio/audio_template.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/audio_template.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -164,7 +164,7 @@
         [sw->info.nchannels == 2]
         [sw->info.sign]
         [sw->info.swap_endianness]
-        [sw->info.bits == 16];
+        [audio_bits_to_index (sw->info.bits)];
 
     sw->name = qemu_strdup (name);
     err = glue (audio_pcm_sw_alloc_resources_, TYPE) (sw);
@@ -288,7 +288,7 @@
         [hw->info.nchannels == 2]
         [hw->info.sign]
         [hw->info.swap_endianness]
-        [hw->info.bits == 16];
+        [audio_bits_to_index (hw->info.bits)];
 
     if (glue (audio_pcm_hw_alloc_resources_, TYPE) (hw)) {
         goto err1;

Modified: trunk/src/host/qemu-neo1973/audio/coreaudio.c
===================================================================
--- trunk/src/host/qemu-neo1973/audio/coreaudio.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/coreaudio.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -294,7 +294,6 @@
     coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
     UInt32 propertySize;
     int err;
-    int bits = 8;
     const char *typ = "playback";
     AudioValueRange frameRange;
 
@@ -305,10 +304,6 @@
         return -1;
     }
 
-    if (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) {
-        bits = 16;
-    }
-
     audio_pcm_init_info (&hw->info, as);
 
     /* open default output device */

Modified: trunk/src/host/qemu-neo1973/audio/mixeng.c
===================================================================
--- trunk/src/host/qemu-neo1973/audio/mixeng.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/mixeng.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -82,6 +82,7 @@
 #undef IN_T
 #undef SHIFT
 
+/* Unsigned 16 bit */
 #define IN_T uint16_t
 #define IN_MIN 0
 #define IN_MAX USHRT_MAX
@@ -101,26 +102,72 @@
 #undef IN_T
 #undef SHIFT
 
-t_sample *mixeng_conv[2][2][2][2] = {
+/* Signed 32 bit */
+#define IN_T int32_t
+#define IN_MIN INT32_MIN
+#define IN_MAX INT32_MAX
+#define SIGNED
+#define SHIFT 32
+#define ENDIAN_CONVERSION natural
+#define ENDIAN_CONVERT(v) (v)
+#include "mixeng_template.h"
+#undef ENDIAN_CONVERT
+#undef ENDIAN_CONVERSION
+#define ENDIAN_CONVERSION swap
+#define ENDIAN_CONVERT(v) bswap32 (v)
+#include "mixeng_template.h"
+#undef ENDIAN_CONVERT
+#undef ENDIAN_CONVERSION
+#undef SIGNED
+#undef IN_MAX
+#undef IN_MIN
+#undef IN_T
+#undef SHIFT
+
+/* Unsigned 16 bit */
+#define IN_T uint32_t
+#define IN_MIN 0
+#define IN_MAX UINT32_MAX
+#define SHIFT 32
+#define ENDIAN_CONVERSION natural
+#define ENDIAN_CONVERT(v) (v)
+#include "mixeng_template.h"
+#undef ENDIAN_CONVERT
+#undef ENDIAN_CONVERSION
+#define ENDIAN_CONVERSION swap
+#define ENDIAN_CONVERT(v) bswap32 (v)
+#include "mixeng_template.h"
+#undef ENDIAN_CONVERT
+#undef ENDIAN_CONVERSION
+#undef IN_MAX
+#undef IN_MIN
+#undef IN_T
+#undef SHIFT
+
+t_sample *mixeng_conv[2][2][2][3] = {
     {
         {
             {
                 conv_natural_uint8_t_to_mono,
-                conv_natural_uint16_t_to_mono
+                conv_natural_uint16_t_to_mono,
+                conv_natural_uint32_t_to_mono
             },
             {
                 conv_natural_uint8_t_to_mono,
-                conv_swap_uint16_t_to_mono
+                conv_swap_uint16_t_to_mono,
+                conv_swap_uint32_t_to_mono,
             }
         },
         {
             {
                 conv_natural_int8_t_to_mono,
-                conv_natural_int16_t_to_mono
+                conv_natural_int16_t_to_mono,
+                conv_natural_int32_t_to_mono
             },
             {
                 conv_natural_int8_t_to_mono,
-                conv_swap_int16_t_to_mono
+                conv_swap_int16_t_to_mono,
+                conv_swap_int32_t_to_mono
             }
         }
     },
@@ -128,46 +175,54 @@
         {
             {
                 conv_natural_uint8_t_to_stereo,
-                conv_natural_uint16_t_to_stereo
+                conv_natural_uint16_t_to_stereo,
+                conv_natural_uint32_t_to_stereo
             },
             {
                 conv_natural_uint8_t_to_stereo,
-                conv_swap_uint16_t_to_stereo
+                conv_swap_uint16_t_to_stereo,
+                conv_swap_uint32_t_to_stereo
             }
         },
         {
             {
                 conv_natural_int8_t_to_stereo,
-                conv_natural_int16_t_to_stereo
+                conv_natural_int16_t_to_stereo,
+                conv_natural_int32_t_to_stereo
             },
             {
                 conv_natural_int8_t_to_stereo,
-                conv_swap_int16_t_to_stereo
+                conv_swap_int16_t_to_stereo,
+                conv_swap_int32_t_to_stereo,
             }
         }
     }
 };
 
-f_sample *mixeng_clip[2][2][2][2] = {
+f_sample *mixeng_clip[2][2][2][3] = {
     {
         {
             {
                 clip_natural_uint8_t_from_mono,
-                clip_natural_uint16_t_from_mono
+                clip_natural_uint16_t_from_mono,
+                clip_natural_uint32_t_from_mono
             },
             {
                 clip_natural_uint8_t_from_mono,
-                clip_swap_uint16_t_from_mono
+                clip_swap_uint16_t_from_mono,
+                clip_swap_uint32_t_from_mono
             }
         },
         {
             {
                 clip_natural_int8_t_from_mono,
-                clip_natural_int16_t_from_mono
+                clip_natural_int16_t_from_mono,
+                clip_natural_int32_t_from_mono
             },
             {
                 clip_natural_int8_t_from_mono,
-                clip_swap_int16_t_from_mono
+                clip_swap_int16_t_from_mono,
+                clip_swap_int32_t_from_mono
             }
         }
     },
@@ -175,21 +230,25 @@
         {
             {
                 clip_natural_uint8_t_from_stereo,
-                clip_natural_uint16_t_from_stereo
+                clip_natural_uint16_t_from_stereo,
+                clip_natural_uint32_t_from_stereo
             },
             {
                 clip_natural_uint8_t_from_stereo,
-                clip_swap_uint16_t_from_stereo
+                clip_swap_uint16_t_from_stereo,
+                clip_swap_uint32_t_from_stereo
             }
         },
         {
             {
                 clip_natural_int8_t_from_stereo,
-                clip_natural_int16_t_from_stereo
+                clip_natural_int16_t_from_stereo,
+                clip_natural_int32_t_from_stereo
             },
             {
                 clip_natural_int8_t_from_stereo,
-                clip_swap_int16_t_from_stereo
+                clip_swap_int16_t_from_stereo,
+                clip_swap_int32_t_from_stereo
             }
         }
     }

Modified: trunk/src/host/qemu-neo1973/audio/mixeng.h
===================================================================
--- trunk/src/host/qemu-neo1973/audio/mixeng.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/mixeng.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -37,8 +37,8 @@
                          int samples, volume_t *vol);
 typedef void (f_sample) (void *dst, const st_sample_t *src, int samples);
 
-extern t_sample *mixeng_conv[2][2][2][2];
-extern f_sample *mixeng_clip[2][2][2][2];
+extern t_sample *mixeng_conv[2][2][2][3];
+extern f_sample *mixeng_clip[2][2][2][3];
 
 void *st_rate_start (int inrate, int outrate);
 void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,

Modified: trunk/src/host/qemu-neo1973/audio/ossaudio.c
===================================================================
--- trunk/src/host/qemu-neo1973/audio/ossaudio.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/ossaudio.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -21,10 +21,15 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+#include <stdlib.h>
 #include <sys/mman.h>
 #include <sys/types.h>
 #include <sys/ioctl.h>
+#ifdef __OpenBSD__
+#include <soundcard.h>
+#else
 #include <sys/soundcard.h>
+#endif
 #include "vl.h"
 
 #define AUDIO_CAP "oss"

Modified: trunk/src/host/qemu-neo1973/audio/wavaudio.c
===================================================================
--- trunk/src/host/qemu-neo1973/audio/wavaudio.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/wavaudio.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -41,7 +41,8 @@
     {
         44100,
         2,
-        AUD_FMT_S16
+        AUD_FMT_S16,
+        AUDIO_HOST_ENDIANNESS
     },
     "qemu.wav"
 };
@@ -131,6 +132,11 @@
     case AUD_FMT_U16:
         bits16 = 1;
         break;
+
+    case AUD_FMT_S32:
+    case AUD_FMT_U32:
+        dolog ("WAVE files can not handle 32bit formats\n");
+        return -1;
     }
 
     hdr[34] = bits16 ? 0x10 : 0x08;

Modified: trunk/src/host/qemu-neo1973/audio/wavcapture.c
===================================================================
--- trunk/src/host/qemu-neo1973/audio/wavcapture.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/wavcapture.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -37,15 +37,15 @@
     if (wav->f) {
         le_store (rlen, rifflen, 4);
         le_store (dlen, datalen, 4);
-        
+
         qemu_fseek (wav->f, 4, SEEK_SET);
         qemu_put_buffer (wav->f, rlen, 4);
-        
+
         qemu_fseek (wav->f, 32, SEEK_CUR);
         qemu_put_buffer (wav->f, dlen, 4);
         qemu_fclose (wav->f);
     }
-    
+
     qemu_free (wav->path);
 }
 

Modified: trunk/src/host/qemu-neo1973/block-qcow2.c
===================================================================
--- trunk/src/host/qemu-neo1973/block-qcow2.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/block-qcow2.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1886,6 +1886,8 @@
     int64_t table_offset;
     uint64_t data64;
     uint32_t data32;
+    int old_table_size;
+    int64_t old_table_offset;
 
     if (min_size <= s->refcount_table_size)
         return 0;
@@ -1931,10 +1933,14 @@
                     &data32, sizeof(data32)) != sizeof(data32))
         goto fail;
     qemu_free(s->refcount_table);
+    old_table_offset = s->refcount_table_offset;
+    old_table_size = s->refcount_table_size;
     s->refcount_table = new_table;
     s->refcount_table_size = new_table_size;
+    s->refcount_table_offset = table_offset;
 
     update_refcount(bs, table_offset, new_table_size2, 1);
+    free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t));
     return 0;
  fail:
     free_clusters(bs, table_offset, new_table_size2);

Modified: trunk/src/host/qemu-neo1973/block-raw.c
===================================================================
--- trunk/src/host/qemu-neo1973/block-raw.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/block-raw.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -914,8 +914,13 @@
     s->hfile = CreateFile(filename, access_flags, 
                           FILE_SHARE_READ, NULL,
                           create_flags, overlapped, NULL);
-    if (s->hfile == INVALID_HANDLE_VALUE) 
+    if (s->hfile == INVALID_HANDLE_VALUE) {
+        int err = GetLastError();
+
+        if (err == ERROR_ACCESS_DENIED)
+            return -EACCES;
         return -1;
+    }
     return 0;
 }
 
@@ -1278,8 +1283,13 @@
     s->hfile = CreateFile(filename, access_flags, 
                           FILE_SHARE_READ, NULL,
                           create_flags, overlapped, NULL);
-    if (s->hfile == INVALID_HANDLE_VALUE) 
+    if (s->hfile == INVALID_HANDLE_VALUE) {
+        int err = GetLastError();
+
+        if (err == ERROR_ACCESS_DENIED)
+            return -EACCES;
         return -1;
+    }
     return 0;
 }
 

Modified: trunk/src/host/qemu-neo1973/block-vmdk.c
===================================================================
--- trunk/src/host/qemu-neo1973/block-vmdk.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/block-vmdk.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -22,6 +22,7 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+
 #include "vl.h"
 #include "block_int.h"
 
@@ -59,7 +60,7 @@
 #define L2_CACHE_SIZE 16
 
 typedef struct BDRVVmdkState {
-    int fd;
+    BlockDriverState *hd;
     int64_t l1_table_offset;
     int64_t l1_backup_table_offset;
     uint32_t *l1_table;
@@ -73,6 +74,7 @@
     uint32_t l2_cache_counts[L2_CACHE_SIZE];
 
     unsigned int cluster_sectors;
+    uint32_t parent_cid;
 } BDRVVmdkState;
 
 static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
@@ -89,27 +91,278 @@
         return 0;
 }
 
+#define CHECK_CID 1
+
+#define SECTOR_SIZE 512				
+#define DESC_SIZE 20*SECTOR_SIZE	// 20 sectors of 512 bytes each
+#define HEADER_SIZE 512   			// first sector of 512 bytes 
+
+static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
+{
+    BDRVVmdkState *s = bs->opaque;
+    char desc[DESC_SIZE];
+    uint32_t cid;
+    char *p_name, *cid_str; 
+    size_t cid_str_size;
+
+    /* the descriptor offset = 0x200 */
+    if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+        return 0;
+
+    if (parent) {
+        cid_str = "parentCID";
+        cid_str_size = sizeof("parentCID");
+    } else {
+        cid_str = "CID";
+        cid_str_size = sizeof("CID");
+    }
+
+    if ((p_name = strstr(desc,cid_str)) != 0) {
+        p_name += cid_str_size;
+        sscanf(p_name,"%x",&cid);
+    }
+
+    return cid;
+}
+
+static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
+{
+    BDRVVmdkState *s = bs->opaque;
+    char desc[DESC_SIZE], tmp_desc[DESC_SIZE];
+    char *p_name, *tmp_str;
+
+    /* the descriptor offset = 0x200 */
+    if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+        return -1;
+
+    tmp_str = strstr(desc,"parentCID");
+    strcpy(tmp_desc, tmp_str);
+    if ((p_name = strstr(desc,"CID")) != 0) {
+        p_name += sizeof("CID");
+        sprintf(p_name,"%x\n",cid);
+        strcat(desc,tmp_desc);
+    }
+
+    if (bdrv_pwrite(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+        return -1;
+    return 0;
+}
+
+static int vmdk_is_cid_valid(BlockDriverState *bs)
+{
+#ifdef CHECK_CID
+    BDRVVmdkState *s = bs->opaque;
+    BlockDriverState *p_bs = s->hd->backing_hd;
+    uint32_t cur_pcid;
+
+    if (p_bs) {
+        cur_pcid = vmdk_read_cid(p_bs,0);
+        if (s->parent_cid != cur_pcid)
+            // CID not valid
+            return 0;
+    }
+#endif
+    // CID valid
+    return 1;
+}
+
+static int vmdk_snapshot_create(const char *filename, const char *backing_file)
+{
+    int snp_fd, p_fd;
+    uint32_t p_cid;
+    char *p_name, *gd_buf, *rgd_buf; 
+    const char *real_filename, *temp_str;
+    VMDK4Header header;
+    uint32_t gde_entries, gd_size;
+    int64_t gd_offset, rgd_offset, capacity, gt_size;
+    char p_desc[DESC_SIZE], s_desc[DESC_SIZE], hdr[HEADER_SIZE];
+    char *desc_template =
+    "# Disk DescriptorFile\n"
+    "version=1\n"
+    "CID=%x\n"
+    "parentCID=%x\n"
+    "createType=\"monolithicSparse\"\n"
+    "parentFileNameHint=\"%s\"\n"
+    "\n"
+    "# Extent description\n"
+    "RW %lu SPARSE \"%s\"\n"
+    "\n"
+    "# The Disk Data Base \n"
+    "#DDB\n"
+    "\n";
+
+    snp_fd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 0644);
+    if (snp_fd < 0)
+        return -1;
+    p_fd = open(backing_file, O_RDONLY | O_BINARY | O_LARGEFILE);
+    if (p_fd < 0) {
+        close(snp_fd);
+        return -1;
+    }
+
+    /* read the header */
+    if (lseek(p_fd, 0x0, SEEK_SET) == -1)
+        goto fail;
+    if (read(p_fd, hdr, HEADER_SIZE) != HEADER_SIZE)
+        goto fail;
+
+    /* write the header */
+    if (lseek(snp_fd, 0x0, SEEK_SET) == -1)
+        goto fail;
+    if (write(snp_fd, hdr, HEADER_SIZE) == -1)
+        goto fail;
+
+    memset(&header, 0, sizeof(header));
+    memcpy(&header,&hdr[4], sizeof(header)); // skip the VMDK4_MAGIC
+
+    ftruncate(snp_fd, header.grain_offset << 9);
+    /* the descriptor offset = 0x200 */
+    if (lseek(p_fd, 0x200, SEEK_SET) == -1)
+        goto fail;
+    if (read(p_fd, p_desc, DESC_SIZE) != DESC_SIZE)
+        goto fail;
+
+    if ((p_name = strstr(p_desc,"CID")) != 0) {
+        p_name += sizeof("CID");
+        sscanf(p_name,"%x",&p_cid);
+    }
+
+    real_filename = filename;
+    if ((temp_str = strrchr(real_filename, '\\')) != NULL)
+        real_filename = temp_str + 1;
+    if ((temp_str = strrchr(real_filename, '/')) != NULL)
+        real_filename = temp_str + 1;
+    if ((temp_str = strrchr(real_filename, ':')) != NULL)
+        real_filename = temp_str + 1;
+
+    sprintf(s_desc, desc_template, p_cid, p_cid, backing_file
+            , (uint32_t)header.capacity, real_filename);
+
+    /* write the descriptor */
+    if (lseek(snp_fd, 0x200, SEEK_SET) == -1)
+        goto fail;
+    if (write(snp_fd, s_desc, strlen(s_desc)) == -1)
+        goto fail;
+
+    gd_offset = header.gd_offset * SECTOR_SIZE;     // offset of GD table
+    rgd_offset = header.rgd_offset * SECTOR_SIZE;   // offset of RGD table
+    capacity = header.capacity * SECTOR_SIZE;       // Extent size
+    /*
+     * Each GDE span 32M disk, means:
+     * 512 GTE per GT, each GTE points to grain
+     */
+    gt_size = (int64_t)header.num_gtes_per_gte * header.granularity * SECTOR_SIZE;
+    if (!gt_size)
+        goto fail;
+    gde_entries = (uint32_t)(capacity / gt_size);  // number of gde/rgde 
+    gd_size = gde_entries * sizeof(uint32_t);
+
+    /* write RGD */
+    rgd_buf = qemu_malloc(gd_size);
+    if (!rgd_buf)
+        goto fail;
+    if (lseek(p_fd, rgd_offset, SEEK_SET) == -1)
+        goto fail_rgd;
+    if (read(p_fd, rgd_buf, gd_size) != gd_size)
+        goto fail_rgd;
+    if (lseek(snp_fd, rgd_offset, SEEK_SET) == -1)
+        goto fail_rgd;
+    if (write(snp_fd, rgd_buf, gd_size) == -1)
+        goto fail_rgd;
+    qemu_free(rgd_buf);
+
+    /* write GD */
+    gd_buf = qemu_malloc(gd_size);
+    if (!gd_buf)
+        goto fail_rgd;
+    if (lseek(p_fd, gd_offset, SEEK_SET) == -1)
+        goto fail_gd;
+    if (read(p_fd, gd_buf, gd_size) != gd_size)
+        goto fail_gd;
+    if (lseek(snp_fd, gd_offset, SEEK_SET) == -1)
+        goto fail_gd;
+    if (write(snp_fd, gd_buf, gd_size) == -1)
+        goto fail_gd;
+    qemu_free(gd_buf);
+
+    close(p_fd);
+    close(snp_fd);
+    return 0;
+
+    fail_gd:
+    qemu_free(gd_buf);
+    fail_rgd:   
+    qemu_free(rgd_buf);
+    fail:
+    close(p_fd);
+    close(snp_fd);
+    return -1;
+}
+
+static void vmdk_parent_close(BlockDriverState *bs)
+{
+    if (bs->backing_hd)
+        bdrv_close(bs->backing_hd);
+}
+
+
+static int vmdk_parent_open(BlockDriverState *bs, const char * filename)
+{
+    BDRVVmdkState *s = bs->opaque;
+    char *p_name; 
+    char desc[DESC_SIZE];
+    char parent_img_name[1024];
+
+    /* the descriptor offset = 0x200 */
+    if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+        return -1;
+
+    if ((p_name = strstr(desc,"parentFileNameHint")) != 0) {
+        char *end_name;
+        struct stat file_buf;
+
+        p_name += sizeof("parentFileNameHint") + 1;
+        if ((end_name = strchr(p_name,'\"')) == 0)
+            return -1;
+                
+        strncpy(s->hd->backing_file, p_name, end_name - p_name);
+        if (stat(s->hd->backing_file, &file_buf) != 0) {
+            path_combine(parent_img_name, sizeof(parent_img_name),
+                         filename, s->hd->backing_file);
+        } else {
+            strcpy(parent_img_name, s->hd->backing_file);
+        }
+
+        s->hd->backing_hd = bdrv_new("");
+        if (!s->hd->backing_hd) {
+            failure:
+            bdrv_close(s->hd);
+            return -1;
+        }
+        if (bdrv_open(s->hd->backing_hd, parent_img_name, 0) < 0)
+            goto failure;
+    }
+
+    return 0;
+}
+
 static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
 {
     BDRVVmdkState *s = bs->opaque;
-    int fd, i;
     uint32_t magic;
-    int l1_size;
+    int l1_size, i, ret;
 
-    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
-    if (fd < 0) {
-        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
-        if (fd < 0)
-            return -1;
-        bs->read_only = 1;
-    }
-    if (read(fd, &magic, sizeof(magic)) != sizeof(magic))
+    ret = bdrv_file_open(&s->hd, filename, flags);
+    if (ret < 0)
+        return ret;
+    if (bdrv_pread(s->hd, 0, &magic, sizeof(magic)) != sizeof(magic))
         goto fail;
+
     magic = be32_to_cpu(magic);
     if (magic == VMDK3_MAGIC) {
         VMDK3Header header;
-        if (read(fd, &header, sizeof(header)) != 
-            sizeof(header))
+
+        if (bdrv_pread(s->hd, sizeof(magic), &header, sizeof(header)) != sizeof(header))
             goto fail;
         s->cluster_sectors = le32_to_cpu(header.granularity);
         s->l2_size = 1 << 9;
@@ -120,8 +373,8 @@
         s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
     } else if (magic == VMDK4_MAGIC) {
         VMDK4Header header;
-        
-        if (read(fd, &header, sizeof(header)) != sizeof(header))
+
+        if (bdrv_pread(s->hd, sizeof(magic), &header, sizeof(header)) != sizeof(header))
             goto fail;
         bs->total_sectors = le64_to_cpu(header.capacity);
         s->cluster_sectors = le64_to_cpu(header.granularity);
@@ -133,18 +386,23 @@
             / s->l1_entry_sectors;
         s->l1_table_offset = le64_to_cpu(header.rgd_offset) << 9;
         s->l1_backup_table_offset = le64_to_cpu(header.gd_offset) << 9;
+
+        // try to open parent images, if exist
+        if (vmdk_parent_open(bs, filename) != 0)
+            goto fail;
+        // write the CID once after the image creation
+        s->parent_cid = vmdk_read_cid(bs,1);
     } else {
         goto fail;
     }
+
     /* read the L1 table */
     l1_size = s->l1_size * sizeof(uint32_t);
     s->l1_table = qemu_malloc(l1_size);
     if (!s->l1_table)
         goto fail;
-    if (lseek(fd, s->l1_table_offset, SEEK_SET) == -1)
+    if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, l1_size) != l1_size)
         goto fail;
-    if (read(fd, s->l1_table, l1_size) != l1_size)
-        goto fail;
     for(i = 0; i < s->l1_size; i++) {
         le32_to_cpus(&s->l1_table[i]);
     }
@@ -153,10 +411,8 @@
         s->l1_backup_table = qemu_malloc(l1_size);
         if (!s->l1_backup_table)
             goto fail;
-        if (lseek(fd, s->l1_backup_table_offset, SEEK_SET) == -1)
+        if (bdrv_pread(s->hd, s->l1_backup_table_offset, s->l1_backup_table, l1_size) != l1_size)
             goto fail;
-        if (read(fd, s->l1_backup_table, l1_size) != l1_size)
-            goto fail;
         for(i = 0; i < s->l1_size; i++) {
             le32_to_cpus(&s->l1_backup_table[i]);
         }
@@ -165,16 +421,43 @@
     s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint32_t));
     if (!s->l2_cache)
         goto fail;
-    s->fd = fd;
     return 0;
  fail:
     qemu_free(s->l1_backup_table);
     qemu_free(s->l1_table);
     qemu_free(s->l2_cache);
-    close(fd);
+    bdrv_delete(s->hd);
     return -1;
 }
 
+static uint64_t get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate);
+
+static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset,
+                             uint64_t offset, int allocate)
+{
+    uint64_t parent_cluster_offset;
+    BDRVVmdkState *s = bs->opaque;
+    uint8_t  whole_grain[s->cluster_sectors*512];        // 128 sectors * 512 bytes each = grain size 64KB
+
+    // we will be here if it's first write on non-exist grain(cluster).
+    // try to read from parent image, if exist
+    if (s->hd->backing_hd) {
+        BDRVVmdkState *ps = s->hd->backing_hd->opaque;
+
+        if (!vmdk_is_cid_valid(bs))
+            return -1;
+        parent_cluster_offset = get_cluster_offset(s->hd->backing_hd, offset, allocate);
+        if (bdrv_pread(ps->hd, parent_cluster_offset, whole_grain, ps->cluster_sectors*512) != 
+                                                                            ps->cluster_sectors*512)
+            return -1;
+
+        if (bdrv_pwrite(s->hd, cluster_offset << 9, whole_grain, sizeof(whole_grain)) != 
+                                                                            sizeof(whole_grain))
+            return -1;
+    }
+    return 0;
+}
+
 static uint64_t get_cluster_offset(BlockDriverState *bs,
                                    uint64_t offset, int allocate)
 {
@@ -212,34 +495,41 @@
         }
     }
     l2_table = s->l2_cache + (min_index * s->l2_size);
-    lseek(s->fd, (int64_t)l2_offset * 512, SEEK_SET);
-    if (read(s->fd, l2_table, s->l2_size * sizeof(uint32_t)) != 
-        s->l2_size * sizeof(uint32_t))
+    if (bdrv_pread(s->hd, (int64_t)l2_offset * 512, l2_table, s->l2_size * sizeof(uint32_t)) != 
+                                                                        s->l2_size * sizeof(uint32_t))
         return 0;
+
     s->l2_cache_offsets[min_index] = l2_offset;
     s->l2_cache_counts[min_index] = 1;
  found:
     l2_index = ((offset >> 9) / s->cluster_sectors) % s->l2_size;
     cluster_offset = le32_to_cpu(l2_table[l2_index]);
     if (!cluster_offset) {
+        struct stat file_buf;
+
         if (!allocate)
             return 0;
-        cluster_offset = lseek(s->fd, 0, SEEK_END);
-        ftruncate(s->fd, cluster_offset + (s->cluster_sectors << 9));
+        stat(s->hd->filename, &file_buf);
+        cluster_offset = file_buf.st_size;
+        bdrv_truncate(s->hd, cluster_offset + (s->cluster_sectors << 9));
+
         cluster_offset >>= 9;
         /* update L2 table */
         tmp = cpu_to_le32(cluster_offset);
         l2_table[l2_index] = tmp;
-        lseek(s->fd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), SEEK_SET);
-        if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
+        if (bdrv_pwrite(s->hd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), 
+                        &tmp, sizeof(tmp)) != sizeof(tmp))
             return 0;
         /* update backup L2 table */
         if (s->l1_backup_table_offset != 0) {
             l2_offset = s->l1_backup_table[l1_index];
-            lseek(s->fd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), SEEK_SET);
-            if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
+            if (bdrv_pwrite(s->hd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), 
+                            &tmp, sizeof(tmp)) != sizeof(tmp))
                 return 0;
         }
+
+        if (get_whole_cluster(bs, cluster_offset, offset, allocate) == -1)
+            return 0;
     }
     cluster_offset <<= 9;
     return cluster_offset;
@@ -265,9 +555,9 @@
                     uint8_t *buf, int nb_sectors)
 {
     BDRVVmdkState *s = bs->opaque;
-    int ret, index_in_cluster, n;
+    int index_in_cluster, n, ret;
     uint64_t cluster_offset;
-    
+
     while (nb_sectors > 0) {
         cluster_offset = get_cluster_offset(bs, sector_num << 9, 0);
         index_in_cluster = sector_num % s->cluster_sectors;
@@ -275,11 +565,18 @@
         if (n > nb_sectors)
             n = nb_sectors;
         if (!cluster_offset) {
-            memset(buf, 0, 512 * n);
+            // try to read from parent image, if exist
+            if (s->hd->backing_hd) {
+                if (!vmdk_is_cid_valid(bs))
+                    return -1;
+                ret = bdrv_read(s->hd->backing_hd, sector_num, buf, n);
+                if (ret < 0)
+                    return -1;
+            } else {
+                memset(buf, 0, 512 * n);
+            }
         } else {
-            lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
-            ret = read(s->fd, buf, n * 512);
-            if (ret != n * 512) 
+            if(bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
                 return -1;
         }
         nb_sectors -= n;
@@ -293,8 +590,9 @@
                      const uint8_t *buf, int nb_sectors)
 {
     BDRVVmdkState *s = bs->opaque;
-    int ret, index_in_cluster, n;
+    int index_in_cluster, n;
     uint64_t cluster_offset;
+    static int cid_update = 0;
 
     while (nb_sectors > 0) {
         index_in_cluster = sector_num & (s->cluster_sectors - 1);
@@ -304,13 +602,17 @@
         cluster_offset = get_cluster_offset(bs, sector_num << 9, 1);
         if (!cluster_offset)
             return -1;
-        lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
-        ret = write(s->fd, buf, n * 512);
-        if (ret != n * 512)
+        if (bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
             return -1;
         nb_sectors -= n;
         sector_num += n;
         buf += n * 512;
+
+        // update CID on the first write every time the virtual disk is opened
+        if (!cid_update) {
+            vmdk_write_cid(bs, time(NULL));
+            cid_update++;
+        }
     }
     return 0;
 }
@@ -334,7 +636,7 @@
         "# The Disk Data Base \n"
         "#DDB\n"
         "\n"
-        "ddb.virtualHWVersion = \"3\"\n"
+        "ddb.virtualHWVersion = \"4\"\n"
         "ddb.geometry.cylinders = \"%lu\"\n"
         "ddb.geometry.heads = \"16\"\n"
         "ddb.geometry.sectors = \"63\"\n"
@@ -343,6 +645,9 @@
     const char *real_filename, *temp_str;
 
     /* XXX: add support for backing file */
+    if (backing_file) {
+        return vmdk_snapshot_create(filename, backing_file);
+    }
 
     fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
               0644);
@@ -421,15 +726,18 @@
 static void vmdk_close(BlockDriverState *bs)
 {
     BDRVVmdkState *s = bs->opaque;
+
     qemu_free(s->l1_table);
     qemu_free(s->l2_cache);
-    close(s->fd);
+    bdrv_delete(s->hd);
+    // try to close parent image, if exist
+    vmdk_parent_close(s->hd);
 }
 
 static void vmdk_flush(BlockDriverState *bs)
 {
     BDRVVmdkState *s = bs->opaque;
-    fsync(s->fd);
+    bdrv_flush(s->hd);
 }
 
 BlockDriver bdrv_vmdk = {

Modified: trunk/src/host/qemu-neo1973/block.c
===================================================================
--- trunk/src/host/qemu-neo1973/block.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/block.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -322,8 +322,8 @@
                BlockDriver *drv)
 {
     int ret, open_flags;
-    char tmp_filename[1024];
-    char backing_filename[1024];
+    char tmp_filename[PATH_MAX];
+    char backing_filename[PATH_MAX];
     
     bs->read_only = 0;
     bs->is_temporary = 0;

Modified: trunk/src/host/qemu-neo1973/configure
===================================================================
--- trunk/src/host/qemu-neo1973/configure	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/configure	2007-05-11 23:44:50 UTC (rev 1948)
@@ -50,10 +50,13 @@
   mips)
     cpu="mips"
   ;;
+  mips64)
+    cpu="mips64"
+  ;;
   s390)
     cpu="s390"
   ;;
-  sparc|sun4[muv])
+  sparc|sun4[cdmuv])
     cpu="sparc"
   ;;
   sparc64)
@@ -94,7 +97,8 @@
 check_gfx="yes"
 check_gcc="yes"
 softmmu="yes"
-user="no"
+linux_user="no"
+darwin_user="no"
 build_docs="no"
 gadgetfs="no"
 uname_release=""
@@ -127,15 +131,38 @@
 Darwin)
 bsd="yes"
 darwin="yes"
+darwin_user="yes"
+cocoa="yes"
+coreaudio="yes"
 OS_CFLAGS="-mdynamic-no-pic"
 ;;
 SunOS)
-solaris="yes"
+    solaris="yes"
+    make="gmake"
+    install="ginstall"
+    needs_libsunmath="no"
+    solarisrev=`uname -r | cut -f2 -d.`
+    if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
+        if test "$solarisrev" -le 9 ; then
+            if test -f /opt/SUNWspro/prod/lib/libsunmath.so.1; then
+                needs_libsunmath="yes"
+            else
+                echo "QEMU will not link correctly on Solaris 8/X86 or 9/x86 without"
+                echo "libsunmath from the Sun Studio compilers tools, due to a lack of"
+                echo "C99 math features in libm.so in Solaris 8/x86 and Solaris 9/x86"
+                echo "Studio 11 can be downloaded from www.sun.com."
+                exit 1
+            fi
+        fi
+        if test "$solarisrev" -ge 9 ; then
+            kqemu="yes"
+        fi
+    fi
 ;;
 *)
 oss="yes"
 linux="yes"
-user="yes"
+linux_user="yes"
 if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
     kqemu="yes"
 fi
@@ -148,18 +175,6 @@
   fi
 fi
 
-if [ "$solaris" = "yes" ] ; then
-    make="gmake"
-    install="ginstall"
-    solarisrev=`uname -r | cut -f2 -d.`
-fi
-
-if [ "$bsd" = "yes" -o "$solaris" = "yes" -o "$mingw32" = "yes" ] ; then
-    AIOLIBS=
-else
-    AIOLIBS="-lrt"
-fi
-
 # find source path
 source_path=`dirname "$0"`
 if [ -z "$source_path" ]; then
@@ -222,7 +237,7 @@
   ;;
   --fmod-inc=*) fmod_inc="$optarg"
   ;;
-  --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" ; user="no"
+  --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" ; linux_user="no"
   ;;
   --disable-slirp) slirp="no"
   ;;
@@ -242,19 +257,64 @@
   ;;
   --enable-system) softmmu="yes"
   ;;
-  --disable-user) user="no"
+  --disable-linux-user) linux_user="no"
   ;;
-  --enable-user) user="yes"
+  --enable-linux-user) linux_user="yes"
   ;;
+  --disable-darwin-user) darwin_user="no"
+  ;;
+  --enable-darwin-user) darwin_user="yes"
+  ;;
   --enable-uname-release=*) uname_release="$optarg"
   ;;
+  --sparc_cpu=*)
+      sparc_cpu="$optarg"
+      case $sparc_cpu in
+        v7|v8) SP_CFLAGS="-m32 -mcpu=${sparc_cpu} -D__sparc_${sparc_cpu}__"; SP_LDFLAGS="-m32"
+                 target_cpu="sparc"; cpu="sparc" ;;
+        v8plus|v8plusa) SP_CFLAGS="-m32 -mcpu=ultrasparc -D__sparc_${sparc_cpu}__"; SP_LDFLAGS="-m32"
+                 target_cpu="sparc"; cpu="sparc" ;;
+        v9)    SP_CFLAGS="-m64 -mcpu=ultrasparc -D__sparc_${sparc_cpu}__"; SP_LDFLAGS="-m64"
+                 target_cpu="sparc64"; cpu="sparc64" ;;
+        *)     echo "undefined SPARC architecture. Exiting";exit 1;;
+      esac
+  ;;
   esac
 done
 
+if [ "$bsd" = "yes" -o "$darwin" = "yes" -o "$mingw32" = "yes" ] ; then
+    AIOLIBS=
+else
+    AIOLIBS="-lrt"
+fi
+
 # default flags for all hosts
 CFLAGS="$CFLAGS -Wall -O2 -g -fno-strict-aliasing"
 LDFLAGS="$LDFLAGS -g"
 
+#
+# If cpu ~= sparc and  sparc_cpu hasn't been defined, plug in the right
+# ARCH_CFLAGS/ARCH_LDFLAGS (assume sparc_v8plus for 32-bit and sparc_v9 for 64-bit)
+#
+case $cpu in
+    sparc) if test -z "$sparc_cpu" ; then
+               ARCH_CFLAGS="-m32 -mcpu=ultrasparc -D__sparc_v8plus__"
+               ARCH_LDFLAGS="-m32"
+           else
+               ARCH_CFLAGS="${SP_CFLAGS}"
+               ARCH_LDFLAGS="${SP_LDFLAGS}"
+           fi
+           ;;
+    sparc64) if test -z "$sparc_cpu" ; then
+               ARCH_CFLAGS="-m64 -mcpu=ultrasparc -D__sparc_v9__"
+               ARCH_LDFLAGS="-m64"
+           else
+               ARCH_CFLAGS="${SP_CFLAGS}"
+               ARCH_LDFLAGS="${SP_LDFLAGS}"
+           fi
+           ;;
+esac
+
 if test x"$show_help" = x"yes" ; then
 cat << EOF
 
@@ -286,14 +346,17 @@
 echo "  --enable-coreaudio       enable Coreaudio audio driver"
 echo "  --enable-alsa            enable ALSA audio driver"
 echo "  --enable-fmod            enable FMOD audio driver"
-echo "  --enabled-dsound         enable DirectSound audio driver"
+echo "  --enable-dsound          enable DirectSound audio driver"
 echo "  --enable-system          enable all system emulation targets"
 echo "  --disable-system         disable all system emulation targets"
-echo "  --enable-user            enable all linux usermode emulation targets"
-echo "  --disable-user           disable all linux usermode emulation targets"
+echo "  --enable-linux-user      enable all linux usermode emulation targets"
+echo "  --disable-linux-user     disable all linux usermode emulation targets"
+echo "  --enable-darwin-user     enable all darwin usermode emulation targets"
+echo "  --disable-darwin-user    disable all darwin usermode emulation targets"
 echo "  --fmod-lib               path to FMOD library"
 echo "  --fmod-inc               path to FMOD includes"
 echo "  --enable-uname-release=R Return R for uname -r in usermode emulation"
+echo "  --sparc_cpu=V            Build qemu for Sparc architecture v7, v8, v8plus, v8plusa, v9"
 echo ""
 echo "NOTE: The object files are built at the place where configure is launched"
 exit 1
@@ -308,7 +371,7 @@
 int main(void) {}
 EOF
 
-if $cc -c -o $TMPO $TMPC 2>/dev/null ; then
+if $cc -c -o $TMPO $TMPC 2> /dev/null ; then
   : C compiler works ok
 else
     echo "ERROR: \"$cc\" either does not exist or does not work"
@@ -332,20 +395,15 @@
 #endif
 int main(){return 0;}
 EOF
-    check_cc() {
-	which "$1" >&/dev/null
-	return $?
-    }
-
-    if "$cc" -o $TMPE $TMPC 2>/dev/null ; then
+    if "$cc" -o $TMPE $TMPC 2> /dev/null ; then
 	echo "WARNING: \"$cc\" looks like gcc 4.x"
 	found_compat_cc="no"
 	if test "$gcc3_search" = "yes" ; then
 	    echo "Looking for gcc 3.x"
 	    for compat_cc in $gcc3_list ; do
-		if check_cc "$compat_cc" ; then
+		if "$cross_prefix$compat_cc" --version > /dev/null 2>&1 ; then
 		    echo "Found \"$compat_cc\""
-		    cc="$compat_cc"
+		    cc="$cross_prefix$compat_cc"
 		    found_compat_cc="yes"
 		    break
 		fi
@@ -407,12 +465,16 @@
 if test -z "$target_list" ; then
 # these targets are portable
     if [ "$softmmu" = "yes" ] ; then
-        target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu arm-softmmu"
+        target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu mips64-softmmu mips64el-softmmu arm-softmmu ppc64-softmmu ppcemb-softmmu "
     fi
 # the following are Linux specific
-    if [ "$user" = "yes" ] ; then
-        target_list="i386-user arm-user armeb-user sparc-user ppc-user mips-user mipsel-user m68k-user $target_list"
+    if [ "$linux_user" = "yes" ] ; then
+        target_list="i386-linux-user arm-linux-user armeb-linux-user sparc-linux-user ppc-linux-user mips-linux-user mipsel-linux-user m68k-linux-user alpha-linux-user $target_list"
     fi
+# the following are Darwin specific
+    if [ "$darwin_user" = "yes" ] ; then
+        target_list="i386-darwin-user ppc-darwin-user $target_list"
+    fi
 else
     target_list=`echo "$target_list" | sed -e 's/,/ /g'`
 fi
@@ -433,7 +495,7 @@
 }
 EOF
 
-if $cc -o $TMPE $TMPC 2>/dev/null ; then
+if $cc -o $TMPE $TMPC 2> /dev/null ; then
 $TMPE && bigendian="yes"
 else
 echo big/little test failed
@@ -442,7 +504,7 @@
 else
 
 # if cross compiling, cannot launch a program, so make a static guess
-if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64" -o "$cpu" = "m68k" -o "$cpu" = "armv4b"; then
+if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "mips64" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64" -o "$cpu" = "m68k" -o "$cpu" = "armv4b"; then
     bigendian="yes"
 fi
 
@@ -460,11 +522,6 @@
 }
 EOF
 
-have_gcc3_options="no"
-if $cc -fno-reorder-blocks -fno-optimize-sibling-calls -o $TMPO $TMPC 2> /dev/null ; then
-   have_gcc3_options="yes"
-fi
-
 ##########################################
 # SDL probe
 
@@ -493,14 +550,16 @@
 if test "$_sdlversion" -lt 121 ; then
 sdl_too_old=yes
 else
-sdl=yes
+ if test "$cocoa" = "no" ; then
+   sdl=yes
+ fi
 fi
 
 # static link with sdl ?
 if test "$sdl" = "yes" ; then
 aa="no"
-`$sdl_config --static-libs | grep \\\-laa > /dev/null` && aa="yes"
-sdl_static_libs=`$sdl_config --static-libs`
+`$sdl_config --static-libs 2>/dev/null | grep \\\-laa > /dev/null` && aa="yes"
+sdl_static_libs=`$sdl_config --static-libs 2>/dev/null`
 if [ "$aa" = "yes" ] ; then
   sdl_static_libs="$sdl_static_libs `aalib-config --static-libs`"
 fi
@@ -514,6 +573,13 @@
 fi # sdl compile test
 
 fi # cross compilation
+
+else
+ # Make sure to disable cocoa if sdl was set
+ if test "$sdl" = "yes" ; then
+   cocoa="no"
+   coreaudio="no"
+ fi
 fi # -z $sdl
 
 ##########################################
@@ -536,27 +602,28 @@
 fi
 
 # Check if tools are available to build documentation.
-if [ -x "`which texi2html`" ] && [ -x "`which pod2man`" ]; then
+if [ -x "`which texi2html 2>/dev/null`" ] && \
+   [ -x "`which pod2man 2>/dev/null`" ]; then
   build_docs="yes"
 fi
 
 if test "$mingw32" = "yes" ; then
-if test -z "$prefix" ; then
-    prefix="/c/Program Files/Qemu"
-fi
-mandir="$prefix"
-datadir="$prefix"
-docdir="$prefix"
-bindir="$prefix"
+  if test -z "$prefix" ; then
+      prefix="/c/Program Files/Qemu"
+  fi
+  mansuffix=""
+  datasuffix=""
+  docsuffix=""
+  binsuffix=""
 else
-if test -z "$prefix" ; then
-    prefix="/usr/local"
+  if test -z "$prefix" ; then
+      prefix="/usr/local"
+  fi
+  mansuffix="/share/man"
+  datasuffix="/share/qemu"
+  docsuffix="/share/doc/qemu"
+  binsuffix="/bin"
 fi
-mandir="$prefix/share/man"
-datadir="$prefix/share/qemu"
-docdir="$prefix/share/doc/qemu"
-bindir="$prefix/bin"
-fi
 
 ##########################################
 # usb_gadgetfs headers
@@ -571,10 +638,10 @@
 fi
 
 echo "Install prefix    $prefix"
-echo "BIOS directory    $datadir"
-echo "binary directory  $bindir"
+echo "BIOS directory    $prefix$datasuffix"
+echo "binary directory  $prefix$binsuffix"
 if test "$mingw32" = "no" ; then
-echo "Manual directory  $mandir"
+echo "Manual directory  $prefix$mansuffix"
 echo "ELF interp prefix $interp_prefix"
 fi
 echo "Source path       $source_path"
@@ -613,6 +680,9 @@
     fmod_support=""
 fi
 echo "FMOD support      $fmod $fmod_support"
+if test -n "$sparc_cpu"; then
+    echo "Target Sparc Arch $sparc_cpu"
+fi
 echo "kqemu support     $kqemu"
 echo "Documentation     $build_docs"
 [ ! -z "$uname_release" ] && \
@@ -634,21 +704,21 @@
 echo "/* Automatically generated by configure - do not modify */" > $config_h
 
 echo "prefix=$prefix" >> $config_mak
-echo "bindir=$bindir" >> $config_mak
-echo "mandir=$mandir" >> $config_mak
-echo "datadir=$datadir" >> $config_mak
-echo "docdir=$docdir" >> $config_mak
-echo "#define CONFIG_QEMU_SHAREDIR \"$datadir\"" >> $config_h
+echo "bindir=\${prefix}$binsuffix" >> $config_mak
+echo "mandir=\${prefix}$mansuffix" >> $config_mak
+echo "datadir=\${prefix}$datasuffix" >> $config_mak
+echo "docdir=\${prefix}$docsuffix" >> $config_mak
+echo "#define CONFIG_QEMU_SHAREDIR \"$prefix$datasuffix\"" >> $config_h
 echo "MAKE=$make" >> $config_mak
 echo "INSTALL=$install" >> $config_mak
 echo "CC=$cc" >> $config_mak
-if test "$have_gcc3_options" = "yes" ; then
-  echo "HAVE_GCC3_OPTIONS=yes" >> $config_mak
-fi
 echo "HOST_CC=$host_cc" >> $config_mak
 echo "AR=$ar" >> $config_mak
 echo "STRIP=$strip -s -R .comment -R .note" >> $config_mak
 echo "OS_CFLAGS=$OS_CFLAGS" >> $config_mak
+echo "OS_LDFLAGS=$OS_LDFLAGS" >> $config_mak
+echo "ARCH_CFLAGS=$ARCH_CFLAGS" >> $config_mak
+echo "ARCH_LDFLAGS=$ARCH_LDFLAGS" >> $config_mak
 echo "CFLAGS=$CFLAGS" >> $config_mak
 echo "LDFLAGS=$LDFLAGS" >> $config_mak
 echo "EXESUF=$EXESUF" >> $config_mak
@@ -671,6 +741,9 @@
 elif test "$cpu" = "mips" ; then
   echo "ARCH=mips" >> $config_mak
   echo "#define HOST_MIPS 1" >> $config_h
+elif test "$cpu" = "mips64" ; then
+  echo "ARCH=mips64" >> $config_mak
+  echo "#define HOST_MIPS64 1" >> $config_h
 elif test "$cpu" = "s390" ; then
   echo "ARCH=s390" >> $config_mak
   echo "#define HOST_S390 1" >> $config_h
@@ -690,7 +763,7 @@
   echo "ARCH=m68k" >> $config_mak
   echo "#define HOST_M68K 1" >> $config_h
 else
-  echo "Unsupported CPU"
+  echo "Unsupported CPU = $cpu"
   exit 1
 fi
 if test "$bigendian" = "yes" ; then
@@ -701,8 +774,14 @@
 if test "$mingw32" = "yes" ; then
   echo "CONFIG_WIN32=yes" >> $config_mak
   echo "#define CONFIG_WIN32 1" >> $config_h
-elif test -f "/usr/include/byteswap.h" ; then
-  echo "#define HAVE_BYTESWAP_H 1" >> $config_h
+else
+  cat > $TMPC << EOF
+#include <byteswap.h>
+int main(void) { return bswap_32(0); }
+EOF
+  if $cc -o $TMPE $TMPC 2> /dev/null ; then
+    echo "#define HAVE_BYTESWAP_H 1" >> $config_h
+  fi
 fi
 if test "$darwin" = "yes" ; then
   echo "CONFIG_DARWIN=yes" >> $config_mak
@@ -711,7 +790,15 @@
 if test "$solaris" = "yes" ; then
   echo "CONFIG_SOLARIS=yes" >> $config_mak
   echo "#define HOST_SOLARIS $solarisrev" >> $config_h
+  if test "$needs_libsunmath" = "yes" ; then
+    echo "NEEDS_LIBSUNMATH=yes" >> $config_mak
+    echo "#define NEEDS_LIBSUNMATH 1" >> $config_h
+  fi
 fi
+if test -n "$sparc_cpu"; then
+  echo "CONFIG__sparc_${sparc_cpu}__=yes" >> $config_mak
+  echo "#define __sparc_${sparc_cpu}__ 1" >> $config_h
+fi
 if test "$gdbstub" = "yes" ; then
   echo "CONFIG_GDBSTUB=yes" >> $config_mak
   echo "#define CONFIG_GDBSTUB 1" >> $config_h
@@ -795,7 +882,9 @@
 [ "$target_cpu" = "sparc64" ] && target_bigendian=yes
 [ "$target_cpu" = "ppc" ] && target_bigendian=yes
 [ "$target_cpu" = "ppc64" ] && target_bigendian=yes
+[ "$target_cpu" = "ppcemb" ] && target_bigendian=yes
 [ "$target_cpu" = "mips" ] && target_bigendian=yes
+[ "$target_cpu" = "mips64" ] && target_bigendian=yes
 [ "$target_cpu" = "sh4eb" ] && target_bigendian=yes
 [ "$target_cpu" = "m68k" ] && target_bigendian=yes
 target_softmmu="no"
@@ -807,6 +896,16 @@
   target_user_only="yes"
 fi
 
+target_linux_user="no"
+if expr $target : '.*-linux-user' > /dev/null ; then
+  target_linux_user="yes"
+fi
+
+target_darwin_user="no"
+if expr $target : '.*-darwin-user' > /dev/null ; then
+  target_darwin_user="yes"
+fi
+
 if test "$target_user_only" = "no" -a "$check_gfx" = "yes" \
         -a "$sdl" = "no" -a "$cocoa" = "no" ; then
     echo "ERROR: QEMU requires SDL or Cocoa for graphical output"
@@ -819,7 +918,7 @@
 
 mkdir -p $target_dir
 mkdir -p $target_dir/fpu
-if test "$target" = "arm-user" -o "$target" = "armeb-user" ; then
+if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" ; then
   mkdir -p $target_dir/nwfpe
 fi
 if test "$target_user_only" = "no" ; then
@@ -874,6 +973,11 @@
   echo "#define TARGET_ARCH \"ppc64\"" >> $config_h
   echo "#define TARGET_PPC 1" >> $config_h
   echo "#define TARGET_PPC64 1" >> $config_h
+elif test "$target_cpu" = "ppcemb" ; then
+  echo "TARGET_ARCH=ppcemb" >> $config_mak
+  echo "#define TARGET_ARCH \"ppcemb\"" >> $config_h
+  echo "#define TARGET_PPC 1" >> $config_h
+  echo "#define TARGET_PPCEMB 1" >> $config_h
 elif test "$target_cpu" = "x86_64" ; then
   echo "TARGET_ARCH=x86_64" >> $config_mak
   echo "#define TARGET_ARCH \"x86_64\"" >> $config_h
@@ -888,6 +992,13 @@
   echo "#define TARGET_MIPS 1" >> $config_h
   echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
   echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
+elif test "$target_cpu" = "mips64" -o "$target_cpu" = "mips64el" ; then
+  echo "TARGET_ARCH=mips64" >> $config_mak
+  echo "#define TARGET_ARCH \"mips64\"" >> $config_h
+  echo "#define TARGET_MIPS 1" >> $config_h
+  echo "#define TARGET_MIPS64 1" >> $config_h
+  echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
+  echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
 elif test "$target_cpu" = "sh4" -o "$target_cpu" = "sh4eb" ; then
   echo "TARGET_ARCH=sh4" >> $config_mak
   echo "#define TARGET_ARCH \"sh4\"" >> $config_h
@@ -898,6 +1009,10 @@
   echo "#define TARGET_ARCH \"m68k\"" >> $config_h
   echo "#define TARGET_M68K 1" >> $config_h
   bflt="yes"
+elif test "$target_cpu" = "alpha" ; then
+  echo "TARGET_ARCH=alpha" >> $config_mak
+  echo "#define TARGET_ARCH \"alpha\"" >> $config_h
+  echo "#define TARGET_ALPHA 1" >> $config_h
 else
   echo "Unsupported target CPU"
   exit 1
@@ -914,6 +1029,14 @@
   echo "CONFIG_USER_ONLY=yes" >> $config_mak
   echo "#define CONFIG_USER_ONLY 1" >> $config_h
 fi
+if test "$target_linux_user" = "yes" ; then
+  echo "CONFIG_LINUX_USER=yes" >> $config_mak
+  echo "#define CONFIG_LINUX_USER 1" >> $config_h
+fi
+if test "$target_darwin_user" = "yes" ; then
+  echo "CONFIG_DARWIN_USER=yes" >> $config_mak
+  echo "#define CONFIG_DARWIN_USER 1" >> $config_h
+fi
 
 if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64" -o "$target_cpu" = "m68k"; then
   echo "CONFIG_SOFTFLOAT=yes" >> $config_mak

Modified: trunk/src/host/qemu-neo1973/console.c
===================================================================
--- trunk/src/host/qemu-neo1973/console.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/console.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -121,6 +121,7 @@
     int total_height;
     int backscroll_height;
     int x, y;
+    int x_saved, y_saved;
     int y_displayed;
     int y_base;
     TextAttributes t_attrib_default; /* default text attributes */
@@ -131,10 +132,7 @@
     int esc_params[MAX_ESC_PARAMS];
     int nb_esc_params;
 
-    /* kbd read handler */
-    IOCanRWHandler *fd_can_read; 
-    IOReadHandler *fd_read;
-    void *fd_opaque;
+    CharDriverState *chr;
     /* fifo for key pressed */
     QEMUFIFO out_fifo;
     uint8_t out_fifo_buf[16];
@@ -147,7 +145,7 @@
 
 void vga_hw_update(void)
 {
-    if (active_console->hw_update)
+    if (active_console && active_console->hw_update)
         active_console->hw_update(active_console->hw);
 }
 
@@ -535,21 +533,24 @@
     int y, y1;
 
     if (s == active_console) {
+        int x = s->x;
+        if (x >= s->width) {
+            x = s->width - 1;
+        }
         y1 = (s->y_base + s->y) % s->total_height;
         y = y1 - s->y_displayed;
         if (y < 0)
             y += s->total_height;
         if (y < s->height) {
-            c = &s->cells[y1 * s->width + s->x];
+            c = &s->cells[y1 * s->width + x];
             if (show) {
                 TextAttributes t_attrib = s->t_attrib_default;
                 t_attrib.invers = !(t_attrib.invers); /* invert fg and bg */
-                vga_putcharxy(s->ds, s->x, y, c->ch, &t_attrib);
+                vga_putcharxy(s->ds, x, y, c->ch, &t_attrib);
             } else {
-                vga_putcharxy(s->ds, s->x, y, c->ch, 
-                              &(c->t_attrib));
+                vga_putcharxy(s->ds, x, y, c->ch, &(c->t_attrib));
             }
-            dpy_update(s->ds, s->x * FONT_WIDTH, y * FONT_HEIGHT, 
+            dpy_update(s->ds, x * FONT_WIDTH, y * FONT_HEIGHT, 
                        FONT_WIDTH, FONT_HEIGHT);
         }
     }
@@ -659,10 +660,6 @@
 {
     int i;
 
-    if (s->nb_esc_params == 0) { /* ESC[m sets all attributes to default */
-        s->t_attrib = s->t_attrib_default;
-        return;
-    }
     for (i=0; i<s->nb_esc_params; i++) {
         switch (s->esc_params[i]) {
             case 0: /* reset all console attributes to default */
@@ -752,10 +749,21 @@
     }
 }
 
+static void console_clear_xy(TextConsole *s, int x, int y)
+{
+    int y1 = (s->y_base + y) % s->total_height;
+    TextCell *c = &s->cells[y1 * s->width + x];
+    c->ch = ' ';
+    c->t_attrib = s->t_attrib_default;
+    c++;
+    update_xy(s, x, y);
+}
+
 static void console_putchar(TextConsole *s, int ch)
 {
     TextCell *c;
-    int y1, i, x;
+    int y1, i;
+    int x, y;
 
     switch(s->state) {
     case TTY_STATE_NORM:
@@ -781,20 +789,27 @@
         case '\a':  /* alert aka. bell */
             /* TODO: has to be implemented */
             break;
+        case 14:
+            /* SI (shift in), character set 0 (ignored) */
+            break;
+        case 15:
+            /* SO (shift out), character set 1 (ignored) */
+            break;
         case 27:    /* esc (introducing an escape sequence) */
             s->state = TTY_STATE_ESC;
             break;
         default:
+            if (s->x >= s->width) {
+                /* line wrap */
+                s->x = 0;
+                console_put_lf(s);
+            }
             y1 = (s->y_base + s->y) % s->total_height;
             c = &s->cells[y1 * s->width + s->x];
             c->ch = ch;
             c->t_attrib = s->t_attrib;
             update_xy(s, s->x, s->y);
             s->x++;
-            if (s->x >= s->width) {
-                s->x = 0;
-                console_put_lf(s);
-            }
             break;
         }
         break;
@@ -818,32 +833,150 @@
             s->nb_esc_params++;
             if (ch == ';')
                 break;
+#ifdef DEBUG_CONSOLE
+            fprintf(stderr, "escape sequence CSI%d;%d%c, %d parameters\n",
+                    s->esc_params[0], s->esc_params[1], ch, s->nb_esc_params);
+#endif
             s->state = TTY_STATE_NORM;
             switch(ch) {
-            case 'D':
-                if (s->x > 0)
-                    s->x--;
+            case 'A':
+                /* move cursor up */
+                if (s->esc_params[0] == 0) {
+                    s->esc_params[0] = 1;
+                }
+                s->y -= s->esc_params[0];
+                if (s->y < 0) {
+                    s->y = 0;
+                }
                 break;
+            case 'B':
+                /* move cursor down */
+                if (s->esc_params[0] == 0) {
+                    s->esc_params[0] = 1;
+                }
+                s->y += s->esc_params[0];
+                if (s->y >= s->height) {
+                    s->y = s->height - 1;
+                }
+                break;
             case 'C':
-                if (s->x < (s->width - 1))
-                    s->x++;
+                /* move cursor right */
+                if (s->esc_params[0] == 0) {
+                    s->esc_params[0] = 1;
+                }
+                s->x += s->esc_params[0];
+                if (s->x >= s->width) {
+                    s->x = s->width - 1;
+                }
                 break;
+            case 'D':
+                /* move cursor left */
+                if (s->esc_params[0] == 0) {
+                    s->esc_params[0] = 1;
+                }
+                s->x -= s->esc_params[0];
+                if (s->x < 0) {
+                    s->x = 0;
+                }
+                break;
+            case 'G':
+                /* move cursor to column */
+                s->x = s->esc_params[0] - 1;
+                if (s->x < 0) {
+                    s->x = 0;
+                }
+                break;
+            case 'f':
+            case 'H':
+                /* move cursor to row, column */
+                s->x = s->esc_params[1] - 1;
+                if (s->x < 0) {
+                    s->x = 0;
+                }
+                s->y = s->esc_params[0] - 1;
+                if (s->y < 0) {
+                    s->y = 0;
+                }
+                break;
+            case 'J':
+                switch (s->esc_params[0]) {
+                case 0:
+                    /* clear to end of screen */
+                    for (y = s->y; y < s->height; y++) {
+                        for (x = 0; x < s->width; x++) {
+                            if (y == s->y && x < s->x) {
+                                continue;
+                            }
+                            console_clear_xy(s, x, y);
+                        }
+                    }
+                    break;
+                case 1:
+                    /* clear from beginning of screen */
+                    for (y = 0; y <= s->y; y++) {
+                        for (x = 0; x < s->width; x++) {
+                            if (y == s->y && x > s->x) {
+                                break;
+                            }
+                            console_clear_xy(s, x, y);
+                        }
+                    }
+                    break;
+                case 2:
+                    /* clear entire screen */
+                    for (y = 0; y <= s->height; y++) {
+                        for (x = 0; x < s->width; x++) {
+                            console_clear_xy(s, x, y);
+                        }
+                    }
+                break;
+                }
             case 'K':
+                switch (s->esc_params[0]) {
+                case 0:
                 /* clear to eol */
-                y1 = (s->y_base + s->y) % s->total_height;
                 for(x = s->x; x < s->width; x++) {
-                    c = &s->cells[y1 * s->width + x];
-                    c->ch = ' ';
-                    c->t_attrib = s->t_attrib_default;
-                    c++;
-                    update_xy(s, x, s->y);
+                        console_clear_xy(s, x, s->y);
                 }
                 break;
-            default:
+                case 1:
+                    /* clear from beginning of line */
+                    for (x = 0; x <= s->x; x++) {
+                        console_clear_xy(s, x, s->y);
+                    }
+                    break;
+                case 2:
+                    /* clear entire line */
+                    for(x = 0; x < s->width; x++) {
+                        console_clear_xy(s, x, s->y);
+                    }
                 break;
             }
+                break;
+            case 'm':
             console_handle_escape(s);
             break;
+            case 'n':
+                /* report cursor position */
+                /* TODO: send ESC[row;colR */
+                break;
+            case 's':
+                /* save cursor position */
+                s->x_saved = s->x;
+                s->y_saved = s->y;
+                break;
+            case 'u':
+                /* restore cursor position */
+                s->x = s->x_saved;
+                s->y = s->y_saved;
+                break;
+            default:
+#ifdef DEBUG_CONSOLE
+                fprintf(stderr, "unhandled escape character '%c'\n", ch);
+#endif
+                break;
+            }
+            break;
         }
     }
 }
@@ -884,16 +1017,6 @@
     return len;
 }
 
-static void console_chr_add_read_handler(CharDriverState *chr, 
-                                         IOCanRWHandler *fd_can_read, 
-                                         IOReadHandler *fd_read, void *opaque)
-{
-    TextConsole *s = chr->opaque;
-    s->fd_can_read = fd_can_read;
-    s->fd_read = fd_read;
-    s->fd_opaque = opaque;
-}
-
 static void console_send_event(CharDriverState *chr, int event)
 {
     TextConsole *s = chr->opaque;
@@ -915,14 +1038,14 @@
     int len;
     uint8_t buf[16];
     
-    len = s->fd_can_read(s->fd_opaque);
+    len = qemu_chr_can_read(s->chr);
     if (len > s->out_fifo.count)
         len = s->out_fifo.count;
     if (len > 0) {
         if (len > sizeof(buf))
             len = sizeof(buf);
         qemu_fifo_read(&s->out_fifo, buf, len);
-        s->fd_read(s->fd_opaque, buf, len);
+        qemu_chr_read(s->chr, buf, len);
     }
     /* characters are pending: we send them a bit later (XXX:
        horrible, should change char device API) */
@@ -973,7 +1096,7 @@
         } else {
                 *q++ = keysym;
         }
-        if (s->fd_read) {
+        if (s->chr->chr_read) {
             qemu_fifo_write(&s->out_fifo, buf, q - buf);
             kbd_send_chars(s);
         }
@@ -1049,9 +1172,9 @@
     }
     chr->opaque = s;
     chr->chr_write = console_puts;
-    chr->chr_add_read_handler = console_chr_add_read_handler;
     chr->chr_send_event = console_send_event;
 
+    s->chr = chr;
     s->out_fifo.buf = s->out_fifo_buf;
     s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
     s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s);

Modified: trunk/src/host/qemu-neo1973/cpu-all.h
===================================================================
--- trunk/src/host/qemu-neo1973/cpu-all.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/cpu-all.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -20,7 +20,7 @@
 #ifndef CPU_ALL_H
 #define CPU_ALL_H
 
-#if defined(__arm__) || defined(__sparc__)
+#if defined(__arm__) || defined(__sparc__) || defined(__mips__)
 #define WORDS_ALIGNED
 #endif
 
@@ -644,12 +644,14 @@
 #define lduw_code(p) lduw_raw(p)
 #define ldsw_code(p) ldsw_raw(p)
 #define ldl_code(p) ldl_raw(p)
+#define ldq_code(p) ldq_raw(p)
 
 #define ldub_kernel(p) ldub_raw(p)
 #define ldsb_kernel(p) ldsb_raw(p)
 #define lduw_kernel(p) lduw_raw(p)
 #define ldsw_kernel(p) ldsw_raw(p)
 #define ldl_kernel(p) ldl_raw(p)
+#define ldq_kernel(p) ldq_raw(p)
 #define ldfl_kernel(p) ldfl_raw(p)
 #define ldfq_kernel(p) ldfq_raw(p)
 #define stb_kernel(p, v) stb_raw(p, v)
@@ -746,6 +748,13 @@
 #define cpu_gen_code cpu_sh4_gen_code
 #define cpu_signal_handler cpu_sh4_signal_handler
 
+#elif defined(TARGET_ALPHA)
+#define CPUState CPUAlphaState
+#define cpu_init cpu_alpha_init
+#define cpu_exec cpu_alpha_exec
+#define cpu_gen_code cpu_alpha_gen_code
+#define cpu_signal_handler cpu_alpha_signal_handler
+
 #else
 
 #error unsupported target CPU
@@ -754,11 +763,17 @@
 
 #endif /* SINGLE_CPU_DEFINES */
 
+CPUState *cpu_copy(CPUState *env);
+
 void cpu_dump_state(CPUState *env, FILE *f, 
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags);
+void cpu_dump_statistics (CPUState *env, FILE *f,
+                          int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+                          int flags);
 
-void cpu_abort(CPUState *env, const char *fmt, ...);
+void cpu_abort(CPUState *env, const char *fmt, ...)
+    __attribute__ ((__format__ (__printf__, 2, 3)));
 extern CPUState *first_cpu;
 extern CPUState *cpu_single_env;
 extern int code_copy_enabled;
@@ -770,10 +785,13 @@
 #define CPU_INTERRUPT_FIQ    0x10 /* Fast interrupt pending.  */
 #define CPU_INTERRUPT_HALT   0x20 /* CPU halt wanted */
 #define CPU_INTERRUPT_SMI    0x40 /* (x86 only) SMI interrupt pending */
+#define CPU_INTERRUPT_DEBUG  0x80 /* Debug event occured.  */
 
 void cpu_interrupt(CPUState *s, int mask);
 void cpu_reset_interrupt(CPUState *env, int mask);
 
+int cpu_watchpoint_insert(CPUState *env, target_ulong addr);
+int cpu_watchpoint_remove(CPUState *env, target_ulong addr);
 int cpu_breakpoint_insert(CPUState *env, target_ulong pc);
 int cpu_breakpoint_remove(CPUState *env, target_ulong pc);
 void cpu_single_step(CPUState *env, int enabled);
@@ -782,7 +800,7 @@
 /* Return the physical page corresponding to a virtual one. Use it
    only for debugging because no protection checks are done. Return -1
    if no page found. */
-target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
+target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
 
 #define CPU_LOG_TB_OUT_ASM (1 << 0) 
 #define CPU_LOG_TB_IN_ASM  (1 << 1)
@@ -848,6 +866,8 @@
                                   unsigned long size,
                                   unsigned long phys_offset);
 uint32_t cpu_get_physical_page_desc(target_phys_addr_t addr);
+ram_addr_t qemu_ram_alloc(unsigned int size);
+void qemu_ram_free(ram_addr_t addr);
 int cpu_register_io_memory(int io_index,
                            CPUReadMemoryFunc **mem_read,
                            CPUWriteMemoryFunc **mem_write,
@@ -872,6 +892,7 @@
 uint32_t ldl_phys(target_phys_addr_t addr);
 uint64_t ldq_phys(target_phys_addr_t addr);
 void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val);
+void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val);
 void stb_phys(target_phys_addr_t addr, uint32_t val);
 void stw_phys(target_phys_addr_t addr, uint32_t val);
 void stl_phys(target_phys_addr_t addr, uint32_t val);
@@ -980,7 +1001,7 @@
     return val;
 }
 
-#elif defined(__sparc_v9__)
+#elif defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__)
 
 static inline int64_t cpu_get_real_ticks (void)
 {
@@ -1001,10 +1022,31 @@
         return rval.i64;
 #endif
 }
+
+#elif defined(__mips__)
+
+static inline int64_t cpu_get_real_ticks(void)
+{
+#if __mips_isa_rev >= 2
+    uint32_t count;
+    static uint32_t cyc_per_count = 0;
+
+    if (!cyc_per_count)
+        __asm__ __volatile__("rdhwr %0, $3" : "=r" (cyc_per_count));
+
+    __asm__ __volatile__("rdhwr %1, $2" : "=r" (count));
+    return (int64_t)(count * cyc_per_count);
 #else
+    /* FIXME */
+    static int64_t ticks = 0;
+    return ticks++;
+#endif
+}
+
+#else
 /* The host CPU doesn't have an easily accessible cycle counter.
-   Just return a monotonically increasing vlue.  This will be totally wrong,
-   but hopefully better than nothing.  */
+   Just return a monotonically increasing value.  This will be
+   totally wrong, but hopefully better than nothing.  */
 static inline int64_t cpu_get_real_ticks (void)
 {
     static int64_t ticks = 0;

Modified: trunk/src/host/qemu-neo1973/cpu-defs.h
===================================================================
--- trunk/src/host/qemu-neo1973/cpu-defs.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/cpu-defs.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -44,10 +44,12 @@
 typedef int32_t target_long;
 typedef uint32_t target_ulong;
 #define TARGET_FMT_lx "%08x"
+#define TARGET_FMT_ld "%d"
 #elif TARGET_LONG_SIZE == 8
 typedef int64_t target_long;
 typedef uint64_t target_ulong;
 #define TARGET_FMT_lx "%016" PRIx64
+#define TARGET_FMT_ld "%" PRId64
 #else
 #error TARGET_LONG_SIZE undefined
 #endif
@@ -60,8 +62,10 @@
 
 #if TARGET_PHYS_ADDR_BITS == 32
 typedef uint32_t target_phys_addr_t;
+#define TARGET_FMT_plx "%08x"
 #elif TARGET_PHYS_ADDR_BITS == 64
 typedef uint64_t target_phys_addr_t;
+#define TARGET_FMT_plx "%016" PRIx64
 #else
 #error TARGET_PHYS_ADDR_BITS undefined
 #endif
@@ -76,6 +80,7 @@
 #define EXCP_DEBUG      0x10002 /* cpu stopped after a breakpoint or singlestep */
 #define EXCP_HALTED     0x10003 /* cpu is halted (waiting for external event) */
 #define MAX_BREAKPOINTS 32
+#define MAX_WATCHPOINTS 32
 
 #define TB_JMP_CACHE_BITS 12
 #define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
@@ -105,6 +110,15 @@
     target_phys_addr_t addend; 
 } CPUTLBEntry;
 
+/* Alpha has 4 different running levels */
+#if defined(TARGET_ALPHA)
+#define NB_MMU_MODES 4
+#elif defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+#define NB_MMU_MODES 3
+#else
+#define NB_MMU_MODES 2
+#endif
+
 #define CPU_COMMON                                                      \
     struct TranslationBlock *current_tb; /* currently executing TB  */  \
     /* soft mmu support */                                              \
@@ -116,7 +130,7 @@
     target_ulong mem_write_vaddr; /* target virtual addr at which the   \
                                      memory was written */              \
     /* 0 = kernel, 1 = user */                                          \
-    CPUTLBEntry tlb_table[2][CPU_TLB_SIZE];                             \
+    CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE];                  \
     struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE];           \
                                                                         \
     /* from this point: preserved by CPU reset */                       \
@@ -125,6 +139,13 @@
     int nb_breakpoints;                                                 \
     int singlestep_enabled;                                             \
                                                                         \
+    struct {                                                            \
+        target_ulong vaddr;                                             \
+        int is_ram;                                                     \
+    } watchpoint[MAX_WATCHPOINTS];                                      \
+    int nb_watchpoints;                                                 \
+    int watchpoint_hit;                                                 \
+                                                                        \
     void *next_cpu; /* next CPU sharing TB cache */                     \
     int cpu_index; /* CPU index (informative) */                        \
     /* user data */                                                     \

Modified: trunk/src/host/qemu-neo1973/cpu-exec.c
===================================================================
--- trunk/src/host/qemu-neo1973/cpu-exec.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/cpu-exec.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -40,7 +40,8 @@
 //#define DEBUG_EXEC
 //#define DEBUG_SIGNAL
 
-#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_M68K)
+#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_M68K) || \
+    defined(TARGET_ALPHA)
 /* XXX: unify with i386 target */
 void cpu_loop_exit(void)
 {
@@ -202,6 +203,10 @@
     flags = env->sr & (SR_MD | SR_RB);
     cs_base = 0;         /* XXXXX */
     pc = env->pc;
+#elif defined(TARGET_ALPHA)
+    flags = env->ps;
+    cs_base = 0;
+    pc = env->pc;
 #else
 #error unsupported CPU
 #endif
@@ -226,43 +231,16 @@
 
 int cpu_exec(CPUState *env1)
 {
-    int saved_T0, saved_T1;
-#if defined(reg_T2)
-    int saved_T2;
-#endif
-    CPUState *saved_env;
-#if defined(TARGET_I386)
-#ifdef reg_EAX
-    int saved_EAX;
-#endif
-#ifdef reg_ECX
-    int saved_ECX;
-#endif
-#ifdef reg_EDX
-    int saved_EDX;
-#endif
-#ifdef reg_EBX
-    int saved_EBX;
-#endif
-#ifdef reg_ESP
-    int saved_ESP;
-#endif
-#ifdef reg_EBP
-    int saved_EBP;
-#endif
-#ifdef reg_ESI
-    int saved_ESI;
-#endif
-#ifdef reg_EDI
-    int saved_EDI;
-#endif
-#elif defined(TARGET_SPARC)
+#define DECLARE_HOST_REGS 1
+#include "hostregs_helper.h"
+#if defined(TARGET_SPARC)
 #if defined(reg_REGWPTR)
     uint32_t *saved_regwptr;
 #endif
 #endif
 #if defined(__sparc__) && !defined(HOST_SOLARIS)
-    int saved_i7, tmp_T0;
+    int saved_i7;
+    target_ulong tmp_T0;
 #endif
     int ret, interrupt_request;
     void (*gen_func)(void);
@@ -283,8 +261,7 @@
 #elif defined(TARGET_PPC)
     if (env1->halted) {
         if (env1->msr[MSR_EE] && 
-            (env1->interrupt_request & 
-             (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER))) {
+            (env1->interrupt_request & CPU_INTERRUPT_HARD)) {
             env1->halted = 0;
         } else {
             return EXCP_HALTED;
@@ -302,7 +279,8 @@
 #elif defined(TARGET_ARM)
     if (env1->halted) {
         /* An interrupt wakes the CPU even if the I and F CPSR bits are
-           set.  */
+           set.  We use EXITTB to silently wake CPU without causing an
+           actual interrupt.  */
         if (env1->interrupt_request &
             (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB)) {
             env1->halted = 0;
@@ -319,49 +297,28 @@
             return EXCP_HALTED;
         }
     }
+#elif defined(TARGET_ALPHA)
+    if (env1->halted) {
+        if (env1->interrupt_request & CPU_INTERRUPT_HARD) {
+            env1->halted = 0;
+        } else {
+            return EXCP_HALTED;
+        }
+    }
 #endif
 
     cpu_single_env = env1; 
 
     /* first we save global registers */
-    saved_env = env;
+#define SAVE_HOST_REGS 1
+#include "hostregs_helper.h"
     env = env1;
-    saved_T0 = T0;
-    saved_T1 = T1;
-#if defined(reg_T2)
-    saved_T2 = T2;
-#endif
 #if defined(__sparc__) && !defined(HOST_SOLARIS)
     /* we also save i7 because longjmp may not restore it */
     asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
 #endif
 
 #if defined(TARGET_I386)
-#ifdef reg_EAX
-    saved_EAX = EAX;
-#endif
-#ifdef reg_ECX
-    saved_ECX = ECX;
-#endif
-#ifdef reg_EDX
-    saved_EDX = EDX;
-#endif
-#ifdef reg_EBX
-    saved_EBX = EBX;
-#endif
-#ifdef reg_ESP
-    saved_ESP = ESP;
-#endif
-#ifdef reg_EBP
-    saved_EBP = EBP;
-#endif
-#ifdef reg_ESI
-    saved_ESI = ESI;
-#endif
-#ifdef reg_EDI
-    saved_EDI = EDI;
-#endif
-
     env_to_regs();
     /* put eflags in CPU temporary format */
     CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
@@ -381,6 +338,8 @@
 #elif defined(TARGET_MIPS)
 #elif defined(TARGET_SH4)
     /* XXXXX */
+#elif defined(TARGET_ALPHA)
+    env_to_regs();
 #else
 #error unsupported target CPU
 #endif
@@ -417,6 +376,8 @@
                                  env->exception_is_int, 
                                  env->error_code, 
                                  env->exception_next_eip, 0);
+                    /* successfully delivered */
+                    env->old_exception = -1;
 #elif defined(TARGET_PPC)
                     do_interrupt(env);
 #elif defined(TARGET_MIPS)
@@ -427,6 +388,8 @@
                     do_interrupt(env);
 #elif defined(TARGET_SH4)
 		    do_interrupt(env);
+#elif defined(TARGET_ALPHA)
+                    do_interrupt(env);
 #endif
                 }
                 env->exception_index = -1;
@@ -465,6 +428,20 @@
 #endif	    
                 interrupt_request = env->interrupt_request;
                 if (__builtin_expect(interrupt_request, 0)) {
+                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
+                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
+                        env->exception_index = EXCP_DEBUG;
+                        cpu_loop_exit();
+                    }
+#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
+    defined(TARGET_PPC) || defined(TARGET_ALPHA)
+                    if (interrupt_request & CPU_INTERRUPT_HALT) {
+                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
+                        env->halted = 1;
+                        env->exception_index = EXCP_HLT;
+                        cpu_loop_exit();
+                    }
+#endif
 #if defined(TARGET_I386)
                     if ((interrupt_request & CPU_INTERRUPT_SMI) &&
                         !(env->hflags & HF_SMM_MASK)) {
@@ -499,43 +476,27 @@
                         cpu_ppc_reset(env);
                     }
 #endif
-                    if (msr_ee != 0) {
-                        if ((interrupt_request & CPU_INTERRUPT_HARD)) {
-			    /* Raise it */
-			    env->exception_index = EXCP_EXTERNAL;
-			    env->error_code = 0;
-                            do_interrupt(env);
+                    if (interrupt_request & CPU_INTERRUPT_HARD) {
+                        ppc_hw_interrupt(env);
+                        if (env->pending_interrupts == 0)
                             env->interrupt_request &= ~CPU_INTERRUPT_HARD;
 #if defined(__sparc__) && !defined(HOST_SOLARIS)
-                            tmp_T0 = 0;
+                        tmp_T0 = 0;
 #else
-                            T0 = 0;
+                        T0 = 0;
 #endif
-                        } else if ((interrupt_request & CPU_INTERRUPT_TIMER)) {
-                            /* Raise it */
-                            env->exception_index = EXCP_DECR;
-                            env->error_code = 0;
-                            do_interrupt(env);
-                            env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
-#if defined(__sparc__) && !defined(HOST_SOLARIS)
-                            tmp_T0 = 0;
-#else
-                            T0 = 0;
-#endif
-                        }
                     }
 #elif defined(TARGET_MIPS)
                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
+                        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
                         (env->CP0_Status & (1 << CP0St_IE)) &&
-                        (env->CP0_Status & env->CP0_Cause & 0x0000FF00) &&
-                        !(env->hflags & MIPS_HFLAG_EXL) &&
-                        !(env->hflags & MIPS_HFLAG_ERL) &&
+                        !(env->CP0_Status & (1 << CP0St_EXL)) &&
+                        !(env->CP0_Status & (1 << CP0St_ERL)) &&
                         !(env->hflags & MIPS_HFLAG_DM)) {
                         /* Raise it */
                         env->exception_index = EXCP_EXT_INTERRUPT;
                         env->error_code = 0;
                         do_interrupt(env);
-                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
 #if defined(__sparc__) && !defined(HOST_SOLARIS)
                         tmp_T0 = 0;
 #else
@@ -563,12 +524,7 @@
 		    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
 			//do_interrupt(0, 0, 0, 0, 0);
 			env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
-		    } else if (interrupt_request & CPU_INTERRUPT_HALT) {
-			env->interrupt_request &= ~CPU_INTERRUPT_HALT;
-			env->halted = 1;
-			env->exception_index = EXCP_HLT;
-			cpu_loop_exit();
-                    }
+		    }
 #elif defined(TARGET_ARM)
                     if (interrupt_request & CPU_INTERRUPT_FIQ
                         && !(env->uncached_cpsr & CPSR_F)) {
@@ -580,14 +536,12 @@
                         env->exception_index = EXCP_IRQ;
                         do_interrupt(env);
                     }
-                    if (interrupt_request & CPU_INTERRUPT_HALT) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
-                        env->halted = 1;
-                        env->exception_index = EXCP_HLT;
-                        cpu_loop_exit();
-                    }
 #elif defined(TARGET_SH4)
 		    /* XXXXX */
+#elif defined(TARGET_ALPHA)
+                    if (interrupt_request & CPU_INTERRUPT_HARD) {
+                        do_interrupt(env);
+                    }
 #endif
                    /* Don't use the cached interupt_request value,
                       do_interrupt may have updated the EXITTB flag. */
@@ -656,6 +610,8 @@
                     cpu_dump_state(env, logfile, fprintf, 0);
 #elif defined(TARGET_SH4)
 		    cpu_dump_state(env, logfile, fprintf, 0);
+#elif defined(TARGET_ALPHA)
+                    cpu_dump_state(env, logfile, fprintf, 0);
 #else
 #error unsupported target CPU 
 #endif
@@ -706,6 +662,7 @@
                                      : /* no outputs */
                                      : "r" (gen_func) 
                                      : "i0", "i1", "i2", "i3", "i4", "i5",
+                                       "o0", "o1", "o2", "o3", "o4", "o5",
                                        "l0", "l1", "l2", "l3", "l4", "l5",
                                        "l6", "l7");
 #elif defined(__arm__)
@@ -833,32 +790,6 @@
 #endif
     /* restore flags in standard format */
     env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
-
-    /* restore global registers */
-#ifdef reg_EAX
-    EAX = saved_EAX;
-#endif
-#ifdef reg_ECX
-    ECX = saved_ECX;
-#endif
-#ifdef reg_EDX
-    EDX = saved_EDX;
-#endif
-#ifdef reg_EBX
-    EBX = saved_EBX;
-#endif
-#ifdef reg_ESP
-    ESP = saved_ESP;
-#endif
-#ifdef reg_EBP
-    EBP = saved_EBP;
-#endif
-#ifdef reg_ESI
-    ESI = saved_ESI;
-#endif
-#ifdef reg_EDI
-    EDI = saved_EDI;
-#endif
 #elif defined(TARGET_ARM)
     /* XXX: Save/restore host fpu exception state?.  */
 #elif defined(TARGET_SPARC)
@@ -873,19 +804,18 @@
               | env->cc_dest | (env->cc_x << 4);
 #elif defined(TARGET_MIPS)
 #elif defined(TARGET_SH4)
+#elif defined(TARGET_ALPHA)
     /* XXXXX */
 #else
 #error unsupported target CPU
 #endif
+
+    /* restore global registers */
 #if defined(__sparc__) && !defined(HOST_SOLARIS)
     asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
 #endif
-    T0 = saved_T0;
-    T1 = saved_T1;
-#if defined(reg_T2)
-    T2 = saved_T2;
-#endif
-    env = saved_env;
+#include "hostregs_helper.h"
+
     /* fail safe : never use cpu_single_env outside cpu_exec() */
     cpu_single_env = NULL; 
     return ret;
@@ -1261,12 +1191,69 @@
     /* never comes here */
     return 1;
 }
+
+#elif defined (TARGET_ALPHA)
+static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
+                                    int is_write, sigset_t *old_set,
+                                    void *puc)
+{
+    TranslationBlock *tb;
+    int ret;
+    
+    if (cpu_single_env)
+        env = cpu_single_env; /* XXX: find a correct solution for multithread */
+#if defined(DEBUG_SIGNAL)
+    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
+           pc, address, is_write, *(unsigned long *)old_set);
+#endif
+    /* XXX: locking issue */
+    if (is_write && page_unprotect(h2g(address), pc, puc)) {
+        return 1;
+    }
+
+    /* see if it is an MMU fault */
+    ret = cpu_alpha_handle_mmu_fault(env, address, is_write, 1, 0);
+    if (ret < 0)
+        return 0; /* not an MMU fault */
+    if (ret == 0)
+        return 1; /* the MMU fault was handled without causing real CPU fault */
+
+    /* now we have a real cpu fault */
+    tb = tb_find_pc(pc);
+    if (tb) {
+        /* the PC is inside the translated code. It means that we have
+           a virtual CPU fault */
+        cpu_restore_state(tb, env, pc, puc);
+    }
+#if 0
+        printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
+               env->nip, env->error_code, tb);
+#endif
+    /* we restore the process signal mask as the sigreturn should
+       do it (XXX: use sigsetjmp) */
+    sigprocmask(SIG_SETMASK, old_set, NULL);
+    cpu_loop_exit();
+    /* never comes here */
+    return 1;
+}
 #else
 #error unsupported target CPU
 #endif
 
 #if defined(__i386__)
 
+#if defined(__APPLE__)
+# include <sys/ucontext.h>
+
+# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
+# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
+# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
+#else
+# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
+# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
+# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
+#endif
+
 #if defined(USE_CODE_COPY)
 static void cpu_send_trap(unsigned long pc, int trap, 
                           struct ucontext *uc)
@@ -1287,9 +1274,10 @@
 }
 #endif
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int trapno;
@@ -1300,8 +1288,8 @@
 #define REG_ERR    ERR
 #define REG_TRAPNO TRAPNO
 #endif
-    pc = uc->uc_mcontext.gregs[REG_EIP];
-    trapno = uc->uc_mcontext.gregs[REG_TRAPNO];
+    pc = EIP_sig(uc);
+    trapno = TRAP_sig(uc);
 #if defined(TARGET_I386) && defined(USE_CODE_COPY)
     if (trapno == 0x00 || trapno == 0x05) {
         /* send division by zero or bound exception */
@@ -1311,15 +1299,16 @@
 #endif
         return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
                                  trapno == 0xe ? 
-                                 (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
+                                 (ERROR_sig(uc) >> 1) & 1 : 0,
                                  &uc->uc_sigmask, puc);
 }
 
 #elif defined(__x86_64__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info,
+int cpu_signal_handler(int host_signum, void *pinfo,
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
 
@@ -1381,9 +1370,10 @@
 # define TRAP_sig(context)			EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
 #endif /* __APPLE__ */
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int is_write;
@@ -1404,9 +1394,10 @@
 
 #elif defined(__alpha__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                            void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     uint32_t *pc = uc->uc_mcontext.sc_pc;
     uint32_t insn = *pc;
@@ -1433,9 +1424,10 @@
 }
 #elif defined(__sparc__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     uint32_t *regs = (uint32_t *)(info + 1);
     void *sigmask = (regs + 20);
     unsigned long pc;
@@ -1466,9 +1458,10 @@
 
 #elif defined(__arm__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int is_write;
@@ -1483,9 +1476,10 @@
 
 #elif defined(__mc68000)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int is_write;
@@ -1505,8 +1499,9 @@
 # define __ISR_VALID	1
 #endif
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc)
+int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long ip;
     int is_write = 0;
@@ -1533,9 +1528,10 @@
 
 #elif defined(__s390__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int is_write;
@@ -1544,10 +1540,25 @@
     /* XXX: compute is_write */
     is_write = 0;
     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
-                             is_write,
-                             &uc->uc_sigmask, puc);
+                             is_write, &uc->uc_sigmask, puc);
 }
 
+#elif defined(__mips__)
+
+int cpu_signal_handler(int host_signum, void *pinfo, 
+                       void *puc)
+{
+    siginfo_t *info = pinfo;
+    struct ucontext *uc = puc;
+    greg_t pc = uc->uc_mcontext.pc;
+    int is_write;
+    
+    /* XXX: compute is_write */
+    is_write = 0;
+    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
+                             is_write, &uc->uc_sigmask, puc);
+}
+
 #else
 
 #error host CPU specific signal handler needed

Added: trunk/src/host/qemu-neo1973/darwin-user/commpage.c
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/commpage.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/commpage.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,358 @@
+ /*
+ *  Commpage syscalls
+ *
+ *  Copyright (c) 2006 Pierre d'Herbemont
+ *
+ *  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.
+ */
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <mach/message.h>
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <libkern/OSAtomic.h>
+
+#include "qemu.h"
+
+//#define DEBUG_COMMPAGE
+
+#ifdef DEBUG_COMMPAGE
+# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); printf(__VA_ARGS__); } while(0)
+#else
+# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); } while(0)
+#endif
+
+/********************************************************************
+ *   Commpage definitions
+ */
+#ifdef TARGET_I386
+/* Reserve space for the commpage see xnu/osfmk/i386/cpu_capabilities.h */
+# define COMMPAGE_START (-16 * 4096) /* base address is -20 * 4096 */
+# define COMMPAGE_SIZE  (0x1240) /* _COMM_PAGE_AREA_LENGTH is 19 * 4096 */
+#elif defined(TARGET_PPC)
+/* Reserve space for the commpage see xnu/osfmk/ppc/cpu_capabilities.h */
+# define COMMPAGE_START (-8*4096)
+# define COMMPAGE_SIZE  (2*4096) /* its _COMM_PAGE_AREA_USED but _COMM_PAGE_AREA_LENGTH is 7*4096 */
+#endif
+
+void do_compare_and_swap32(void *cpu_env, int num);
+void do_compare_and_swap64(void *cpu_env, int num);
+void do_add_atomic_word32(void *cpu_env, int num);
+void do_cgettimeofday(void *cpu_env, int num, uint32_t arg1);
+void do_nanotime(void *cpu_env, int num);
+
+void unimpl_commpage(void *cpu_env, int num);
+
+typedef void (*commpage_8args_function_t)(uint32_t arg1, uint32_t arg2, uint32_t arg3,
+                uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
+                uint32_t arg8);
+typedef void (*commpage_indirect_function_t)(void *cpu_env, int num, uint32_t arg1,
+                uint32_t arg2, uint32_t arg3,  uint32_t arg4, uint32_t arg5,
+                uint32_t arg6, uint32_t arg7, uint32_t arg8);
+
+#define HAS_PTR  0x10
+#define NO_PTR   0x20
+#define CALL_DIRECT   0x1
+#define CALL_INDIRECT 0x2
+
+#define COMMPAGE_ENTRY(name, nargs, offset, func, options) \
+    { #name, offset, nargs, options, (commpage_8args_function_t)func }
+
+struct commpage_entry {
+    char * name;
+    int offset;
+    int nargs;
+    char options;
+    commpage_8args_function_t function;
+};
+
+static inline int commpage_code_num(struct commpage_entry *entry)
+{
+    if((entry->options & HAS_PTR))
+        return entry->offset + 4;
+    else
+        return entry->offset;
+}
+
+static inline int commpage_is_indirect(struct commpage_entry *entry)
+{
+    return !(entry->options & CALL_DIRECT);
+}
+
+/********************************************************************
+ *   Commpage entry
+ */
+static struct commpage_entry commpage_entries[] =
+{
+    COMMPAGE_ENTRY(compare_and_swap32,    0, 0x080,  do_compare_and_swap32, CALL_INDIRECT | HAS_PTR),
+    COMMPAGE_ENTRY(compare_and_swap64,    0, 0x0c0,  do_compare_and_swap64, CALL_INDIRECT | HAS_PTR),
+    COMMPAGE_ENTRY(enqueue,               0, 0x100,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(dequeue,               0, 0x140,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(memory_barrier,        0, 0x180,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(add_atomic_word32,     0, 0x1a0,  do_add_atomic_word32,  CALL_INDIRECT | HAS_PTR),
+    COMMPAGE_ENTRY(add_atomic_word64,     0, 0x1c0,  unimpl_commpage,       CALL_INDIRECT | HAS_PTR),
+
+    COMMPAGE_ENTRY(mach_absolute_time,    0, 0x200,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(spinlock_try,          1, 0x220,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(spinlock_lock,         1, 0x260,  OSSpinLockLock,        CALL_DIRECT),
+    COMMPAGE_ENTRY(spinlock_unlock,       1, 0x2a0,  OSSpinLockUnlock,      CALL_DIRECT),
+    COMMPAGE_ENTRY(pthread_getspecific,   0, 0x2c0,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(gettimeofday,          1, 0x2e0,  do_cgettimeofday,      CALL_INDIRECT),
+    COMMPAGE_ENTRY(sys_dcache_flush,      0, 0x4e0,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(sys_icache_invalidate, 0, 0x520,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(pthread_self,          0, 0x580,  unimpl_commpage,       CALL_INDIRECT),
+
+    COMMPAGE_ENTRY(relinquish,            0, 0x5c0,  unimpl_commpage,       CALL_INDIRECT),
+
+#ifdef TARGET_I386
+    COMMPAGE_ENTRY(bts,                   0, 0x5e0,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(btc,                   0, 0x5f0,  unimpl_commpage,       CALL_INDIRECT),
+#endif
+
+    COMMPAGE_ENTRY(bzero,                 2, 0x600,  bzero,                 CALL_DIRECT),
+    COMMPAGE_ENTRY(bcopy,                 3, 0x780,  bcopy,                 CALL_DIRECT),
+    COMMPAGE_ENTRY(memcpy,                3, 0x7a0,  memcpy,                CALL_DIRECT),
+
+#ifdef TARGET_I386
+    COMMPAGE_ENTRY(old_nanotime,          0, 0xf80,  do_nanotime,           CALL_INDIRECT),
+    COMMPAGE_ENTRY(memset_pattern,        0, 0xf80,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(long_copy,             0, 0x1200, unimpl_commpage,       CALL_INDIRECT),
+
+    COMMPAGE_ENTRY(sysintegrity,          0, 0x1600, unimpl_commpage,       CALL_INDIRECT),
+
+    COMMPAGE_ENTRY(nanotime,              0, 0x1700, do_nanotime,           CALL_INDIRECT),
+#elif TARGET_PPC
+    COMMPAGE_ENTRY(compare_and_swap32b,   0, 0xf80,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(compare_and_swap64b,   0, 0xfc0,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(memset_pattern,        0, 0x1000, unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(bigcopy,               0, 0x1140, unimpl_commpage,       CALL_INDIRECT),
+#endif
+};
+
+
+/********************************************************************
+ *   Commpage backdoor
+ */
+static inline void print_commpage_entry(struct commpage_entry entry)
+{
+    printf("@0x%x %s\n", entry.offset, entry.name);
+}
+
+static inline void install_commpage_backdoor_for_entry(struct commpage_entry entry)
+{
+#ifdef TARGET_I386
+    char * commpage = (char*)(COMMPAGE_START+entry.offset);
+    int c = 0;
+    if(entry.options & HAS_PTR)
+    {
+        commpage[c++] = (COMMPAGE_START+entry.offset+4) & 0xff;
+        commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 8) & 0xff;
+        commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 16) & 0xff;
+        commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 24) & 0xff;
+    }
+    commpage[c++] = 0xcd;
+    commpage[c++] = 0x79; /* int 0x79 */
+    commpage[c++] = 0xc3; /* ret */
+#else
+    qerror("can't install the commpage on this arch\n");
+#endif
+}
+
+/********************************************************************
+ *   Commpage initialization
+ */
+void commpage_init(void)
+{
+#if (defined(__i386__) ^ defined(TARGET_I386)) || (defined(__powerpc__) ^ defined(TARGET_PPC))
+    int i;
+    void * commpage = (void *)target_mmap( COMMPAGE_START, COMMPAGE_SIZE,
+                           PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+    if((int)commpage != COMMPAGE_START)
+        qerror("can't allocate the commpage\n");
+
+    bzero(commpage, COMMPAGE_SIZE);
+
+    /* XXX: commpage data not handled */
+
+    for(i = 0; i < sizeof(commpage_entries)/sizeof(commpage_entries[0]); i++)
+        install_commpage_backdoor_for_entry(commpage_entries[i]);
+#else
+    /* simply map our pages so they can be executed
+       XXX: we don't really want to do that since in the ppc on ppc situation we may
+       not able to run commpages host optimized instructions (like G5's on a G5),
+       hence this is sometimes a broken fix. */
+    page_set_flags(COMMPAGE_START, COMMPAGE_START+COMMPAGE_SIZE, PROT_EXEC | PROT_READ | PAGE_VALID);
+#endif
+}
+
+/********************************************************************
+ *   Commpage implementation
+ */
+void do_compare_and_swap32(void *cpu_env, int num)
+{
+#ifdef TARGET_I386
+    uint32_t old = ((CPUX86State*)cpu_env)->regs[R_EAX];
+    uint32_t *value = (uint32_t*)((CPUX86State*)cpu_env)->regs[R_ECX];
+    DPRINTF("commpage: compare_and_swap32(%x,new,%p)\n", old, value);
+
+    if(value && old == tswap32(*value))
+    {
+        uint32_t new = ((CPUX86State*)cpu_env)->regs[R_EDX];
+        *value = tswap32(new);
+        /* set zf flag */
+        ((CPUX86State*)cpu_env)->eflags |= 0x40;
+    }
+    else
+    {
+        ((CPUX86State*)cpu_env)->regs[R_EAX] = tswap32(*value);
+        /* unset zf flag */
+        ((CPUX86State*)cpu_env)->eflags &= ~0x40;
+    }
+#else
+    qerror("do_compare_and_swap32 unimplemented");
+#endif
+}
+
+void do_compare_and_swap64(void *cpu_env, int num)
+{
+#ifdef TARGET_I386
+    /* OSAtomicCompareAndSwap64 is not available on non 64 bits ppc, here is a raw implementation */
+    uint64_t old, new, swapped_val;
+    uint64_t *value = (uint64_t*)((CPUX86State*)cpu_env)->regs[R_ESI];
+    old = (uint64_t)((uint64_t)((CPUX86State*)cpu_env)->regs[R_EDX]) << 32 | (uint64_t)((CPUX86State*)cpu_env)->regs[R_EAX];
+
+    DPRINTF("commpage: compare_and_swap64(%llx,new,%p)\n", old, value);
+    swapped_val = tswap64(*value);
+
+    if(old == swapped_val)
+    {
+        new = (uint64_t)((uint64_t)((CPUX86State*)cpu_env)->regs[R_ECX]) << 32 | (uint64_t)((CPUX86State*)cpu_env)->regs[R_EBX];
+        *value = tswap64(new);
+        /* set zf flag */
+        ((CPUX86State*)cpu_env)->eflags |= 0x40;
+    }
+    else
+    {
+        ((CPUX86State*)cpu_env)->regs[R_EAX] = (uint32_t)(swapped_val);
+        ((CPUX86State*)cpu_env)->regs[R_EDX] = (uint32_t)(swapped_val >> 32);
+        /* unset zf flag */
+        ((CPUX86State*)cpu_env)->eflags &= ~0x40;
+    }
+#else
+    qerror("do_compare_and_swap64 unimplemented");
+#endif
+}
+
+void do_add_atomic_word32(void *cpu_env, int num)
+{
+#ifdef TARGET_I386
+    uint32_t amt = ((CPUX86State*)cpu_env)->regs[R_EAX];
+    uint32_t *value = (uint32_t*)((CPUX86State*)cpu_env)->regs[R_EDX];
+    uint32_t swapped_value = tswap32(*value);
+
+    DPRINTF("commpage: add_atomic_word32(%x,%p)\n", amt, value);
+
+    /* old value in EAX */
+    ((CPUX86State*)cpu_env)->regs[R_EAX] = swapped_value;
+    *value = tswap32(swapped_value + amt);
+#else
+    qerror("do_add_atomic_word32 unimplemented");
+#endif
+}
+
+void do_cgettimeofday(void *cpu_env, int num, uint32_t arg1)
+{
+#ifdef TARGET_I386
+    extern int __commpage_gettimeofday(struct timeval *);
+    DPRINTF("commpage: gettimeofday(0x%x)\n", arg1);
+    struct timeval *time = (struct timeval *)arg1;
+    int ret = __commpage_gettimeofday(time);
+    tswap32s((uint32_t*)&time->tv_sec);
+    tswap32s((uint32_t*)&time->tv_usec);
+    ((CPUX86State*)cpu_env)->regs[R_EAX] = ret; /* Success */
+#else
+    qerror("do_gettimeofday unimplemented");
+#endif
+}
+
+void do_nanotime(void *cpu_env, int num)
+{
+#ifdef TARGET_I386
+    uint64_t t = mach_absolute_time();
+    ((CPUX86State*)cpu_env)->regs[R_EAX] = (int)(t & 0xffffffff);
+    ((CPUX86State*)cpu_env)->regs[R_EDX] = (int)((t >> 32) & 0xffffffff);
+#else
+    qerror("do_nanotime unimplemented");
+#endif
+}
+
+void unimpl_commpage(void *cpu_env, int num)
+{
+    qerror("qemu: commpage function 0x%x not implemented\n", num);
+}
+
+/********************************************************************
+ *   do_commpage - called by the main cpu loop
+ */
+void
+do_commpage(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
+                uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
+                uint32_t arg8)
+{
+    int i, found = 0;
+
+    arg1 = tswap32(arg1);
+    arg2 = tswap32(arg2);
+    arg3 = tswap32(arg3);
+    arg4 = tswap32(arg4);
+    arg5 = tswap32(arg5);
+    arg6 = tswap32(arg6);
+    arg7 = tswap32(arg7);
+    arg8 = tswap32(arg8);
+
+    num = num-COMMPAGE_START-2;
+
+    for(i = 0; i < sizeof(commpage_entries)/sizeof(commpage_entries[0]); i++) {
+        if( num == commpage_code_num(&commpage_entries[i]) )
+        {
+            DPRINTF("commpage: %s %s\n", commpage_entries[i].name, commpage_is_indirect(&commpage_entries[i]) ? "[indirect]" : "[direct]");
+            found = 1;
+            if(commpage_is_indirect(&commpage_entries[i]))
+            {
+                commpage_indirect_function_t function = (commpage_indirect_function_t)commpage_entries[i].function;
+                function(cpu_env, num, arg1, arg2, arg3,
+                    arg4, arg5, arg6, arg7, arg8);
+            }
+            else
+            {
+                commpage_entries[i].function(arg1, arg2, arg3,
+                    arg4, arg5, arg6, arg7, arg8);
+            }
+            break;
+        }
+    }
+
+    if(!found)
+    {
+        gemu_log("qemu: commpage function 0x%x not defined\n", num);
+        gdb_handlesig (cpu_env, SIGTRAP);
+        exit(-1);
+    }
+}

Added: trunk/src/host/qemu-neo1973/darwin-user/ioctls.h
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/ioctls.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/ioctls.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,4 @@
+     /* emulated ioctl list */
+
+     IOCTL(TIOCGETA, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
+     IOCTL(TIOCSETA, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))

Added: trunk/src/host/qemu-neo1973/darwin-user/ioctls_types.h
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/ioctls_types.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/ioctls_types.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1 @@
+STRUCT(termios, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, MK_ARRAY(TYPE_CHAR, 20), TYPE_INT, TYPE_INT)
\ No newline at end of file

Added: trunk/src/host/qemu-neo1973/darwin-user/machload.c
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/machload.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/machload.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,903 @@
+/*
+ *  Mach-O object file loading
+ *
+ *  Copyright (c) 2006 Pierre d'Herbemont
+ *
+ * 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
+ */
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "qemu.h"
+#include "disas.h"
+
+#include <mach-o/loader.h>
+#include <mach-o/fat.h>
+#include <mach-o/nlist.h>
+#include <mach-o/reloc.h>
+#include <mach-o/ppc/reloc.h>
+
+//#define DEBUG_MACHLOAD
+
+#ifdef DEBUG_MACHLOAD
+# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); printf(__VA_ARGS__); } while(0)
+#else
+# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); } while(0)
+#endif
+
+# define check_mach_header(x) (x.magic == MH_CIGAM)
+
+extern const char *interp_prefix;
+
+/* we don't have a good implementation for this */
+#define DONT_USE_DYLD_SHARED_MAP
+
+/* Pass extra arg to DYLD for debug */
+//#define ACTIVATE_DYLD_TRACE
+
+//#define OVERRIDE_DYLINKER
+
+#ifdef OVERRIDE_DYLINKER
+# ifdef TARGET_I386
+#  define DYLINKER_NAME "/Users/steg/qemu/tests/i386-darwin-env/usr/lib/dyld"
+# else
+#  define DYLINKER_NAME "/usr/lib/dyld"
+# endif
+#endif
+
+/* XXX: in an include */
+struct nlist_extended
+{
+    union {
+        char *n_name;
+        long  n_strx;
+    } n_un;
+    unsigned char n_type;
+    unsigned char n_sect;
+    short st_desc;
+    unsigned long st_value;
+    unsigned long st_size;
+};
+
+/* Print symbols in gdb */
+void *macho_text_sect = 0;
+int   macho_offset = 0;
+
+int load_object(const char *filename, struct target_pt_regs * regs, void ** mh);
+void qerror(const char *format, ...);
+#ifdef TARGET_I386
+typedef struct mach_i386_thread_state {
+    unsigned int    eax;
+    unsigned int    ebx;
+    unsigned int    ecx;
+    unsigned int    edx;
+    unsigned int    edi;
+    unsigned int    esi;
+    unsigned int    ebp;
+    unsigned int    esp;
+    unsigned int    ss;
+    unsigned int    eflags;
+    unsigned int    eip;
+    unsigned int    cs;
+    unsigned int    ds;
+    unsigned int    es;
+    unsigned int    fs;
+    unsigned int    gs;
+} mach_i386_thread_state_t;
+
+void bswap_i386_thread_state(struct mach_i386_thread_state *ts)
+{
+    bswap32s((uint32_t*)&ts->eax);
+    bswap32s((uint32_t*)&ts->ebx);
+    bswap32s((uint32_t*)&ts->ecx);
+    bswap32s((uint32_t*)&ts->edx);
+    bswap32s((uint32_t*)&ts->edi);
+    bswap32s((uint32_t*)&ts->esi);
+    bswap32s((uint32_t*)&ts->ebp);
+    bswap32s((uint32_t*)&ts->esp);
+    bswap32s((uint32_t*)&ts->ss);
+    bswap32s((uint32_t*)&ts->eflags);
+    bswap32s((uint32_t*)&ts->eip);
+    bswap32s((uint32_t*)&ts->cs);
+    bswap32s((uint32_t*)&ts->ds);
+    bswap32s((uint32_t*)&ts->es);
+    bswap32s((uint32_t*)&ts->fs);
+    bswap32s((uint32_t*)&ts->gs);
+}
+#define target_thread_state mach_i386_thread_state
+#define TARGET_CPU_TYPE CPU_TYPE_I386
+#define TARGET_CPU_NAME "i386"
+#endif
+
+#ifdef TARGET_PPC
+struct mach_ppc_thread_state {
+    unsigned int srr0;      /* Instruction address register (PC) */
+    unsigned int srr1;    /* Machine state register (supervisor) */
+    unsigned int r0;
+    unsigned int r1;
+    unsigned int r2;
+    unsigned int r3;
+    unsigned int r4;
+    unsigned int r5;
+    unsigned int r6;
+    unsigned int r7;
+    unsigned int r8;
+    unsigned int r9;
+    unsigned int r10;
+    unsigned int r11;
+    unsigned int r12;
+    unsigned int r13;
+    unsigned int r14;
+    unsigned int r15;
+    unsigned int r16;
+    unsigned int r17;
+    unsigned int r18;
+    unsigned int r19;
+    unsigned int r20;
+    unsigned int r21;
+    unsigned int r22;
+    unsigned int r23;
+    unsigned int r24;
+    unsigned int r25;
+    unsigned int r26;
+    unsigned int r27;
+    unsigned int r28;
+    unsigned int r29;
+    unsigned int r30;
+    unsigned int r31;
+
+    unsigned int cr;        /* Condition register */
+    unsigned int xer;    /* User's integer exception register */
+    unsigned int lr;    /* Link register */
+    unsigned int ctr;    /* Count register */
+    unsigned int mq;    /* MQ register (601 only) */
+
+    unsigned int vrsave;    /* Vector Save Register */
+};
+
+void bswap_ppc_thread_state(struct mach_ppc_thread_state *ts)
+{
+    bswap32s((uint32_t*)&ts->srr0);
+    bswap32s((uint32_t*)&ts->srr1);
+    bswap32s((uint32_t*)&ts->r0);
+    bswap32s((uint32_t*)&ts->r1);
+    bswap32s((uint32_t*)&ts->r2);
+    bswap32s((uint32_t*)&ts->r3);
+    bswap32s((uint32_t*)&ts->r4);
+    bswap32s((uint32_t*)&ts->r5);
+    bswap32s((uint32_t*)&ts->r6);
+    bswap32s((uint32_t*)&ts->r7);
+    bswap32s((uint32_t*)&ts->r8);
+    bswap32s((uint32_t*)&ts->r9);
+    bswap32s((uint32_t*)&ts->r10);
+    bswap32s((uint32_t*)&ts->r11);
+    bswap32s((uint32_t*)&ts->r12);
+    bswap32s((uint32_t*)&ts->r13);
+    bswap32s((uint32_t*)&ts->r14);
+    bswap32s((uint32_t*)&ts->r15);
+    bswap32s((uint32_t*)&ts->r16);
+    bswap32s((uint32_t*)&ts->r17);
+    bswap32s((uint32_t*)&ts->r18);
+    bswap32s((uint32_t*)&ts->r19);
+    bswap32s((uint32_t*)&ts->r20);
+    bswap32s((uint32_t*)&ts->r21);
+    bswap32s((uint32_t*)&ts->r22);
+    bswap32s((uint32_t*)&ts->r23);
+    bswap32s((uint32_t*)&ts->r24);
+    bswap32s((uint32_t*)&ts->r25);
+    bswap32s((uint32_t*)&ts->r26);
+    bswap32s((uint32_t*)&ts->r27);
+    bswap32s((uint32_t*)&ts->r28);
+    bswap32s((uint32_t*)&ts->r29);
+    bswap32s((uint32_t*)&ts->r30);
+    bswap32s((uint32_t*)&ts->r31);
+
+    bswap32s((uint32_t*)&ts->cr);
+    bswap32s((uint32_t*)&ts->xer);
+    bswap32s((uint32_t*)&ts->lr);
+    bswap32s((uint32_t*)&ts->ctr);
+    bswap32s((uint32_t*)&ts->mq);
+
+    bswap32s((uint32_t*)&ts->vrsave);
+}
+
+#define target_thread_state mach_ppc_thread_state
+#define TARGET_CPU_TYPE CPU_TYPE_POWERPC
+#define TARGET_CPU_NAME "PowerPC"
+#endif
+
+struct target_thread_command {
+    unsigned long    cmd;    /* LC_THREAD or  LC_UNIXTHREAD */
+    unsigned long    cmdsize;    /* total size of this command */
+    unsigned long flavor;    /* flavor of thread state */
+    unsigned long count;        /* count of longs in thread state */
+    struct target_thread_state state;  /* thread state for this flavor */
+};
+
+void bswap_tc(struct target_thread_command *tc)
+{
+    bswap32s((uint32_t*)(&tc->flavor));
+    bswap32s((uint32_t*)&tc->count);
+#if defined(TARGET_I386)
+    bswap_i386_thread_state(&tc->state);
+#elif defined(TARGET_PPC)
+    bswap_ppc_thread_state(&tc->state);
+#else
+# error unknown TARGET_CPU_TYPE
+#endif
+}
+
+void bswap_mh(struct mach_header *mh)
+{
+    bswap32s((uint32_t*)(&mh->magic));
+    bswap32s((uint32_t*)&mh->cputype);
+    bswap32s((uint32_t*)&mh->cpusubtype);
+    bswap32s((uint32_t*)&mh->filetype);
+    bswap32s((uint32_t*)&mh->ncmds);
+    bswap32s((uint32_t*)&mh->sizeofcmds);
+    bswap32s((uint32_t*)&mh->flags);
+}
+
+void bswap_lc(struct load_command *lc)
+{
+    bswap32s((uint32_t*)&lc->cmd);
+    bswap32s((uint32_t*)&lc->cmdsize);
+}
+
+
+void bswap_fh(struct fat_header *fh)
+{
+    bswap32s((uint32_t*)&fh->magic);
+    bswap32s((uint32_t*)&fh->nfat_arch);
+}
+
+void bswap_fa(struct fat_arch *fa)
+{
+    bswap32s((uint32_t*)&fa->cputype);
+    bswap32s((uint32_t*)&fa->cpusubtype);
+    bswap32s((uint32_t*)&fa->offset);
+    bswap32s((uint32_t*)&fa->size);
+    bswap32s((uint32_t*)&fa->align);
+}
+
+void bswap_segcmd(struct segment_command *sc)
+{
+    bswap32s((uint32_t*)&sc->vmaddr);
+    bswap32s((uint32_t*)&sc->vmsize);
+    bswap32s((uint32_t*)&sc->fileoff);
+    bswap32s((uint32_t*)&sc->filesize);
+    bswap32s((uint32_t*)&sc->maxprot);
+    bswap32s((uint32_t*)&sc->initprot);
+    bswap32s((uint32_t*)&sc->nsects);
+    bswap32s((uint32_t*)&sc->flags);
+}
+
+void bswap_symtabcmd(struct symtab_command *stc)
+{
+    bswap32s((uint32_t*)&stc->cmd);
+    bswap32s((uint32_t*)&stc->cmdsize);
+    bswap32s((uint32_t*)&stc->symoff);
+    bswap32s((uint32_t*)&stc->nsyms);
+    bswap32s((uint32_t*)&stc->stroff);
+    bswap32s((uint32_t*)&stc->strsize);
+}
+
+void bswap_sym(struct nlist *n)
+{
+    bswap32s((uint32_t*)&n->n_un.n_strx);
+    bswap16s((uint16_t*)&n->n_desc);
+    bswap32s((uint32_t*)&n->n_value);
+}
+
+int load_thread(struct mach_header *mh, struct target_thread_command *tc, struct target_pt_regs * regs, int fd, int mh_pos, int need_bswap)
+{
+    int entry;
+    if(need_bswap)
+        bswap_tc(tc);
+#if defined(TARGET_I386)
+    entry = tc->state.eip;
+    DPRINTF(" eax 0x%.8x\n ebx 0x%.8x\n ecx 0x%.8x\n edx 0x%.8x\n edi 0x%.8x\n esi 0x%.8x\n ebp 0x%.8x\n esp 0x%.8x\n ss 0x%.8x\n eflags 0x%.8x\n eip 0x%.8x\n cs 0x%.8x\n ds 0x%.8x\n es 0x%.8x\n fs 0x%.8x\n gs 0x%.8x\n",
+            tc->state.eax, tc->state.ebx, tc->state.ecx, tc->state.edx, tc->state.edi, tc->state.esi, tc->state.ebp,
+            tc->state.esp, tc->state.ss, tc->state.eflags, tc->state.eip, tc->state.cs, tc->state.ds, tc->state.es,
+            tc->state.fs, tc->state.gs );
+#define reg_copy(reg)   regs->reg = tc->state.reg
+    if(regs)
+    {
+        reg_copy(eax);
+        reg_copy(ebx);
+        reg_copy(ecx);
+        reg_copy(edx);
+
+        reg_copy(edi);
+        reg_copy(esi);
+
+        reg_copy(ebp);
+        reg_copy(esp);
+
+        reg_copy(eflags);
+        reg_copy(eip);
+    /*
+        reg_copy(ss);
+        reg_copy(cs);
+        reg_copy(ds);
+        reg_copy(es);
+        reg_copy(fs);
+        reg_copy(gs);*/
+    }
+#undef reg_copy
+#elif defined(TARGET_PPC)
+    entry =  tc->state.srr0;
+#endif
+    DPRINTF("load_thread: entry 0x%x\n", entry);
+    return entry;
+}
+
+int load_dylinker(struct mach_header *mh, struct dylinker_command *dc, int fd, int mh_pos, int need_bswap)
+{
+    int size;
+    char * dylinker_name;
+    size = dc->cmdsize - sizeof(struct dylinker_command);
+
+    if(need_bswap)
+        dylinker_name = (char*)(bswap_32(dc->name.offset)+(int)dc);
+    else
+        dylinker_name = (char*)((dc->name.offset)+(int)dc);
+
+#ifdef OVERRIDE_DYLINKER
+    dylinker_name = DYLINKER_NAME;
+#else
+    if(asprintf(&dylinker_name, "%s%s", interp_prefix, dylinker_name) == -1)
+        qerror("can't allocate the new dylinker name\n");
+#endif
+
+    DPRINTF("dylinker_name %s\n", dylinker_name);
+    return load_object(dylinker_name, NULL, NULL);
+}
+
+int load_segment(struct mach_header *mh, struct segment_command *sc, int fd, int mh_pos, int need_bswap, int fixed, int slide)
+{
+    unsigned long addr = sc->vmaddr;
+    unsigned long size = sc->filesize;
+    unsigned long error = 0;
+
+    if(need_bswap)
+        bswap_segcmd(sc);
+
+    if(sc->vmaddr == 0)
+    {
+        DPRINTF("load_segment: sc->vmaddr == 0 returning\n");
+        return -1;
+    }
+
+    if (strcmp(sc->segname, "__PAGEZERO") == 0)
+    {
+        DPRINTF("load_segment: __PAGEZERO returning\n");
+        return -1;
+    }
+
+    /* Right now mmap memory */
+    /* XXX: should check to see that the space is free, because MAP_FIXED is dangerous */
+    DPRINTF("load_segment: mmaping %s to 0x%x-(0x%x|0x%x) + 0x%x\n", sc->segname, sc->vmaddr, sc->filesize, sc->vmsize, slide);
+
+    if(sc->filesize > 0)
+    {
+        int opt = 0;
+
+        if(fixed)
+            opt |= MAP_FIXED;
+
+        DPRINTF("sc->vmaddr 0x%x slide 0x%x add 0x%x\n", slide, sc->vmaddr, sc->vmaddr+slide);
+
+        addr = target_mmap(sc->vmaddr+slide, sc->filesize,  sc->initprot, opt, fd, mh_pos + sc->fileoff);
+
+        if(addr==-1)
+            qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide);
+
+        error = addr-sc->vmaddr;
+    }
+    else
+    {
+        addr = sc->vmaddr+slide;
+        error = slide;
+    }
+
+    if(sc->vmsize > sc->filesize)
+    {
+        addr += sc->filesize;
+        size = sc->vmsize-sc->filesize;
+        addr = target_mmap(addr, size, sc->initprot, MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+        if(addr==-1)
+            qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide);
+    }
+
+    return error;
+}
+
+void *load_data(int fd, long offset, unsigned int size)
+{
+    char *data;
+
+    data = malloc(size);
+    if (!data)
+        return NULL;
+    lseek(fd, offset, SEEK_SET);
+    if (read(fd, data, size) != size) {
+        free(data);
+        return NULL;
+    }
+    return data;
+}
+
+/* load a mach-o object file */
+int load_object(const char *filename, struct target_pt_regs * regs, void ** mh)
+{
+    int need_bswap = 0;
+    int entry_point = 0;
+    int dyld_entry_point = 0;
+    int slide, mmapfixed;
+    int fd;
+    struct load_command *lcmds, *lc;
+    int is_fat = 0;
+    unsigned int i, magic;
+    int mach_hdr_pos = 0;
+    struct mach_header mach_hdr;
+
+    /* for symbol lookup whith -d flag. */
+    struct symtab_command *    symtabcmd = 0;
+    struct nlist_extended *symtab, *sym;
+    struct nlist     *symtab_std, *syment;
+    char            *strtab;
+
+    fd = open(filename, O_RDONLY);
+    if (fd < 0)
+        qerror("can't open file '%s'", filename);
+
+    /* Read magic header.  */
+    if (read(fd, &magic, sizeof (magic)) != sizeof (magic))
+        qerror("unable to read Magic of '%s'", filename);
+
+    /* Check Mach identification.  */
+    if(magic == MH_MAGIC)
+    {
+        is_fat = 0;
+        need_bswap = 0;
+    } else if (magic == MH_CIGAM)
+    {
+        is_fat = 0;
+        need_bswap = 1;
+    } else if (magic == FAT_MAGIC)
+    {
+        is_fat = 1;
+        need_bswap = 0;
+    } else if (magic == FAT_CIGAM)
+    {
+        is_fat = 1;
+        need_bswap = 1;
+    }
+    else
+        qerror("Not a Mach-O file.", filename);
+
+    DPRINTF("loading %s %s...\n", filename, is_fat ? "[FAT]": "[REGULAR]");
+    if(is_fat)
+    {
+        int found = 0;
+        struct fat_header fh;
+        struct fat_arch *fa;
+
+        lseek(fd, 0, SEEK_SET);
+
+        /* Read Fat header.  */
+        if (read(fd, &fh, sizeof (fh)) != sizeof (fh))
+            qerror("unable to read file header");
+
+        if(need_bswap)
+            bswap_fh(&fh);
+
+        /* Read Fat Arch.  */
+        fa = malloc(sizeof(struct fat_arch)*fh.nfat_arch);
+
+        if (read(fd, fa, sizeof(struct fat_arch)*fh.nfat_arch) != sizeof(struct fat_arch)*fh.nfat_arch)
+            qerror("unable to read file header");
+
+        for( i = 0; i < fh.nfat_arch; i++, fa++)
+        {
+            if(need_bswap)
+                bswap_fa(fa);
+            if(fa->cputype == TARGET_CPU_TYPE)
+            {
+                mach_hdr_pos = fa->offset;
+                lseek(fd, mach_hdr_pos, SEEK_SET);
+
+                /* Read Mach header.  */
+
+                if (read(fd, &mach_hdr, sizeof(struct mach_header)) != sizeof (struct mach_header))
+                    qerror("unable to read file header");
+
+                if(mach_hdr.magic == MH_MAGIC)
+                    need_bswap = 0;
+                else if (mach_hdr.magic == MH_CIGAM)
+                    need_bswap = 1;
+                else
+                    qerror("Invalid mach header in Fat Mach-O File");
+                found = 1;
+                break;
+            }
+        }
+        if(!found)
+            qerror("%s: No %s CPU found in FAT Header", filename, TARGET_CPU_NAME);
+    }
+    else
+    {
+        lseek(fd, 0, SEEK_SET);
+        /* Read Mach header */
+        if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr))
+            qerror("%s: unable to read file header", filename);
+    }
+
+    if(need_bswap)
+        bswap_mh(&mach_hdr);
+
+    if ((mach_hdr.cputype) != TARGET_CPU_TYPE)
+        qerror("%s: Unsupported CPU 0x%x (only 0x%x(%s) supported)", filename, mach_hdr.cputype, TARGET_CPU_TYPE, TARGET_CPU_NAME);
+
+
+    switch(mach_hdr.filetype)
+    {
+        case MH_EXECUTE:  break;
+        case MH_FVMLIB:
+        case MH_DYLIB:
+        case MH_DYLINKER: break;
+        default:
+            qerror("%s: Unsupported Mach type (0x%x)", filename, mach_hdr.filetype);
+    }
+
+    /* read segment headers */
+    lcmds = malloc(mach_hdr.sizeofcmds);
+
+    if(read(fd, lcmds, mach_hdr.sizeofcmds) != mach_hdr.sizeofcmds)
+            qerror("%s: unable to read load_command", filename);
+    slide = 0;
+    mmapfixed = 0;
+    for(i=0, lc = lcmds; i < (mach_hdr.ncmds) ; i++)
+    {
+
+        if(need_bswap)
+            bswap_lc(lc);
+        switch(lc->cmd)
+        {
+            case LC_SEGMENT:
+                /* The main_exe can't be relocated */
+                if(mach_hdr.filetype == MH_EXECUTE)
+                    mmapfixed = 1;
+
+                slide = load_segment(&mach_hdr, (struct segment_command*)lc, fd, mach_hdr_pos, need_bswap, mmapfixed, slide);
+
+                /* other segment must be mapped according to slide exactly, if load_segment did something */
+                if(slide != -1)
+                    mmapfixed = 1;
+                else
+                    slide = 0; /* load_segment didn't map the segment */
+
+                if(mach_hdr.filetype == MH_EXECUTE && slide != 0)
+                    qerror("%s: Warning executable can't be mapped at the right address (offset: 0x%x)\n", filename, slide);
+
+                if(strcmp(((struct segment_command*)(lc))->segname, "__TEXT") == 0)
+                {
+                    /* Text section */
+                    if(mach_hdr.filetype == MH_EXECUTE)
+                    {
+                        /* return the mach_header */
+                        *mh = (void*)(((struct segment_command*)(lc))->vmaddr + slide);
+                    }
+                    else
+                    {
+                        /* it is dyld save the section for gdb, we will be interested in dyld symbol
+                           while debuging */
+                        macho_text_sect = (void*)(((struct segment_command*)(lc))->vmaddr + slide);
+                        macho_offset = slide;
+                    }
+                }
+                break;
+            case LC_LOAD_DYLINKER:
+                dyld_entry_point = load_dylinker( &mach_hdr, (struct dylinker_command*)lc, fd, mach_hdr_pos, need_bswap );
+                break;
+            case LC_LOAD_DYLIB:
+                /* dyld will do that for us */
+                break;
+            case LC_THREAD:
+            case LC_UNIXTHREAD:
+                {
+                struct target_pt_regs * _regs;
+                if(mach_hdr.filetype == MH_DYLINKER)
+                    _regs = regs;
+                else
+                    _regs = 0;
+                entry_point = load_thread( &mach_hdr, (struct target_thread_command*)lc, _regs, fd, mach_hdr_pos, need_bswap );
+                }
+                break;
+            case LC_SYMTAB:
+                /* Save the symtab and strtab */
+                symtabcmd = (struct symtab_command *)lc;
+                break;
+            case LC_ID_DYLINKER:
+            case LC_ID_DYLIB:
+            case LC_UUID:
+            case LC_DYSYMTAB:
+            case LC_TWOLEVEL_HINTS:
+            case LC_PREBIND_CKSUM:
+            case LC_SUB_LIBRARY:
+                break;
+            default: fprintf(stderr, "warning: unkown command 0x%x in '%s'\n", lc->cmd, filename);
+        }
+        lc = (struct load_command*)((int)(lc)+(lc->cmdsize));
+    }
+
+    if(symtabcmd)
+    {
+        if(need_bswap)
+            bswap_symtabcmd(symtabcmd);
+
+        symtab_std = load_data(fd, symtabcmd->symoff+mach_hdr_pos, symtabcmd->nsyms * sizeof(struct nlist));
+        strtab = load_data(fd, symtabcmd->stroff+mach_hdr_pos, symtabcmd->strsize);
+
+        symtab = malloc(sizeof(struct nlist_extended) * symtabcmd->nsyms);
+
+        if(need_bswap)
+        {
+            for(i = 0, syment = symtab_std; i < symtabcmd->nsyms; i++, syment++)
+                bswap_sym(syment);
+        }
+
+        for(i = 0, sym = symtab, syment = symtab_std; i < symtabcmd->nsyms; i++, sym++, syment++)
+        {
+            struct nlist *sym_follow, *sym_next = 0;
+            unsigned int j;
+            memset(sym, 0, sizeof(*sym));
+
+            sym->n_type = syment->n_type;
+            if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
+                continue;
+
+            memcpy(sym, syment, sizeof(*syment));
+
+            /* Find the following symbol in order to get the current symbol size */
+            for(j = 0, sym_follow = symtab_std; j < symtabcmd->nsyms; j++, sym_follow++) {
+                if ( sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value))
+                    continue;
+                if(!sym_next) {
+                    sym_next = sym_follow;
+                    continue;
+                }
+                if(!(sym_next->n_value > sym_follow->n_value))
+                    continue;
+                sym_next = sym_follow;
+            }
+            if(sym_next)
+                sym->st_size = sym_next->n_value - sym->st_value;
+            else
+                sym->st_size = 10; /* XXX: text_sec_hdr->size + text_sec_hdr->offset - sym->st_value; */
+
+            sym->st_value += slide;
+        }
+
+        free((void*)symtab_std);
+
+        {
+            DPRINTF("saving symtab of %s (%d symbol(s))\n", filename, symtabcmd->nsyms);
+            struct syminfo *s;
+            s = malloc(sizeof(*s));
+            s->disas_symtab = symtab;
+            s->disas_strtab = strtab;
+            s->disas_num_syms = symtabcmd->nsyms;
+            s->next = syminfos;
+            syminfos = s;
+        }
+    }
+    close(fd);
+    if(mach_hdr.filetype == MH_EXECUTE && dyld_entry_point)
+        return dyld_entry_point;
+    else
+        return entry_point+slide;
+}
+
+extern unsigned long stack_size;
+
+unsigned long setup_arg_pages(void * mh, char ** argv, char ** env)
+{
+    unsigned long stack_base, error, size;
+    int i;
+    int * stack;
+    int argc, envc;
+
+    /* Create enough stack to hold everything.  If we don't use
+     * it for args, we'll use it for something else...
+     */
+    size = stack_size;
+
+    error = target_mmap(0,
+                        size + qemu_host_page_size,
+                        PROT_READ | PROT_WRITE,
+                        MAP_PRIVATE | MAP_ANONYMOUS,
+                        -1, 0);
+    if (error == -1)
+        qerror("stk mmap");
+
+    /* we reserve one extra page at the top of the stack as guard */
+    target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
+
+    stack_base = error + size;
+    stack = (void*)stack_base;
+/*
+ *    | STRING AREA |
+ *    +-------------+
+ *    |      0      |
+*    +-------------+
+ *    |  apple[n]   |
+ *    +-------------+
+ *           :
+ *    +-------------+
+ *    |  apple[0]   |
+ *    +-------------+
+ *    |      0      |
+ *    +-------------+
+ *    |    env[n]   |
+ *    +-------------+
+ *           :
+ *           :
+ *    +-------------+
+ *    |    env[0]   |
+ *    +-------------+
+ *    |      0      |
+ *    +-------------+
+ *    | arg[argc-1] |
+ *    +-------------+
+ *           :
+ *           :
+ *    +-------------+
+ *    |    arg[0]   |
+ *    +-------------+
+ *    |     argc    |
+ *    +-------------+
+ * sp->    |      mh     | address of where the a.out's file offset 0 is in memory
+ *    +-------------+
+*/
+    /* Construct the stack Stack grows down */
+    stack--;
+
+    /* XXX: string should go up there */
+
+    *stack = 0;
+    stack--;
+
+    /* Push the absolute path of our executable */
+    DPRINTF("pushing apple %s (0x%x)\n", (char*)argv[0], (int)argv[0]);
+    stl(stack, (int) argv[0]);
+
+    stack--;
+
+    stl(stack, 0);
+    stack--;
+
+    /* Get envc */
+    for(envc = 0; env[envc]; envc++);
+
+    for(i = envc-1; i >= 0; i--)
+    {
+        DPRINTF("pushing env %s (0x%x)\n", (char*)env[i], (int)env[i]);
+        stl(stack, (int)env[i]);
+        stack--;
+
+        /* XXX: remove that when string will be on top of the stack */
+        page_set_flags((int)env[i], (int)(env[i]+strlen(env[i])), PROT_READ | PAGE_VALID);
+    }
+
+    /* Add on the stack the interp_prefix choosen if so */
+    if(interp_prefix[0])
+    {
+        char *dyld_root;
+        asprintf(&dyld_root, "DYLD_ROOT_PATH=%s", interp_prefix);
+        page_set_flags((int)dyld_root, (int)(dyld_root+strlen(interp_prefix)+1), PROT_READ | PAGE_VALID);
+
+        stl(stack, (int)dyld_root);
+        stack--;
+    }
+
+#ifdef DONT_USE_DYLD_SHARED_MAP
+    {
+        char *shared_map_mode;
+        asprintf(&shared_map_mode, "DYLD_SHARED_REGION=avoid");
+        page_set_flags((int)shared_map_mode, (int)(shared_map_mode+strlen(shared_map_mode)+1), PROT_READ | PAGE_VALID);
+
+        stl(stack, (int)shared_map_mode);
+        stack--;
+    }
+#endif
+
+#ifdef ACTIVATE_DYLD_TRACE
+    char * extra_env_static[] = {"DYLD_DEBUG_TRACE=yes",
+    "DYLD_PREBIND_DEBUG=3", "DYLD_UNKNOW_TRACE=yes",
+    "DYLD_PRINT_INITIALIZERS=yes",
+    "DYLD_PRINT_SEGMENTS=yes", "DYLD_PRINT_REBASINGS=yes", "DYLD_PRINT_BINDINGS=yes", "DYLD_PRINT_INITIALIZERS=yes", "DYLD_PRINT_WARNINGS=yes" };
+
+    char ** extra_env = malloc(sizeof(extra_env_static));
+    bcopy(extra_env_static, extra_env, sizeof(extra_env_static));
+    page_set_flags((int)extra_env, (int)((void*)extra_env+sizeof(extra_env_static)), PROT_READ | PAGE_VALID);
+
+    for(i = 0; i<9; i++)
+    {
+        DPRINTF("pushing (extra) env %s (0x%x)\n", (char*)extra_env[i], (int)extra_env[i]);
+        stl(stack, (int) extra_env[i]);
+        stack--;
+    }
+#endif
+
+    stl(stack, 0);
+    stack--;
+
+    /* Get argc */
+    for(argc = 0; argv[argc]; argc++);
+
+    for(i = argc-1; i >= 0; i--)
+    {
+        DPRINTF("pushing arg %s (0x%x)\n", (char*)argv[i], (int)argv[i]);
+        stl(stack, (int) argv[i]);
+        stack--;
+
+        /* XXX: remove that when string will be on top of the stack */
+        page_set_flags((int)argv[i], (int)(argv[i]+strlen(argv[i])), PROT_READ | PAGE_VALID);
+    }
+
+    DPRINTF("pushing argc %d \n", argc);
+    stl(stack, argc);
+    stack--;
+
+    DPRINTF("pushing mh 0x%x \n", (int)mh);
+    stl(stack, (int) mh);
+
+    /* Stack points on the mh */
+    return (unsigned long)stack;
+}
+
+int mach_exec(const char * filename, char ** argv, char ** envp,
+             struct target_pt_regs * regs)
+{
+    int entrypoint, stack;
+    void * mh; /* the Mach Header that will be  used by dyld */
+
+    DPRINTF("mach_exec at 0x%x\n", (int)mach_exec);
+
+    entrypoint = load_object(filename, regs, &mh);
+    stack = setup_arg_pages(mh, argv, envp);
+#if defined(TARGET_I386)
+    regs->eip = entrypoint;
+    regs->esp = stack;
+#elif defined(TARGET_PPC)
+    regs->nip = entrypoint;
+    regs->gpr[1] = stack;
+#endif
+    DPRINTF("mach_exec returns eip set to 0x%x esp 0x%x mh 0x%x\n", entrypoint, stack, (int)mh);
+
+    if(!entrypoint)
+        qerror("%s: no entry point!\n", filename);
+
+    return 0;
+}

Added: trunk/src/host/qemu-neo1973/darwin-user/main.c
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/main.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/main.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,918 @@
+/*
+ *  qemu user main
+ *
+ *  Copyright (c) 2003 Fabrice Bellard
+ *  Copyright (c) 2006 Pierre d'Herbemont
+ *
+ *  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.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sys/syscall.h>
+#include <sys/mman.h>
+
+#include "qemu.h"
+
+#define DEBUG_LOGFILE "/tmp/qemu.log"
+
+#ifdef __APPLE__
+#include <crt_externs.h>
+# define environ  (*_NSGetEnviron())
+#endif
+
+#include <mach/mach_init.h>
+#include <mach/vm_map.h>
+
+const char *interp_prefix = "";
+
+asm(".zerofill __STD_PROG_ZONE, __STD_PROG_ZONE, __std_prog_zone, 0x0dfff000");
+
+/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
+   we allocate a bigger stack. Need a better solution, for example
+   by remapping the process stack directly at the right place */
+unsigned long stack_size = 512 * 1024;
+
+void qerror(const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+    fprintf(stderr, "\n");
+    exit(1);
+}
+
+void gemu_log(const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+}
+
+void cpu_outb(CPUState *env, int addr, int val)
+{
+    fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
+}
+
+void cpu_outw(CPUState *env, int addr, int val)
+{
+    fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
+}
+
+void cpu_outl(CPUState *env, int addr, int val)
+{
+    fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
+}
+
+int cpu_inb(CPUState *env, int addr)
+{
+    fprintf(stderr, "inb: port=0x%04x\n", addr);
+    return 0;
+}
+
+int cpu_inw(CPUState *env, int addr)
+{
+    fprintf(stderr, "inw: port=0x%04x\n", addr);
+    return 0;
+}
+
+int cpu_inl(CPUState *env, int addr)
+{
+    fprintf(stderr, "inl: port=0x%04x\n", addr);
+    return 0;
+}
+
+int cpu_get_pic_interrupt(CPUState *env)
+{
+    return -1;
+}
+#ifdef TARGET_PPC
+
+static inline uint64_t cpu_ppc_get_tb (CPUState *env)
+{
+    /* TO FIX */
+    return 0;
+}
+
+uint32_t cpu_ppc_load_tbl (CPUState *env)
+{
+    return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
+}
+
+uint32_t cpu_ppc_load_tbu (CPUState *env)
+{
+    return cpu_ppc_get_tb(env) >> 32;
+}
+
+static void cpu_ppc_store_tb (CPUState *env, uint64_t value)
+{
+    /* TO FIX */
+}
+
+void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
+{
+    cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
+}
+
+void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
+{
+    cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
+}
+
+uint32_t cpu_ppc_load_decr (CPUState *env)
+{
+    /* TO FIX */
+    return -1;
+}
+
+void cpu_ppc_store_decr (CPUState *env, uint32_t value)
+{
+    /* TO FIX */
+}
+
+void cpu_loop(CPUPPCState *env)
+{
+    int trapnr;
+    uint32_t ret;
+    target_siginfo_t info;
+
+    for(;;) {
+        trapnr = cpu_ppc_exec(env);
+        if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&
+            trapnr != EXCP_TRACE) {
+            if (loglevel > 0) {
+                cpu_dump_state(env, logfile, fprintf, 0);
+            }
+        }
+        switch(trapnr) {
+        case EXCP_NONE:
+            break;
+        case EXCP_SYSCALL_USER:
+            /* system call */
+            if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
+                ret = do_unix_syscall(env, env->gpr[0]/*, env->gpr[3], env->gpr[4],
+                                      env->gpr[5], env->gpr[6], env->gpr[7],
+                                      env->gpr[8], env->gpr[9], env->gpr[10]*/);
+            else if(((int)env->gpr[0])<0)
+                ret = do_mach_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
+                                      env->gpr[5], env->gpr[6], env->gpr[7],
+                                      env->gpr[8], env->gpr[9], env->gpr[10]);
+            else
+                ret = do_thread_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
+                                        env->gpr[5], env->gpr[6], env->gpr[7],
+                                        env->gpr[8], env->gpr[9], env->gpr[10]);
+
+            /* Unix syscall error signaling */
+            if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
+            {
+                if( (int)ret < 0 )
+                    env->nip += 0;
+                else
+                    env->nip += 4;
+            }
+
+            /* Return value */
+            env->gpr[3] = ret;
+            break;
+        case EXCP_RESET:
+            /* Should not happen ! */
+            fprintf(stderr, "RESET asked... Stop emulation\n");
+            if (loglevel)
+                fprintf(logfile, "RESET asked... Stop emulation\n");
+                abort();
+        case EXCP_MACHINE_CHECK:
+            fprintf(stderr, "Machine check exeption...  Stop emulation\n");
+            if (loglevel)
+                fprintf(logfile, "RESET asked... Stop emulation\n");
+                info.si_signo = SIGBUS;
+            info.si_errno = 0;
+            info.si_code = BUS_OBJERR;
+            info.si_addr = (void*)(env->nip - 4);
+            queue_signal(info.si_signo, &info);
+        case EXCP_DSI:
+#ifndef DAR
+/* To deal with multiple qemu header version as host for the darwin-user code */
+# define DAR SPR_DAR
+#endif
+            fprintf(stderr, "Invalid data memory access: 0x%08x\n", env->spr[DAR]);
+            if (loglevel) {
+                fprintf(logfile, "Invalid data memory access: 0x%08x\n",
+                        env->spr[DAR]);
+            }
+            /* Handle this via the gdb */
+            gdb_handlesig (env, SIGSEGV);
+
+            info.si_addr = (void*)env->nip;
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP_ISI:
+            fprintf(stderr, "Invalid instruction fetch\n");
+            if (loglevel)
+                fprintf(logfile, "Invalid instruction fetch\n");
+            /* Handle this via the gdb */
+            gdb_handlesig (env, SIGSEGV);
+
+            info.si_addr = (void*)(env->nip - 4);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP_EXTERNAL:
+            /* Should not happen ! */
+            fprintf(stderr, "External interruption... Stop emulation\n");
+            if (loglevel)
+                fprintf(logfile, "External interruption... Stop emulation\n");
+                abort();
+        case EXCP_ALIGN:
+            fprintf(stderr, "Invalid unaligned memory access\n");
+            if (loglevel)
+                fprintf(logfile, "Invalid unaligned memory access\n");
+                info.si_signo = SIGBUS;
+            info.si_errno = 0;
+            info.si_code = BUS_ADRALN;
+            info.si_addr = (void*)(env->nip - 4);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP_PROGRAM:
+            switch (env->error_code & ~0xF) {
+                case EXCP_FP:
+                    fprintf(stderr, "Program exception\n");
+                    if (loglevel)
+                        fprintf(logfile, "Program exception\n");
+                        /* Set FX */
+                        env->fpscr[7] |= 0x8;
+                    /* Finally, update FEX */
+                    if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
+                        ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
+                        env->fpscr[7] |= 0x4;
+                        info.si_signo = SIGFPE;
+                    info.si_errno = 0;
+                    switch (env->error_code & 0xF) {
+                        case EXCP_FP_OX:
+                            info.si_code = FPE_FLTOVF;
+                            break;
+                        case EXCP_FP_UX:
+                            info.si_code = FPE_FLTUND;
+                            break;
+                        case EXCP_FP_ZX:
+                        case EXCP_FP_VXZDZ:
+                            info.si_code = FPE_FLTDIV;
+                            break;
+                        case EXCP_FP_XX:
+                            info.si_code = FPE_FLTRES;
+                            break;
+                        case EXCP_FP_VXSOFT:
+                            info.si_code = FPE_FLTINV;
+                            break;
+                        case EXCP_FP_VXNAN:
+                        case EXCP_FP_VXISI:
+                        case EXCP_FP_VXIDI:
+                        case EXCP_FP_VXIMZ:
+                        case EXCP_FP_VXVC:
+                        case EXCP_FP_VXSQRT:
+                        case EXCP_FP_VXCVI:
+                            info.si_code = FPE_FLTSUB;
+                            break;
+                        default:
+                            fprintf(stderr, "Unknown floating point exception "
+                                    "(%02x)\n", env->error_code);
+                            if (loglevel) {
+                                fprintf(logfile, "Unknown floating point exception "
+                                        "(%02x)\n", env->error_code & 0xF);
+                            }
+                    }
+                        break;
+                case EXCP_INVAL:
+                    fprintf(stderr, "Invalid instruction\n");
+                    if (loglevel)
+                        fprintf(logfile, "Invalid instruction\n");
+                        info.si_signo = SIGILL;
+                    info.si_errno = 0;
+                    switch (env->error_code & 0xF) {
+                        case EXCP_INVAL_INVAL:
+                            info.si_code = ILL_ILLOPC;
+                            break;
+                        case EXCP_INVAL_LSWX:
+                            info.si_code = ILL_ILLOPN;
+                            break;
+                        case EXCP_INVAL_SPR:
+                            info.si_code = ILL_PRVREG;
+                            break;
+                        case EXCP_INVAL_FP:
+                            info.si_code = ILL_COPROC;
+                            break;
+                        default:
+                            fprintf(stderr, "Unknown invalid operation (%02x)\n",
+                                    env->error_code & 0xF);
+                            if (loglevel) {
+                                fprintf(logfile, "Unknown invalid operation (%02x)\n",
+                                        env->error_code & 0xF);
+                            }
+                                info.si_code = ILL_ILLADR;
+                            break;
+                    }
+                        /* Handle this via the gdb */
+                        gdb_handlesig (env, SIGSEGV);
+                    break;
+                case EXCP_PRIV:
+                    fprintf(stderr, "Privilege violation\n");
+                    if (loglevel)
+                        fprintf(logfile, "Privilege violation\n");
+                        info.si_signo = SIGILL;
+                    info.si_errno = 0;
+                    switch (env->error_code & 0xF) {
+                        case EXCP_PRIV_OPC:
+                            info.si_code = ILL_PRVOPC;
+                            break;
+                        case EXCP_PRIV_REG:
+                            info.si_code = ILL_PRVREG;
+                            break;
+                        default:
+                            fprintf(stderr, "Unknown privilege violation (%02x)\n",
+                                    env->error_code & 0xF);
+                            info.si_code = ILL_PRVOPC;
+                            break;
+                    }
+                        break;
+                case EXCP_TRAP:
+                    fprintf(stderr, "Tried to call a TRAP\n");
+                    if (loglevel)
+                        fprintf(logfile, "Tried to call a TRAP\n");
+                        abort();
+                default:
+                    /* Should not happen ! */
+                    fprintf(stderr, "Unknown program exception (%02x)\n",
+                            env->error_code);
+                    if (loglevel) {
+                        fprintf(logfile, "Unknwon program exception (%02x)\n",
+                                env->error_code);
+                    }
+                        abort();
+            }
+            info.si_addr = (void*)(env->nip - 4);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP_NO_FP:
+            fprintf(stderr, "No floating point allowed\n");
+            if (loglevel)
+                fprintf(logfile, "No floating point allowed\n");
+                info.si_signo = SIGILL;
+            info.si_errno = 0;
+            info.si_code = ILL_COPROC;
+            info.si_addr = (void*)(env->nip - 4);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP_DECR:
+            /* Should not happen ! */
+            fprintf(stderr, "Decrementer exception\n");
+            if (loglevel)
+                fprintf(logfile, "Decrementer exception\n");
+            abort();
+        case EXCP_TRACE:
+            /* Pass to gdb: we use this to trace execution */
+            gdb_handlesig (env, SIGTRAP);
+            break;
+        case EXCP_FP_ASSIST:
+            /* Should not happen ! */
+            fprintf(stderr, "Floating point assist exception\n");
+            if (loglevel)
+                fprintf(logfile, "Floating point assist exception\n");
+            abort();
+        case EXCP_MTMSR:
+            /* We reloaded the msr, just go on */
+            if (msr_pr == 0) {
+                fprintf(stderr, "Tried to go into supervisor mode !\n");
+                if (loglevel)
+                    fprintf(logfile, "Tried to go into supervisor mode !\n");
+                abort();
+            }
+            break;
+        case EXCP_BRANCH:
+            /* We stopped because of a jump... */
+            break;
+        case EXCP_INTERRUPT:
+            /* Don't know why this should ever happen... */
+            fprintf(stderr, "EXCP_INTERRUPT\n");
+            break;
+        case EXCP_DEBUG:
+            gdb_handlesig (env, SIGTRAP);
+            break;
+        default:
+            fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
+                    trapnr);
+            if (loglevel) {
+                fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - "
+                        "0x%02x - aborting\n", trapnr, env->error_code);
+            }
+                abort();
+        }
+        process_pending_signals(env);
+    }
+}
+#endif
+
+
+#ifdef TARGET_I386
+
+/***********************************************************/
+/* CPUX86 core interface */
+
+uint64_t cpu_get_tsc(CPUX86State *env)
+{
+    return cpu_get_real_ticks();
+}
+
+void
+write_dt(void *ptr, unsigned long addr, unsigned long limit,
+                     int flags)
+{
+    unsigned int e1, e2;
+    e1 = (addr << 16) | (limit & 0xffff);
+    e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
+    e2 |= flags;
+    stl((uint8_t *)ptr, e1);
+    stl((uint8_t *)ptr + 4, e2);
+}
+
+static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
+                     unsigned long addr, unsigned int sel)
+{
+    unsigned int e1, e2;
+    e1 = (addr & 0xffff) | (sel << 16);
+    e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
+    stl((uint8_t *)ptr, e1);
+    stl((uint8_t *)ptr + 4, e2);
+}
+
+#define GDT_TABLE_SIZE 14
+#define LDT_TABLE_SIZE 15
+#define IDT_TABLE_SIZE 256
+#define TSS_SIZE 104
+uint64_t gdt_table[GDT_TABLE_SIZE];
+uint64_t ldt_table[LDT_TABLE_SIZE];
+uint64_t idt_table[IDT_TABLE_SIZE];
+uint32_t tss[TSS_SIZE];
+
+/* only dpl matters as we do only user space emulation */
+static void set_idt(int n, unsigned int dpl)
+{
+    set_gate(idt_table + n, 0, dpl, 0, 0);
+}
+
+/* ABI convention: after a syscall if there was an error the CF flag is set */
+static inline void set_error(CPUX86State *env, int ret)
+{
+    if(ret<0)
+        env->eflags = env->eflags | 0x1;
+    else
+        env->eflags &= ~0x1;
+    env->regs[R_EAX] = ret;
+}
+
+void cpu_loop(CPUX86State *env)
+{
+    int trapnr;
+    int ret;
+    uint8_t *pc;
+    target_siginfo_t info;
+
+    for(;;) {
+        trapnr = cpu_x86_exec(env);
+        uint32_t *params = (uint32_t *)env->regs[R_ESP];
+        switch(trapnr) {
+        case 0x79: /* Our commpage hack back door exit is here */
+            do_commpage(env,  env->eip,   *(params + 1), *(params + 2),
+                                          *(params + 3), *(params + 4),
+                                          *(params + 5), *(params + 6),
+                                          *(params + 7), *(params + 8));
+            break;
+        case 0x81: /* mach syscall */
+        {
+            ret = do_mach_syscall(env,  env->regs[R_EAX],
+                                          *(params + 1), *(params + 2),
+                                          *(params + 3), *(params + 4),
+                                          *(params + 5), *(params + 6),
+                                          *(params + 7), *(params + 8));
+            set_error(env, ret);
+            break;
+        }
+        case 0x90: /* unix backdoor */
+        {
+            /* after sysenter, stack is in R_ECX, new eip in R_EDX (sysexit will flip them back)*/
+            int saved_stack = env->regs[R_ESP];
+            env->regs[R_ESP] = env->regs[R_ECX];
+
+            ret = do_unix_syscall(env, env->regs[R_EAX]);
+
+            env->regs[R_ECX] = env->regs[R_ESP];
+            env->regs[R_ESP] = saved_stack;
+
+            set_error(env, ret);
+            break;
+        }
+        case 0x80: /* unix syscall */
+        {
+            ret = do_unix_syscall(env, env->regs[R_EAX]/*,
+                                          *(params + 1), *(params + 2),
+                                          *(params + 3), *(params + 4),
+                                          *(params + 5), *(params + 6),
+                                          *(params + 7), *(params + 8)*/);
+            set_error(env, ret);
+            break;
+        }
+        case 0x82: /* thread syscall */
+        {
+            ret = do_thread_syscall(env,  env->regs[R_EAX],
+                                          *(params + 1), *(params + 2),
+                                          *(params + 3), *(params + 4),
+                                          *(params + 5), *(params + 6),
+                                          *(params + 7), *(params + 8));
+            set_error(env, ret);
+            break;
+        }
+        case EXCP0B_NOSEG:
+        case EXCP0C_STACK:
+            info.si_signo = SIGBUS;
+            info.si_errno = 0;
+            info.si_code = BUS_NOOP;
+            info.si_addr = 0;
+            gdb_handlesig (env, SIGBUS);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP0D_GPF:
+            info.si_signo = SIGSEGV;
+            info.si_errno = 0;
+            info.si_code = SEGV_NOOP;
+            info.si_addr = 0;
+            gdb_handlesig (env, SIGSEGV);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP0E_PAGE:
+            info.si_signo = SIGSEGV;
+            info.si_errno = 0;
+            if (!(env->error_code & 1))
+                info.si_code = SEGV_MAPERR;
+            else
+                info.si_code = SEGV_ACCERR;
+            info.si_addr = (void*)env->cr[2];
+            gdb_handlesig (env, SIGSEGV);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP00_DIVZ:
+            /* division by zero */
+            info.si_signo = SIGFPE;
+            info.si_errno = 0;
+            info.si_code = FPE_INTDIV;
+            info.si_addr = (void*)env->eip;
+            gdb_handlesig (env, SIGFPE);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP01_SSTP:
+        case EXCP03_INT3:
+            info.si_signo = SIGTRAP;
+            info.si_errno = 0;
+            info.si_code = TRAP_BRKPT;
+            info.si_addr = (void*)env->eip;
+            gdb_handlesig (env, SIGTRAP);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP04_INTO:
+        case EXCP05_BOUND:
+            info.si_signo = SIGSEGV;
+            info.si_errno = 0;
+            info.si_code = SEGV_NOOP;
+            info.si_addr = 0;
+            gdb_handlesig (env, SIGSEGV);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP06_ILLOP:
+            info.si_signo = SIGILL;
+            info.si_errno = 0;
+            info.si_code = ILL_ILLOPN;
+            info.si_addr = (void*)env->eip;
+            gdb_handlesig (env, SIGILL);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP_INTERRUPT:
+            /* just indicate that signals should be handled asap */
+            break;
+        case EXCP_DEBUG:
+            {
+                int sig;
+
+                sig = gdb_handlesig (env, SIGTRAP);
+                if (sig)
+                  {
+                    info.si_signo = sig;
+                    info.si_errno = 0;
+                    info.si_code = TRAP_BRKPT;
+                    queue_signal(info.si_signo, &info);
+                  }
+            }
+            break;
+        default:
+            pc = (void*)(env->segs[R_CS].base + env->eip);
+            fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
+                    (long)pc, trapnr);
+            abort();
+        }
+        process_pending_signals(env);
+    }
+}
+#endif
+
+void usage(void)
+{
+    printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n"
+           "usage: qemu-" TARGET_ARCH " [-h] [-d opts] [-L path] [-s size] program [arguments...]\n"
+           "Darwin CPU emulator (compiled for %s emulation)\n"
+           "\n"
+           "-h           print this help\n"
+           "-L path      set the %s library path (default='%s')\n"
+           "-s size      set the stack size in bytes (default=%ld)\n"
+           "\n"
+           "debug options:\n"
+#ifdef USE_CODE_COPY
+           "-no-code-copy   disable code copy acceleration\n"
+#endif
+           "-d options   activate log (logfile='%s')\n"
+           "-g wait for gdb on port 1234\n"
+           "-p pagesize  set the host page size to 'pagesize'\n",
+           TARGET_ARCH,
+           TARGET_ARCH,
+           interp_prefix,
+           stack_size,
+           DEBUG_LOGFILE);
+    _exit(1);
+}
+
+/* XXX: currently only used for async signals (see signal.c) */
+CPUState *global_env;
+/* used only if single thread */
+CPUState *cpu_single_env = NULL;
+
+/* used to free thread contexts */
+TaskState *first_task_state;
+
+int main(int argc, char **argv)
+{
+    const char *filename;
+    struct target_pt_regs regs1, *regs = &regs1;
+    TaskState ts1, *ts = &ts1;
+    CPUState *env;
+    int optind;
+    short use_gdbstub = 0;
+    const char *r;
+
+    if (argc <= 1)
+        usage();
+
+    /* init debug */
+    cpu_set_log_filename(DEBUG_LOGFILE);
+
+    optind = 1;
+    for(;;) {
+        if (optind >= argc)
+            break;
+        r = argv[optind];
+        if (r[0] != '-')
+            break;
+        optind++;
+        r++;
+        if (!strcmp(r, "-")) {
+            break;
+        } else if (!strcmp(r, "d")) {
+            int mask;
+            CPULogItem *item;
+
+        if (optind >= argc)
+        break;
+
+        r = argv[optind++];
+            mask = cpu_str_to_log_mask(r);
+            if (!mask) {
+                printf("Log items (comma separated):\n");
+                for(item = cpu_log_items; item->mask != 0; item++) {
+                    printf("%-10s %s\n", item->name, item->help);
+                }
+                exit(1);
+            }
+            cpu_set_log(mask);
+        } else if (!strcmp(r, "s")) {
+            r = argv[optind++];
+            stack_size = strtol(r, (char **)&r, 0);
+            if (stack_size <= 0)
+                usage();
+            if (*r == 'M')
+                stack_size *= 1024 * 1024;
+            else if (*r == 'k' || *r == 'K')
+                stack_size *= 1024;
+        } else if (!strcmp(r, "L")) {
+            interp_prefix = argv[optind++];
+        } else if (!strcmp(r, "p")) {
+            qemu_host_page_size = atoi(argv[optind++]);
+            if (qemu_host_page_size == 0 ||
+                (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
+                fprintf(stderr, "page size must be a power of two\n");
+                exit(1);
+            }
+        } else
+        if (!strcmp(r, "g")) {
+            use_gdbstub = 1;
+        } else
+#ifdef USE_CODE_COPY
+        if (!strcmp(r, "no-code-copy")) {
+            code_copy_enabled = 0;
+        } else
+#endif
+        {
+            usage();
+        }
+    }
+    if (optind >= argc)
+        usage();
+    filename = argv[optind];
+
+    /* Zero out regs */
+    memset(regs, 0, sizeof(struct target_pt_regs));
+
+    /* NOTE: we need to init the CPU at this stage to get
+       qemu_host_page_size */
+    env = cpu_init();
+
+    printf("Starting %s with qemu\n----------------\n", filename);
+
+    commpage_init();
+
+    if (mach_exec(filename, argv+optind, environ, regs) != 0) {
+    printf("Error loading %s\n", filename);
+    _exit(1);
+    }
+
+    syscall_init();
+    signal_init();
+    global_env = env;
+
+    /* build Task State */
+    memset(ts, 0, sizeof(TaskState));
+    env->opaque = ts;
+    ts->used = 1;
+    env->user_mode_only = 1;
+
+#if defined(TARGET_I386)
+    cpu_x86_set_cpl(env, 3);
+
+    env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
+    env->hflags |= HF_PE_MASK;
+
+    if (env->cpuid_features & CPUID_SSE) {
+        env->cr[4] |= CR4_OSFXSR_MASK;
+        env->hflags |= HF_OSFXSR_MASK;
+    }
+
+    /* flags setup : we activate the IRQs by default as in user mode */
+    env->eflags |= IF_MASK;
+
+    /* darwin register setup */
+    env->regs[R_EAX] = regs->eax;
+    env->regs[R_EBX] = regs->ebx;
+    env->regs[R_ECX] = regs->ecx;
+    env->regs[R_EDX] = regs->edx;
+    env->regs[R_ESI] = regs->esi;
+    env->regs[R_EDI] = regs->edi;
+    env->regs[R_EBP] = regs->ebp;
+    env->regs[R_ESP] = regs->esp;
+    env->eip = regs->eip;
+
+    /* Darwin LDT setup */
+    /* 2 - User code segment
+       3 - User data segment
+       4 - User cthread */
+    bzero(ldt_table, LDT_TABLE_SIZE * sizeof(ldt_table[0]));
+    env->ldt.base = (uint32_t) ldt_table;
+    env->ldt.limit = sizeof(ldt_table) - 1;
+
+    write_dt(ldt_table + 2, 0, 0xfffff,
+             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
+             (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
+    write_dt(ldt_table + 3, 0, 0xfffff,
+             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
+             (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
+    write_dt(ldt_table + 4, 0, 0xfffff,
+             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
+             (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
+
+    /* Darwin GDT setup.
+     * has changed a lot between old Darwin/x86 (pre-Mac Intel) and Mac OS X/x86,
+       now everything is done via  int 0x81(mach) int 0x82 (thread) and sysenter/sysexit(unix) */
+    bzero(gdt_table, sizeof(gdt_table));
+    env->gdt.base = (uint32_t)gdt_table;
+    env->gdt.limit = sizeof(gdt_table) - 1;
+
+    /* Set up a back door to handle sysenter syscalls (unix) */
+    char * syscallbackdoor = malloc(64);
+    page_set_flags((int)syscallbackdoor, (int)syscallbackdoor + 64, PROT_EXEC | PROT_READ | PAGE_VALID);
+
+    int i = 0;
+    syscallbackdoor[i++] = 0xcd;
+    syscallbackdoor[i++] = 0x90; /* int 0x90 */
+    syscallbackdoor[i++] = 0x0F;
+    syscallbackdoor[i++] = 0x35; /* sysexit */
+
+    /* Darwin sysenter/sysexit setup */
+    env->sysenter_cs = 0x1; //XXX
+    env->sysenter_eip = (int)syscallbackdoor;
+    env->sysenter_esp = (int)malloc(64);
+
+    /* Darwin TSS setup
+       This must match up with GDT[4] */
+    env->tr.base = (uint32_t) tss;
+    env->tr.limit = sizeof(tss) - 1;
+    env->tr.flags = DESC_P_MASK | (0x9 << DESC_TYPE_SHIFT);
+    stw(tss + 2, 0x10);  // ss0 = 0x10 = GDT[2] = Kernel Data Segment
+
+    /* Darwin interrupt setup */
+    bzero(idt_table, sizeof(idt_table));
+    env->idt.base = (uint32_t) idt_table;
+    env->idt.limit = sizeof(idt_table) - 1;
+    set_idt(0, 0);
+    set_idt(1, 0);
+    set_idt(2, 0);
+    set_idt(3, 3);
+    set_idt(4, 3);
+    set_idt(5, 3);
+    set_idt(6, 0);
+    set_idt(7, 0);
+    set_idt(8, 0);
+    set_idt(9, 0);
+    set_idt(10, 0);
+    set_idt(11, 0);
+    set_idt(12, 0);
+    set_idt(13, 0);
+    set_idt(14, 0);
+    set_idt(15, 0);
+    set_idt(16, 0);
+    set_idt(17, 0);
+    set_idt(18, 0);
+    set_idt(19, 0);
+    /* Syscalls are done via
+        int 0x80 (unix) (rarely used)
+        int 0x81 (mach)
+        int 0x82 (thread)
+        int 0x83 (diag) (not handled here)
+        sysenter/sysexit (unix) -> we redirect that to int 0x90 */
+    set_idt(0x79, 3); /* Commpage hack, here is our backdoor interrupt */
+    set_idt(0x80, 3); /* Unix Syscall */
+    set_idt(0x81, 3); /* Mach Syscalls */
+    set_idt(0x82, 3); /* thread Syscalls */
+
+    set_idt(0x90, 3); /* qemu-darwin-user's Unix syscalls backdoor */
+
+
+    cpu_x86_load_seg(env, R_CS, __USER_CS);
+    cpu_x86_load_seg(env, R_DS, __USER_DS);
+    cpu_x86_load_seg(env, R_ES, __USER_DS);
+    cpu_x86_load_seg(env, R_SS, __USER_DS);
+    cpu_x86_load_seg(env, R_FS, __USER_DS);
+    cpu_x86_load_seg(env, R_GS, __USER_DS);
+
+#elif defined(TARGET_PPC)
+    {
+        int i;
+        env->nip = regs->nip;
+        for(i = 0; i < 32; i++) {
+            env->gpr[i] = regs->gpr[i];
+        }
+    }
+#else
+#error unsupported target CPU
+#endif
+
+    if (use_gdbstub) {
+        printf("Waiting for gdb Connection on port 1234...\n");
+        gdbserver_start (1234);
+        gdb_handlesig(env, 0);
+    }
+
+    cpu_loop(env);
+    /* never exits */
+    return 0;
+}

Added: trunk/src/host/qemu-neo1973/darwin-user/mmap.c
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/mmap.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/mmap.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,411 @@
+/*
+ *  mmap support for qemu
+ *
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  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.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/mman.h>
+
+#include "qemu.h"
+
+//#define DEBUG_MMAP
+
+/* NOTE: all the constants are the HOST ones */
+int target_mprotect(unsigned long start, unsigned long len, int prot)
+{
+    unsigned long end, host_start, host_end, addr;
+    int prot1, ret;
+
+#ifdef DEBUG_MMAP
+    printf("mprotect: start=0x%lx len=0x%lx prot=%c%c%c\n", start, len,
+           prot & PROT_READ ? 'r' : '-',
+           prot & PROT_WRITE ? 'w' : '-',
+           prot & PROT_EXEC ? 'x' : '-');
+#endif
+
+    if ((start & ~TARGET_PAGE_MASK) != 0)
+        return -EINVAL;
+    len = TARGET_PAGE_ALIGN(len);
+    end = start + len;
+    if (end < start)
+        return -EINVAL;
+    if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
+        return -EINVAL;
+    if (len == 0)
+        return 0;
+
+    host_start = start & qemu_host_page_mask;
+    host_end = HOST_PAGE_ALIGN(end);
+    if (start > host_start) {
+        /* handle host page containing start */
+        prot1 = prot;
+        for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
+            prot1 |= page_get_flags(addr);
+        }
+        if (host_end == host_start + qemu_host_page_size) {
+            for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
+                prot1 |= page_get_flags(addr);
+            }
+            end = host_end;
+        }
+        ret = mprotect((void *)host_start, qemu_host_page_size, prot1 & PAGE_BITS);
+        if (ret != 0)
+            return ret;
+        host_start += qemu_host_page_size;
+    }
+    if (end < host_end) {
+        prot1 = prot;
+        for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
+            prot1 |= page_get_flags(addr);
+        }
+        ret = mprotect((void *)(host_end - qemu_host_page_size), qemu_host_page_size,
+                       prot1 & PAGE_BITS);
+        if (ret != 0)
+            return ret;
+        host_end -= qemu_host_page_size;
+    }
+
+    /* handle the pages in the middle */
+    if (host_start < host_end) {
+        ret = mprotect((void *)host_start, host_end - host_start, prot);
+        if (ret != 0)
+            return ret;
+    }
+    page_set_flags(start, start + len, prot | PAGE_VALID);
+    return 0;
+}
+
+/* map an incomplete host page */
+int mmap_frag(unsigned long host_start,
+               unsigned long start, unsigned long end,
+               int prot, int flags, int fd, unsigned long offset)
+{
+    unsigned long host_end, ret, addr;
+    int prot1, prot_new;
+
+    host_end = host_start + qemu_host_page_size;
+
+    /* get the protection of the target pages outside the mapping */
+    prot1 = 0;
+    for(addr = host_start; addr < host_end; addr++) {
+        if (addr < start || addr >= end)
+            prot1 |= page_get_flags(addr);
+    }
+
+    if (prot1 == 0) {
+        /* no page was there, so we allocate one */
+        ret = (long)mmap((void *)host_start, qemu_host_page_size, prot,
+                         flags | MAP_ANONYMOUS, -1, 0);
+        if (ret == -1)
+            return ret;
+    }
+    prot1 &= PAGE_BITS;
+
+    prot_new = prot | prot1;
+    if (!(flags & MAP_ANONYMOUS)) {
+        /* msync() won't work here, so we return an error if write is
+           possible while it is a shared mapping */
+#ifndef __APPLE__
+        if ((flags & MAP_TYPE) == MAP_SHARED &&
+#else
+        if ((flags &  MAP_SHARED) &&
+#endif
+            (prot & PROT_WRITE))
+            return -EINVAL;
+
+        /* adjust protection to be able to read */
+        if (!(prot1 & PROT_WRITE))
+            mprotect((void *)host_start, qemu_host_page_size, prot1 | PROT_WRITE);
+
+        /* read the corresponding file data */
+        pread(fd, (void *)start, end - start, offset);
+
+        /* put final protection */
+        if (prot_new != (prot1 | PROT_WRITE))
+            mprotect((void *)host_start, qemu_host_page_size, prot_new);
+    } else {
+        /* just update the protection */
+        if (prot_new != prot1) {
+            mprotect((void *)host_start, qemu_host_page_size, prot_new);
+        }
+    }
+    return 0;
+}
+
+/* NOTE: all the constants are the HOST ones */
+long target_mmap(unsigned long start, unsigned long len, int prot,
+                 int flags, int fd, unsigned long offset)
+{
+    unsigned long ret, end, host_start, host_end, retaddr, host_offset, host_len;
+#if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__)
+    static unsigned long last_start = 0x40000000;
+#endif
+
+#ifdef DEBUG_MMAP
+    {
+        printf("mmap: start=0x%lx len=0x%lx prot=%c%c%c flags=",
+               start, len,
+               prot & PROT_READ ? 'r' : '-',
+               prot & PROT_WRITE ? 'w' : '-',
+               prot & PROT_EXEC ? 'x' : '-');
+        if (flags & MAP_FIXED)
+            printf("MAP_FIXED ");
+        if (flags & MAP_ANONYMOUS)
+            printf("MAP_ANON ");
+#ifndef MAP_TYPE
+# define MAP_TYPE 0x3
+#endif
+        switch(flags & MAP_TYPE) {
+        case MAP_PRIVATE:
+            printf("MAP_PRIVATE ");
+            break;
+        case MAP_SHARED:
+            printf("MAP_SHARED ");
+            break;
+        default:
+            printf("[MAP_TYPE=0x%x] ", flags & MAP_TYPE);
+            break;
+        }
+        printf("fd=%d offset=%lx\n", fd, offset);
+    }
+#endif
+
+    if (offset & ~TARGET_PAGE_MASK)
+        return -EINVAL;
+
+    len = TARGET_PAGE_ALIGN(len);
+    if (len == 0)
+        return start;
+    host_start = start & qemu_host_page_mask;
+
+    if (!(flags & MAP_FIXED)) {
+#if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__)
+        /* tell the kenel to search at the same place as i386 */
+        if (host_start == 0) {
+            host_start = last_start;
+            last_start += HOST_PAGE_ALIGN(len);
+        }
+#endif
+        if (qemu_host_page_size != qemu_real_host_page_size) {
+            /* NOTE: this code is only for debugging with '-p' option */
+            /* reserve a memory area */
+            host_len = HOST_PAGE_ALIGN(len) + qemu_host_page_size - TARGET_PAGE_SIZE;
+            host_start = (long)mmap((void *)host_start, host_len, PROT_NONE,
+                                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+            if (host_start == -1)
+                return host_start;
+            host_end = host_start + host_len;
+            start = HOST_PAGE_ALIGN(host_start);
+            end = start + HOST_PAGE_ALIGN(len);
+            if (start > host_start)
+                munmap((void *)host_start, start - host_start);
+            if (end < host_end)
+                munmap((void *)end, host_end - end);
+            /* use it as a fixed mapping */
+            flags |= MAP_FIXED;
+        } else {
+            /* if not fixed, no need to do anything */
+            host_offset = offset & qemu_host_page_mask;
+            host_len = len + offset - host_offset;
+            start = (long)mmap((void *)host_start, host_len,
+                               prot, flags, fd, host_offset);
+            if (start == -1)
+                return start;
+            /* update start so that it points to the file position at 'offset' */
+            if (!(flags & MAP_ANONYMOUS))
+                start += offset - host_offset;
+            goto the_end1;
+        }
+    }
+
+    if (start & ~TARGET_PAGE_MASK)
+        return -EINVAL;
+    end = start + len;
+    host_end = HOST_PAGE_ALIGN(end);
+
+    /* worst case: we cannot map the file because the offset is not
+       aligned, so we read it */
+    if (!(flags & MAP_ANONYMOUS) &&
+        (offset & ~qemu_host_page_mask) != (start & ~qemu_host_page_mask)) {
+        /* msync() won't work here, so we return an error if write is
+           possible while it is a shared mapping */
+#ifndef __APPLE__
+        if ((flags & MAP_TYPE) == MAP_SHARED &&
+#else
+        if ((flags & MAP_SHARED) &&
+#endif
+            (prot & PROT_WRITE))
+            return -EINVAL;
+        retaddr = target_mmap(start, len, prot | PROT_WRITE,
+                              MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
+                              -1, 0);
+        if (retaddr == -1)
+            return retaddr;
+        pread(fd, (void *)start, len, offset);
+        if (!(prot & PROT_WRITE)) {
+            ret = target_mprotect(start, len, prot);
+            if (ret != 0)
+                return ret;
+        }
+        goto the_end;
+    }
+
+    /* handle the start of the mapping */
+    if (start > host_start) {
+        if (host_end == host_start + qemu_host_page_size) {
+            /* one single host page */
+            ret = mmap_frag(host_start, start, end,
+                            prot, flags, fd, offset);
+            if (ret == -1)
+                return ret;
+            goto the_end1;
+        }
+        ret = mmap_frag(host_start, start, host_start + qemu_host_page_size,
+                        prot, flags, fd, offset);
+        if (ret == -1)
+            return ret;
+        host_start += qemu_host_page_size;
+    }
+    /* handle the end of the mapping */
+    if (end < host_end) {
+        ret = mmap_frag(host_end - qemu_host_page_size,
+                        host_end - qemu_host_page_size, host_end,
+                        prot, flags, fd,
+                        offset + host_end - qemu_host_page_size - start);
+        if (ret == -1)
+            return ret;
+        host_end -= qemu_host_page_size;
+    }
+
+    /* map the middle (easier) */
+    if (host_start < host_end) {
+        unsigned long offset1;
+	if (flags & MAP_ANONYMOUS)
+	  offset1 = 0;
+	else
+	  offset1 = offset + host_start - start;
+        ret = (long)mmap((void *)host_start, host_end - host_start,
+                         prot, flags, fd, offset1);
+        if (ret == -1)
+            return ret;
+    }
+ the_end1:
+    page_set_flags(start, start + len, prot | PAGE_VALID);
+ the_end:
+#ifdef DEBUG_MMAP
+    printf("target_mmap: ret=0x%lx\n", (long)start);
+    page_dump(stdout);
+    printf("\n");
+#endif
+    return start;
+}
+
+int target_munmap(unsigned long start, unsigned long len)
+{
+    unsigned long end, host_start, host_end, addr;
+    int prot, ret;
+
+#ifdef DEBUG_MMAP
+    printf("munmap: start=0x%lx len=0x%lx\n", start, len);
+#endif
+    if (start & ~TARGET_PAGE_MASK)
+        return -EINVAL;
+    len = TARGET_PAGE_ALIGN(len);
+    if (len == 0)
+        return -EINVAL;
+    end = start + len;
+    host_start = start & qemu_host_page_mask;
+    host_end = HOST_PAGE_ALIGN(end);
+
+    if (start > host_start) {
+        /* handle host page containing start */
+        prot = 0;
+        for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
+            prot |= page_get_flags(addr);
+        }
+        if (host_end == host_start + qemu_host_page_size) {
+            for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
+                prot |= page_get_flags(addr);
+            }
+            end = host_end;
+        }
+        if (prot != 0)
+            host_start += qemu_host_page_size;
+    }
+    if (end < host_end) {
+        prot = 0;
+        for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
+            prot |= page_get_flags(addr);
+        }
+        if (prot != 0)
+            host_end -= qemu_host_page_size;
+    }
+
+    /* unmap what we can */
+    if (host_start < host_end) {
+        ret = munmap((void *)host_start, host_end - host_start);
+        if (ret != 0)
+            return ret;
+    }
+
+    page_set_flags(start, start + len, 0);
+    return 0;
+}
+
+/* XXX: currently, we only handle MAP_ANONYMOUS and not MAP_FIXED
+   blocks which have been allocated starting on a host page */
+long target_mremap(unsigned long old_addr, unsigned long old_size,
+                   unsigned long new_size, unsigned long flags,
+                   unsigned long new_addr)
+{
+#ifndef __APPLE__
+    /* XXX: use 5 args syscall */
+    new_addr = (long)mremap((void *)old_addr, old_size, new_size, flags);
+    if (new_addr == -1)
+        return new_addr;
+    prot = page_get_flags(old_addr);
+    page_set_flags(old_addr, old_addr + old_size, 0);
+    page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID);
+    return new_addr;
+#else
+    qerror("target_mremap: unsupported\n");
+#endif
+
+}
+
+int target_msync(unsigned long start, unsigned long len, int flags)
+{
+    unsigned long end;
+
+    if (start & ~TARGET_PAGE_MASK)
+        return -EINVAL;
+    len = TARGET_PAGE_ALIGN(len);
+    end = start + len;
+    if (end < start)
+        return -EINVAL;
+    if (end == start)
+        return 0;
+
+    start &= qemu_host_page_mask;
+    return msync((void *)start, end - start, flags);
+}
+

Added: trunk/src/host/qemu-neo1973/darwin-user/qemu.h
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/qemu.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/qemu.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,179 @@
+#ifndef GEMU_H
+#define GEMU_H
+
+#include "thunk.h"
+
+#include <signal.h>
+#include <string.h>
+
+#include "cpu.h"
+
+#include "gdbstub.h"
+
+typedef siginfo_t target_siginfo_t;
+#define target_sigaction	sigaction
+#ifdef TARGET_I386
+struct target_pt_regs {
+	long ebx;
+	long ecx;
+	long edx;
+	long esi;
+	long edi;
+	long ebp;
+	long eax;
+	int  xds;
+	int  xes;
+	long orig_eax;
+	long eip;
+	int  xcs;
+	long eflags;
+	long esp;
+	int  xss;
+};
+struct	target_sigcontext {
+    int			sc_onstack;
+    int			sc_mask;
+    int	sc_eax;
+    int	sc_ebx;
+    int	sc_ecx;
+    int	sc_edx;
+    int	sc_edi;
+    int	sc_esi;
+    int	sc_ebp;
+    int	sc_esp;
+    int	sc_ss;
+    int	sc_eflags;
+    int	sc_eip;
+    int	sc_cs;
+    int	sc_ds;
+    int	sc_es;
+    int	sc_fs;
+    int	sc_gs;
+};
+
+#define __USER_CS	(0x17)
+#define __USER_DS	(0x1F)
+
+#elif defined(TARGET_PPC)
+struct target_pt_regs {
+	unsigned long gpr[32];
+	unsigned long nip;
+	unsigned long msr;
+	unsigned long orig_gpr3;	/* Used for restarting system calls */
+	unsigned long ctr;
+	unsigned long link;
+	unsigned long xer;
+	unsigned long ccr;
+	unsigned long mq;		/* 601 only (not used at present) */
+					/* Used on APUS to hold IPL value. */
+	unsigned long trap;		/* Reason for being here */
+	unsigned long dar;		/* Fault registers */
+	unsigned long dsisr;
+	unsigned long result; 		/* Result of a system call */
+};
+
+struct target_sigcontext {
+    int		sc_onstack;     /* sigstack state to restore */
+    int		sc_mask;        /* signal mask to restore */
+    int		sc_ir;			/* pc */
+    int		sc_psw;         /* processor status word */
+    int		sc_sp;      	/* stack pointer if sc_regs == NULL */
+    void	*sc_regs;		/* (kernel private) saved state */
+};
+
+#endif
+
+typedef struct TaskState {
+    struct TaskState *next;
+    int used; /* non zero if used */
+    uint8_t stack[0];
+} __attribute__((aligned(16))) TaskState;
+
+void syscall_init(void);
+long do_mach_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
+                uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8);
+long do_thread_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
+                uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8);
+long do_unix_syscall(void *cpu_env, int num);
+int do_sigaction(int sig, const struct sigaction *act,
+                 struct sigaction *oact);
+int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss);
+
+void gemu_log(const char *fmt, ...) __attribute__((format(printf,1,2)));
+void qerror(const char *fmt, ...);
+
+void write_dt(void *ptr, unsigned long addr, unsigned long limit, int flags);
+
+extern CPUState *global_env;
+void cpu_loop(CPUState *env);
+void init_paths(const char *prefix);
+const char *path(const char *pathname);
+
+extern int loglevel;
+extern FILE *logfile;
+
+/* commpage.c */
+void commpage_init();
+void do_commpage(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
+                uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8);
+
+/* signal.c */
+void process_pending_signals(void *cpu_env);
+void signal_init(void);
+int queue_signal(int sig, target_siginfo_t *info);
+void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
+void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
+long do_sigreturn(CPUState *env, int num);
+
+/* machload.c */
+int mach_exec(const char * filename, char ** argv, char ** envp,
+			  struct target_pt_regs * regs);
+
+/* mmap.c */
+int target_mprotect(unsigned long start, unsigned long len, int prot);
+long target_mmap(unsigned long start, unsigned long len, int prot,
+                 int flags, int fd, unsigned long offset);
+int target_munmap(unsigned long start, unsigned long len);
+long target_mremap(unsigned long old_addr, unsigned long old_size,
+                   unsigned long new_size, unsigned long flags,
+                   unsigned long new_addr);
+int target_msync(unsigned long start, unsigned long len, int flags);
+
+/* user access */
+
+/* XXX: todo protect every memory access */
+#define lock_user(x,y,z)    (void*)(x)
+#define unlock_user(x,y,z)
+
+/* Mac OS X ABI arguments processing */
+#ifdef TARGET_I386
+static inline uint32_t get_int_arg(int *i, CPUX86State *cpu_env)
+{
+    uint32_t *args = (uint32_t*)(cpu_env->regs[R_ESP] + 4 + *i);
+    *i+=4;
+    return tswap32(*args);
+}
+static inline uint64_t get_int64_arg(int *i, CPUX86State *cpu_env)
+{
+    uint64_t *args = (uint64_t*)(cpu_env->regs[R_ESP] + 4 + *i);
+    *i+=8;
+    return tswap64(*args);
+}
+#elif defined(TARGET_PPC)
+static inline uint32_t get_int_arg(int *i, CPUPPCState *cpu_env)
+{
+    /* XXX: won't work when args goes on stack after gpr10 */
+    uint32_t args = (uint32_t)(cpu_env->gpr[3+(*i & 0xff)/4]);
+    *i+=4;
+    return tswap32(args);
+}
+static inline uint64_t get_int64_arg(int *i, CPUPPCState *cpu_env)
+{
+    /* XXX: won't work when args goes on stack after gpr10 */
+    uint64_t args = (uint64_t)(cpu_env->fpr[1+(*i >> 8)/8]);
+    *i+=(8 << 8) + 8;
+    return tswap64(args);
+}
+#endif
+
+#endif

Added: trunk/src/host/qemu-neo1973/darwin-user/signal.c
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/signal.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/signal.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,463 @@
+/*
+ *  Emulation of Linux signals
+ *
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  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.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/ucontext.h>
+
+#ifdef __ia64__
+#undef uc_mcontext
+#undef uc_sigmask
+#undef uc_stack
+#undef uc_link
+#endif
+
+#include <signal.h>
+
+#include "qemu.h"
+
+#define DEBUG_SIGNAL
+
+#define MAX_SIGQUEUE_SIZE 1024
+
+struct sigqueue {
+    struct sigqueue *next;
+    target_siginfo_t info;
+};
+
+struct emulated_sigaction {
+    struct target_sigaction sa;
+    int pending; /* true if signal is pending */
+    struct sigqueue *first;
+    struct sigqueue info; /* in order to always have memory for the
+                             first signal, we put it here */
+};
+
+struct sigaltstack target_sigaltstack_used = {
+    0, 0, SA_DISABLE
+};
+
+static struct emulated_sigaction sigact_table[NSIG];
+static struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
+static struct sigqueue *first_free; /* first free siginfo queue entry */
+static int signal_pending; /* non zero if a signal may be pending */
+
+static void host_signal_handler(int host_signum, siginfo_t *info,
+                                void *puc);
+
+
+static inline int host_to_target_signal(int sig)
+{
+    return sig;
+}
+
+static inline int target_to_host_signal(int sig)
+{
+    return sig;
+}
+
+/* siginfo conversion */
+
+
+
+void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
+{
+
+}
+
+void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
+{
+
+}
+
+void signal_init(void)
+{
+    struct sigaction act;
+    int i;
+
+    /* set all host signal handlers. ALL signals are blocked during
+       the handlers to serialize them. */
+    sigfillset(&act.sa_mask);
+    act.sa_flags = SA_SIGINFO;
+    act.sa_sigaction = host_signal_handler;
+    for(i = 1; i < NSIG; i++) {
+        sigaction(i, &act, NULL);
+    }
+
+    memset(sigact_table, 0, sizeof(sigact_table));
+
+    first_free = &sigqueue_table[0];
+    for(i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++)
+        sigqueue_table[i].next = &sigqueue_table[i + 1];
+    sigqueue_table[MAX_SIGQUEUE_SIZE - 1].next = NULL;
+}
+
+/* signal queue handling */
+
+static inline struct sigqueue *alloc_sigqueue(void)
+{
+    struct sigqueue *q = first_free;
+    if (!q)
+        return NULL;
+    first_free = q->next;
+    return q;
+}
+
+static inline void free_sigqueue(struct sigqueue *q)
+{
+    q->next = first_free;
+    first_free = q;
+}
+
+/* abort execution with signal */
+void __attribute((noreturn)) force_sig(int sig)
+{
+    int host_sig;
+    host_sig = target_to_host_signal(sig);
+    fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n",
+            sig, strsignal(host_sig));
+    _exit(-host_sig);
+}
+
+/* queue a signal so that it will be send to the virtual CPU as soon
+   as possible */
+int queue_signal(int sig, target_siginfo_t *info)
+{
+    struct emulated_sigaction *k;
+    struct sigqueue *q, **pq;
+    target_ulong handler;
+
+#if defined(DEBUG_SIGNAL)
+    fprintf(stderr, "queue_signal: sig=%d\n",
+            sig);
+#endif
+    k = &sigact_table[sig - 1];
+    handler = (target_ulong)k->sa.sa_handler;
+    if (handler == SIG_DFL) {
+        /* default handler : ignore some signal. The other are fatal */
+        if (sig != SIGCHLD &&
+            sig != SIGURG &&
+            sig != SIGWINCH) {
+            force_sig(sig);
+        } else {
+            return 0; /* indicate ignored */
+        }
+    } else if (handler == host_to_target_signal(SIG_IGN)) {
+        /* ignore signal */
+        return 0;
+    } else if (handler == host_to_target_signal(SIG_ERR)) {
+        force_sig(sig);
+    } else {
+        pq = &k->first;
+        if (!k->pending) {
+            /* first signal */
+            q = &k->info;
+        } else {
+            q = alloc_sigqueue();
+            if (!q)
+                return -EAGAIN;
+            while (*pq != NULL)
+                pq = &(*pq)->next;
+        }
+        *pq = q;
+        q->info = *info;
+        q->next = NULL;
+        k->pending = 1;
+        /* signal that a new signal is pending */
+        signal_pending = 1;
+        return 1; /* indicates that the signal was queued */
+    }
+}
+
+static void host_signal_handler(int host_signum, siginfo_t *info,
+                                void *puc)
+{
+    int sig;
+    target_siginfo_t tinfo;
+
+    /* the CPU emulator uses some host signals to detect exceptions,
+       we we forward to it some signals */
+    if (host_signum == SIGSEGV || host_signum == SIGBUS
+#if defined(TARGET_I386) && defined(USE_CODE_COPY)
+        || host_signum == SIGFPE
+#endif
+        ) {
+        if (cpu_signal_handler(host_signum, (void*)info, puc))
+            return;
+    }
+
+    /* get target signal number */
+    sig = host_to_target_signal(host_signum);
+    if (sig < 1 || sig > NSIG)
+        return;
+
+#if defined(DEBUG_SIGNAL)
+	fprintf(stderr, "qemu: got signal %d\n", sig);
+#endif
+    if (queue_signal(sig, &tinfo) == 1) {
+        /* interrupt the virtual CPU as soon as possible */
+        cpu_interrupt(global_env, CPU_INTERRUPT_EXIT);
+    }
+}
+
+int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss)
+{
+    /* XXX: test errors */
+    if(oss)
+    {
+        oss->ss_sp = tswap32(target_sigaltstack_used.ss_sp);
+        oss->ss_size = tswap32(target_sigaltstack_used.ss_size);
+        oss->ss_flags = tswap32(target_sigaltstack_used.ss_flags);
+    }
+    if(ss)
+    {
+        target_sigaltstack_used.ss_sp = tswap32(ss->ss_sp);
+        target_sigaltstack_used.ss_size = tswap32(ss->ss_size);
+        target_sigaltstack_used.ss_flags = tswap32(ss->ss_flags);
+    }
+    return 0;
+}
+
+int do_sigaction(int sig, const struct sigaction *act,
+                 struct sigaction *oact)
+{
+    struct emulated_sigaction *k;
+    struct sigaction act1;
+    int host_sig;
+
+    if (sig < 1 || sig > NSIG)
+        return -EINVAL;
+
+    k = &sigact_table[sig - 1];
+#if defined(DEBUG_SIGNAL)
+    fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",
+            sig, (int)act, (int)oact);
+#endif
+    if (oact) {
+#if defined(DEBUG_SIGNAL)
+    fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",
+            sig, (int)act, (int)oact);
+#endif
+
+        oact->sa_handler = tswapl(k->sa.sa_handler);
+        oact->sa_flags = tswapl(k->sa.sa_flags);
+        oact->sa_mask = tswapl(k->sa.sa_mask);
+    }
+    if (act) {
+#if defined(DEBUG_SIGNAL)
+    fprintf(stderr, "sigaction handler 0x%x flag 0x%x mask 0x%x\n",
+            act->sa_handler, act->sa_flags, act->sa_mask);
+#endif
+
+        k->sa.sa_handler = tswapl(act->sa_handler);
+        k->sa.sa_flags = tswapl(act->sa_flags);
+        k->sa.sa_mask = tswapl(act->sa_mask);
+        /* we update the host signal state */
+        host_sig = target_to_host_signal(sig);
+        if (host_sig != SIGSEGV && host_sig != SIGBUS) {
+#if defined(DEBUG_SIGNAL)
+    fprintf(stderr, "sigaction handler going to call sigaction\n",
+            act->sa_handler, act->sa_flags, act->sa_mask);
+#endif
+
+            sigfillset(&act1.sa_mask);
+            act1.sa_flags = SA_SIGINFO;
+            if (k->sa.sa_flags & SA_RESTART)
+                act1.sa_flags |= SA_RESTART;
+            /* NOTE: it is important to update the host kernel signal
+               ignore state to avoid getting unexpected interrupted
+               syscalls */
+            if (k->sa.sa_handler == SIG_IGN) {
+                act1.sa_sigaction = (void *)SIG_IGN;
+            } else if (k->sa.sa_handler == SIG_DFL) {
+                act1.sa_sigaction = (void *)SIG_DFL;
+            } else {
+                act1.sa_sigaction = host_signal_handler;
+            }
+            sigaction(host_sig, &act1, NULL);
+        }
+    }
+    return 0;
+}
+
+
+#ifdef TARGET_I386
+
+static inline void *
+get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size)
+{
+    /* XXX Fix that */
+    if(target_sigaltstack_used.ss_flags & SA_DISABLE)
+    {
+        int esp;
+        /* Default to using normal stack */
+        esp = env->regs[R_ESP];
+
+        return (void *)((esp - frame_size) & -8ul);
+    }
+    else
+    {
+        return target_sigaltstack_used.ss_sp;
+    }
+}
+
+static void setup_frame(int sig, struct emulated_sigaction *ka,
+			void *set, CPUState *env)
+{
+	void *frame;
+	int i, err = 0;
+
+    fprintf(stderr, "setup_frame %d\n", sig);
+	frame = get_sigframe(ka, env, sizeof(*frame));
+
+	/* Set up registers for signal handler */
+	env->regs[R_ESP] = (unsigned long) frame;
+	env->eip = (unsigned long) ka->sa.sa_handler;
+
+	env->eflags &= ~TF_MASK;
+
+	return;
+
+give_sigsegv:
+	if (sig == SIGSEGV)
+		ka->sa.sa_handler = SIG_DFL;
+	force_sig(SIGSEGV /* , current */);
+}
+
+long do_sigreturn(CPUState *env, int num)
+{
+    int i = 0;
+    struct target_sigcontext *scp = get_int_arg(&i, env);
+    /* XXX Get current signal number */
+    /* XXX Adjust accordin to sc_onstack, sc_mask */
+    if(tswapl(scp->sc_onstack) & 0x1)
+        target_sigaltstack_used.ss_flags |= ~SA_DISABLE;
+    else
+        target_sigaltstack_used.ss_flags &=  SA_DISABLE;
+    int set = tswapl(scp->sc_eax);
+    sigprocmask(SIG_SETMASK, &set, NULL);
+
+    fprintf(stderr, "do_sigreturn: partially implemented %x EAX:%x EBX:%x\n", scp->sc_mask, tswapl(scp->sc_eax), tswapl(scp->sc_ebx));
+    fprintf(stderr, "ECX:%x EDX:%x EDI:%x\n", scp->sc_ecx, tswapl(scp->sc_edx), tswapl(scp->sc_edi));
+    fprintf(stderr, "EIP:%x\n", tswapl(scp->sc_eip));
+
+    env->regs[R_EAX] = tswapl(scp->sc_eax);
+    env->regs[R_EBX] = tswapl(scp->sc_ebx);
+    env->regs[R_ECX] = tswapl(scp->sc_ecx);
+    env->regs[R_EDX] = tswapl(scp->sc_edx);
+    env->regs[R_EDI] = tswapl(scp->sc_edi);
+    env->regs[R_ESI] = tswapl(scp->sc_esi);
+    env->regs[R_EBP] = tswapl(scp->sc_ebp);
+    env->regs[R_ESP] = tswapl(scp->sc_esp);
+    env->segs[R_SS].selector = (void*)tswapl(scp->sc_ss);
+    env->eflags = tswapl(scp->sc_eflags);
+    env->eip = tswapl(scp->sc_eip);
+    env->segs[R_CS].selector = (void*)tswapl(scp->sc_cs);
+    env->segs[R_DS].selector = (void*)tswapl(scp->sc_ds);
+    env->segs[R_ES].selector = (void*)tswapl(scp->sc_es);
+    env->segs[R_FS].selector = (void*)tswapl(scp->sc_fs);
+    env->segs[R_GS].selector = (void*)tswapl(scp->sc_gs);
+
+    /* Again, because our caller's caller will reset EAX */
+    return env->regs[R_EAX];
+}
+
+#else
+
+static void setup_frame(int sig, struct emulated_sigaction *ka,
+			void *set, CPUState *env)
+{
+    fprintf(stderr, "setup_frame: not implemented\n");
+}
+
+long do_sigreturn(CPUState *env, int num)
+{
+    int i = 0;
+    struct target_sigcontext *scp = get_int_arg(&i, env);
+    fprintf(stderr, "do_sigreturn: not implemented\n");
+    return -ENOSYS;
+}
+
+#endif
+
+void process_pending_signals(void *cpu_env)
+{
+    struct emulated_sigaction *k;
+    struct sigqueue *q;
+    target_ulong handler;
+    int sig;
+
+    if (!signal_pending)
+        return;
+
+    k = sigact_table;
+
+    for(sig = 1; sig <= NSIG; sig++) {
+        if (k->pending)
+            goto handle_signal;
+        k++;
+    }
+
+    /* if no signal is pending, just return */
+    signal_pending = 0;
+    return;
+handle_signal:
+    #ifdef DEBUG_SIGNAL
+    fprintf(stderr, "qemu: process signal %d\n", sig);
+    #endif
+    /* dequeue signal */
+    q = k->first;
+    k->first = q->next;
+    if (!k->first)
+        k->pending = 0;
+
+    sig = gdb_handlesig (cpu_env, sig);
+    if (!sig) {
+        fprintf (stderr, "Lost signal\n");
+        abort();
+    }
+
+    handler = k->sa.sa_handler;
+    if (handler == SIG_DFL) {
+        /* default handler : ignore some signal. The other are fatal */
+        if (sig != SIGCHLD &&
+            sig != SIGURG &&
+            sig != SIGWINCH) {
+            force_sig(sig);
+        }
+    } else if (handler == SIG_IGN) {
+        /* ignore sig */
+    } else if (handler == SIG_ERR) {
+        force_sig(sig);
+    } else {
+
+        setup_frame(sig, k, 0, cpu_env);
+	if (k->sa.sa_flags & SA_RESETHAND)
+            k->sa.sa_handler = SIG_DFL;
+    }
+    if (q != &k->info)
+        free_sigqueue(q);
+}
+
+

Added: trunk/src/host/qemu-neo1973/darwin-user/syscall.c
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/syscall.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/syscall.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,1567 @@
+/*
+ *  Darwin syscalls
+ *
+ *  Copyright (c) 2003 Fabrice Bellard
+ *  Copyright (c) 2006 Pierre d'Herbemont
+ *
+ *  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.
+ */
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <mach/host_info.h>
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+#include <mach/message.h>
+
+#include <pthread.h>
+#include <dirent.h>
+
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/dirent.h>
+#include <sys/uio.h>
+#include <sys/termios.h>
+#include <sys/ptrace.h>
+#include <net/if.h>
+
+#include <sys/param.h>
+#include <sys/mount.h>
+
+#include <sys/attr.h>
+
+#include <mach/ndr.h>
+#include <mach/mig_errors.h>
+
+#include <sys/xattr.h>
+
+#include "qemu.h"
+
+//#define DEBUG_SYSCALL
+
+#ifdef DEBUG_SYSCALL
+# define DEBUG_FORCE_ENABLE_LOCAL() int __DEBUG_qemu_user_force_enable = 1
+# define DEBUG_BEGIN_ENABLE  __DEBUG_qemu_user_force_enable = 1;
+# define DEBUG_END_ENABLE  __DEBUG_qemu_user_force_enable = 0;
+
+# define DEBUG_DISABLE_ALL() static int __DEBUG_qemu_user_force_enable = 0
+# define DEBUG_ENABLE_ALL()  static int __DEBUG_qemu_user_force_enable = 1
+    DEBUG_ENABLE_ALL();
+
+# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); \
+                           if(__DEBUG_qemu_user_force_enable) fprintf(stderr, __VA_ARGS__); \
+                         } while(0)
+#else
+# define DEBUG_FORCE_ENABLE_LOCAL()
+# define DEBUG_BEGIN_ENABLE
+# define DEBUG_END_ENABLE
+
+# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); } while(0)
+#endif
+
+enum {
+    bswap_out = 0,
+    bswap_in = 1
+};
+
+extern const char *interp_prefix;
+
+static inline long get_errno(long ret)
+{
+    if (ret == -1)
+        return -errno;
+    else
+        return ret;
+}
+
+static inline int is_error(long ret)
+{
+    return (unsigned long)ret >= (unsigned long)(-4096);
+}
+
+/* ------------------------------------------------------------
+   Mach syscall handling
+*/
+
+void static inline print_description_msg_header(mach_msg_header_t *hdr)
+{
+    char *name = NULL;
+    int i;
+    struct { int number; char *name; } msg_name[] =
+    {
+        /* see http://fxr.watson.org/fxr/source/compat/mach/mach_namemap.c?v=NETBSD */
+        { 200,      "host_info" },
+        { 202,      "host_page_size" },
+        { 206,      "host_get_clock_service" },
+        { 206,      "host_get_clock_service" },
+        { 206,      "host_get_clock_service" },
+        { 306,      "host_get_clock_service" },
+        { 3204,     "mach_port_allocate" },
+        { 3206,     "mach_port_deallocate" },
+        { 3404,     "mach_ports_lookup" },
+        { 3409,     "mach_task_get_special_port" },
+        { 3414,     "mach_task_get_exception_ports" },
+        { 3418,     "mach_semaphore_create" },
+        { 3504,     "mach_semaphore_create" },
+        { 3509,     "mach_semaphore_create" },
+        { 3518,     "semaphore_create" },
+        { 3616,     "thread_policy" },
+        { 3801,     "vm_allocate" },
+        { 3802,     "vm_deallocate" },
+        { 3802,     "vm_deallocate" },
+        { 3803,     "vm_protect" },
+        { 3812,     "vm_map" },
+        { 4241776,  "lu_message_send_id" },  /* lookupd */
+        { 4241876,  "lu_message_reply_id" }, /* lookupd */
+    };
+
+    for(i = 0; i < sizeof(msg_name)/sizeof(msg_name[0]); i++) {
+        if(msg_name[i].number == hdr->msgh_id)
+        {
+            name = msg_name[i].name;
+            break;
+        }
+    }
+    if(!name)
+        DPRINTF("unknown mach msg %d 0x%x\n", hdr->msgh_id, hdr->msgh_id);
+    else
+        DPRINTF("%s\n", name);
+#if 0
+    DPRINTF("Bits: %8x\n", hdr->msgh_bits);
+    DPRINTF("Size: %8x\n", hdr->msgh_size);
+    DPRINTF("Rmte: %8x\n", hdr->msgh_remote_port);
+    DPRINTF("Locl: %8x\n", hdr->msgh_local_port);
+    DPRINTF("Rsrv: %8x\n", hdr->msgh_reserved);
+
+    DPRINTF("Id  : %8x\n", hdr->msgh_id);
+
+    NDR_record_t *ndr = (NDR_record_t *)(hdr + 1);
+    DPRINTF("hdr = %p, sizeof(hdr) = %x, NDR = %p\n", hdr, (unsigned int)sizeof(mach_msg_header_t), ndr);
+    DPRINTF("%d %d %d %d %d %d %d %d\n",
+           ndr->mig_vers, ndr->if_vers, ndr->reserved1, ndr->mig_encoding,
+           ndr->int_rep, ndr->char_rep, ndr->float_rep, ndr->reserved2);
+#endif
+}
+
+static inline void print_mach_msg_return(mach_msg_return_t ret)
+{
+    int i, found = 0;
+#define MACH_MSG_RET(msg) { msg, #msg }
+    struct { int code; char *name; } msg_name[] =
+    {
+        /* ref: http://darwinsource.opendarwin.org/10.4.2/xnu-792.2.4/osfmk/man/mach_msg.html */
+        /* send message */
+        MACH_MSG_RET(MACH_SEND_MSG_TOO_SMALL),
+        MACH_MSG_RET(MACH_SEND_NO_BUFFER),
+        MACH_MSG_RET(MACH_SEND_INVALID_DATA),
+        MACH_MSG_RET(MACH_SEND_INVALID_HEADER),
+        MACH_MSG_RET(MACH_SEND_INVALID_DEST),
+        MACH_MSG_RET(MACH_SEND_INVALID_NOTIFY),
+        MACH_MSG_RET(MACH_SEND_INVALID_REPLY),
+        MACH_MSG_RET(MACH_SEND_INVALID_TRAILER),
+        MACH_MSG_RET(MACH_SEND_INVALID_MEMORY),
+        MACH_MSG_RET(MACH_SEND_INVALID_RIGHT),
+        MACH_MSG_RET(MACH_SEND_INVALID_TYPE),
+        MACH_MSG_RET(MACH_SEND_INTERRUPTED),
+        MACH_MSG_RET(MACH_SEND_TIMED_OUT),
+
+        MACH_MSG_RET(MACH_RCV_BODY_ERROR),
+        MACH_MSG_RET(MACH_RCV_HEADER_ERROR),
+
+        MACH_MSG_RET(MACH_RCV_IN_SET),
+        MACH_MSG_RET(MACH_RCV_INTERRUPTED),
+
+        MACH_MSG_RET(MACH_RCV_INVALID_DATA),
+        MACH_MSG_RET(MACH_RCV_INVALID_NAME),
+        MACH_MSG_RET(MACH_RCV_INVALID_NOTIFY),
+        MACH_MSG_RET(MACH_RCV_INVALID_TRAILER),
+        MACH_MSG_RET(MACH_RCV_INVALID_TYPE),
+
+        MACH_MSG_RET(MACH_RCV_PORT_CHANGED),
+        MACH_MSG_RET(MACH_RCV_PORT_DIED),
+
+        MACH_MSG_RET(MACH_RCV_SCATTER_SMALL),
+        MACH_MSG_RET(MACH_RCV_TIMED_OUT),
+        MACH_MSG_RET(MACH_RCV_TOO_LARGE)
+    };
+#undef MACH_MSG_RET
+
+    if( ret == MACH_MSG_SUCCESS)
+        DPRINTF("MACH_MSG_SUCCESS\n");
+    else
+    {
+        for( i = 0; i < sizeof(msg_name)/sizeof(msg_name[0]); i++) {
+            if(msg_name[i].code == ret) {
+                DPRINTF("%s\n", msg_name[i].name);
+                found = 1;
+                break;
+            }
+        }
+        if(!found)
+            qerror("unknow mach message ret code %d\n", ret);
+    }
+}
+
+static inline void swap_mach_msg_header(mach_msg_header_t *hdr)
+{
+    hdr->msgh_bits = tswap32(hdr->msgh_bits);
+    hdr->msgh_size = tswap32(hdr->msgh_size);
+    hdr->msgh_remote_port = tswap32(hdr->msgh_remote_port);
+    hdr->msgh_local_port = tswap32(hdr->msgh_local_port);
+    hdr->msgh_reserved = tswap32(hdr->msgh_reserved);
+    hdr->msgh_id = tswap32(hdr->msgh_id);
+}
+
+struct complex_msg {
+            mach_msg_header_t hdr;
+            mach_msg_body_t body;
+};
+
+static inline void swap_mach_msg_body(struct complex_msg *complex_msg, int bswap)
+{
+    mach_msg_port_descriptor_t *descr = (mach_msg_port_descriptor_t *)(complex_msg+1);
+    int i,j;
+
+    if(bswap == bswap_in)
+        tswap32s(&complex_msg->body.msgh_descriptor_count);
+
+    DPRINTF("body.msgh_descriptor_count %d\n", complex_msg->body.msgh_descriptor_count);
+
+    for(i = 0; i < complex_msg->body.msgh_descriptor_count; i++) {
+        switch(descr->type)
+        {
+            case MACH_MSG_PORT_DESCRIPTOR:
+                tswap32s(&descr->name);
+                descr++;
+                break;
+            case MACH_MSG_OOL_DESCRIPTOR:
+            {
+                mach_msg_ool_descriptor_t *ool = (void *)descr;
+                tswap32s((uint32_t *)&ool->address);
+                tswap32s(&ool->size);
+
+                descr = (mach_msg_port_descriptor_t *)(ool+1);
+                break;
+            }
+            case MACH_MSG_OOL_PORTS_DESCRIPTOR:
+            {
+                mach_msg_ool_ports_descriptor_t *ool_ports = (void *)descr;
+                mach_port_name_t * port_names;
+
+                if(bswap == bswap_in)
+                {
+                    tswap32s((uint32_t *)&ool_ports->address);
+                    tswap32s(&ool_ports->count);
+                }
+
+                port_names = ool_ports->address;
+
+                for(j = 0; j < ool_ports->count; j++)
+                    tswap32s(&port_names[j]);
+
+                if(bswap == bswap_out)
+                {
+                    tswap32s((uint32_t *)&ool_ports->address);
+                    tswap32s(&ool_ports->count);
+                }
+
+                descr = (mach_msg_port_descriptor_t *)(ool_ports+1);
+                break;
+            }
+            default: qerror("unknow mach msg descriptor type %x\n", descr->type);
+        }
+    }
+    if(bswap == bswap_out)
+        tswap32s(&complex_msg->body.msgh_descriptor_count);
+}
+
+static inline void swap_mach_msg(mach_msg_header_t *hdr, int bswap)
+{
+    if (bswap == bswap_out && hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
+        swap_mach_msg_body((struct complex_msg *)hdr, bswap);
+
+    swap_mach_msg_header(hdr);
+
+    if (bswap == bswap_in && hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
+        swap_mach_msg_body((struct complex_msg *)hdr, bswap);
+}
+
+static inline uint32_t target_mach_msg_trap(
+        mach_msg_header_t *hdr, uint32_t options, uint32_t send_size,
+        uint32_t rcv_size, uint32_t rcv_name, uint32_t time_out, uint32_t notify)
+{
+    extern int mach_msg_trap(mach_msg_header_t *, mach_msg_option_t,
+          mach_msg_size_t, mach_msg_size_t, mach_port_t,
+          mach_msg_timeout_t, mach_port_t);
+    mach_msg_audit_trailer_t *trailer;
+    mach_msg_id_t msg_id;
+    uint32_t ret = 0;
+    int i;
+
+    swap_mach_msg(hdr, bswap_in);
+
+    msg_id = hdr->msgh_id;
+
+    print_description_msg_header(hdr);
+
+    ret = mach_msg_trap(hdr, options, send_size, rcv_size, rcv_name, time_out, notify);
+
+    print_mach_msg_return(ret);
+
+    if( (options & MACH_RCV_MSG) && (REQUESTED_TRAILER_SIZE(options) > 0) )
+    {
+        /* XXX: the kernel always return the full trailer with MACH_SEND_MSG, so we should
+                probably always bswap it  */
+        /* warning: according to Mac OS X Internals (the book) msg_size might be expressed in
+                    natural_t units but according to xnu/osfmk/mach/message.h: "The size of
+                    the message must be specified in bytes" */
+        trailer = (mach_msg_audit_trailer_t *)((uint8_t *)hdr + hdr->msgh_size);
+        /* XXX: Should probably do that based on the option asked by the sender, but dealing
+        with kernel answer seems more sound */
+        switch(trailer->msgh_trailer_size)
+        {
+            case sizeof(mach_msg_audit_trailer_t):
+                for(i = 0; i < 8; i++)
+                    tswap32s(&trailer->msgh_audit.val[i]);
+                /* Fall in mach_msg_security_trailer_t case */
+            case sizeof(mach_msg_security_trailer_t):
+                tswap32s(&trailer->msgh_sender.val[0]);
+                tswap32s(&trailer->msgh_sender.val[1]);
+                /* Fall in mach_msg_seqno_trailer_t case */
+            case sizeof(mach_msg_seqno_trailer_t):
+                tswap32s(&trailer->msgh_seqno);
+                /* Fall in mach_msg_trailer_t case */
+            case sizeof(mach_msg_trailer_t):
+                tswap32s(&trailer->msgh_trailer_type);
+                tswap32s(&trailer->msgh_trailer_size);
+                break;
+            case 0:
+                /* Safer not to byteswap, but probably wrong */
+                break;
+            default:
+                qerror("unknow trailer type given its size %d\n", trailer->msgh_trailer_size);
+                break;
+        }
+    }
+
+    /* Special message handling */
+    switch (msg_id) {
+        case 200: /* host_info */
+        {
+            mig_reply_error_t *err = (mig_reply_error_t *)hdr;
+            struct {
+                uint32_t unknow1;
+                uint32_t max_cpus;
+                uint32_t avail_cpus;
+                uint32_t memory_size;
+                uint32_t cpu_type;
+                uint32_t cpu_subtype;
+            } *data = (void *)(err+1);
+
+            DPRINTF("maxcpu = 0x%x\n",   data->max_cpus);
+            DPRINTF("numcpu = 0x%x\n",   data->avail_cpus);
+            DPRINTF("memsize = 0x%x\n",  data->memory_size);
+
+#if defined(TARGET_I386)
+            data->cpu_type = CPU_TYPE_I386;
+            DPRINTF("cpu_type changed to 0x%x(i386)\n", data->cpu_type);
+            data->cpu_subtype = CPU_SUBTYPE_PENT;
+            DPRINTF("cpu_subtype changed to 0x%x(i386_pent)\n", data->cpu_subtype);
+#elif defined(TARGET_PPC)
+            data->cpu_type = CPU_TYPE_POWERPC;
+            DPRINTF("cpu_type changed to 0x%x(ppc)\n", data->cpu_type);
+            data->cpu_subtype = CPU_SUBTYPE_POWERPC_750;
+            DPRINTF("cpu_subtype changed to 0x%x(ppc_all)\n", data->cpu_subtype);
+#else
+# error target not supported
+#endif
+            break;
+        }
+        case 202: /* host_page_size */
+        {
+            mig_reply_error_t *err = (mig_reply_error_t *)hdr;
+            uint32_t *pagesize = (uint32_t *)(err+1);
+
+            DPRINTF("pagesize = %d\n", *pagesize);
+            break;
+        }
+        default: break;
+    }
+
+    swap_mach_msg(hdr, bswap_out);
+
+    return ret;
+}
+
+long do_mach_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
+                uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
+                uint32_t arg8)
+{
+    extern uint32_t mach_reply_port();
+
+    long ret = 0;
+
+    arg1 = tswap32(arg1);
+    arg2 = tswap32(arg2);
+    arg3 = tswap32(arg3);
+    arg4 = tswap32(arg4);
+    arg5 = tswap32(arg5);
+    arg6 = tswap32(arg6);
+    arg7 = tswap32(arg7);
+    arg8 = tswap32(arg8);
+
+    DPRINTF("mach syscall %d : " , num);
+
+    switch(num) {
+    /* see xnu/osfmk/mach/syscall_sw.h */
+    case -26:
+        DPRINTF("mach_reply_port()\n");
+        ret = mach_reply_port();
+        break;
+    case -27:
+        DPRINTF("mach_thread_self()\n");
+        ret = mach_thread_self();
+        break;
+    case -28:
+        DPRINTF("mach_task_self()\n");
+        ret = mach_task_self();
+        break;
+    case -29:
+        DPRINTF("mach_host_self()\n");
+        ret = mach_host_self();
+        break;
+    case -31:
+        DPRINTF("mach_msg_trap(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
+                arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+        ret = target_mach_msg_trap((mach_msg_header_t *)arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+        break;
+/* may need more translation if target arch is different from host */
+#if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
+    case -33:
+        DPRINTF("semaphore_signal_trap(0x%x)\n", arg1);
+        ret = semaphore_signal_trap(arg1);
+        break;
+    case -34:
+        DPRINTF("semaphore_signal_all_trap(0x%x)\n", arg1);
+        ret = semaphore_signal_all_trap(arg1);
+        break;
+    case -35:
+        DPRINTF("semaphore_signal_thread_trap(0x%x)\n", arg1, arg2);
+        ret = semaphore_signal_thread_trap(arg1,arg2);
+        break;
+#endif
+    case -36:
+        DPRINTF("semaphore_wait_trap(0x%x)\n", arg1);
+        extern int semaphore_wait_trap(int); // XXX: is there any header for that?
+        ret = semaphore_wait_trap(arg1);
+        break;
+/* may need more translation if target arch is different from host */
+#if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
+    case -37:
+        DPRINTF("semaphore_wait_signal_trap(0x%x, 0x%x)\n", arg1, arg2);
+        ret = semaphore_wait_signal_trap(arg1,arg2);
+        break;
+#endif
+    case -43:
+        DPRINTF("map_fd(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
+                arg1, arg2, arg3, arg4, arg5);
+        ret = map_fd(arg1, arg2, (void*)arg3, arg4, arg5);
+        tswap32s((uint32_t*)arg3);
+        break;
+/* may need more translation if target arch is different from host */
+#if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
+    case -61:
+        DPRINTF("syscall_thread_switch(0x%x, 0x%x, 0x%x)\n",
+                arg1, arg2, arg3);
+        ret = syscall_thread_switch(arg1, arg2, arg3);  // just a hint to the scheduler; can drop?
+        break;
+#endif
+    case -89:
+        DPRINTF("mach_timebase_info(0x%x)\n", arg1);
+        struct mach_timebase_info info;
+        ret = mach_timebase_info(&info);
+        if(!is_error(ret))
+        {
+            struct mach_timebase_info *outInfo = (void*)arg1;
+            outInfo->numer = tswap32(info.numer);
+            outInfo->denom = tswap32(info.denom);
+        }
+        break;
+    case -90:
+        DPRINTF("mach_wait_until()\n");
+        extern int mach_wait_until(uint64_t); // XXX: is there any header for that?
+        ret = mach_wait_until(((uint64_t)arg2<<32) | (uint64_t)arg1);
+        break;
+    case -91:
+        DPRINTF("mk_timer_create()\n");
+        extern int mk_timer_create(); // XXX: is there any header for that?
+        ret = mk_timer_create();
+        break;
+    case -92:
+        DPRINTF("mk_timer_destroy()\n");
+        extern int mk_timer_destroy(int); // XXX: is there any header for that?
+        ret = mk_timer_destroy(arg1);
+        break;
+    case -93:
+        DPRINTF("mk_timer_create()\n");
+        extern int mk_timer_arm(int, uint64_t); // XXX: is there any header for that?
+        ret = mk_timer_arm(arg1, ((uint64_t)arg3<<32) | (uint64_t)arg2);
+        break;
+    case -94:
+        DPRINTF("mk_timer_cancel()\n");
+        extern int mk_timer_cancel(int, uint64_t *); // XXX: is there any header for that?
+        ret = mk_timer_cancel(arg1, (uint64_t *)arg2);
+        if((!is_error(ret)) && arg2)
+            tswap64s((uint64_t *)arg2);
+        break;
+    default:
+        gemu_log("qemu: Unsupported mach syscall: %d(0x%x)\n", num, num);
+        gdb_handlesig (cpu_env, SIGTRAP);
+        exit(0);
+        break;
+    }
+    return ret;
+}
+
+/* ------------------------------------------------------------
+   thread type syscall handling
+*/
+long do_thread_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
+                uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
+                uint32_t arg8)
+{
+    extern uint32_t cthread_set_self(uint32_t);
+    extern uint32_t processor_facilities_used();
+    long ret = 0;
+
+    arg1 = tswap32(arg1);
+    arg2 = tswap32(arg2);
+    arg3 = tswap32(arg3);
+    arg4 = tswap32(arg4);
+    arg5 = tswap32(arg5);
+    arg6 = tswap32(arg6);
+    arg7 = tswap32(arg7);
+    arg8 = tswap32(arg8);
+
+    DPRINTF("thread syscall %d : " , num);
+
+    switch(num) {
+#ifdef TARGET_I386
+    case 0x3:
+#endif
+    case 0x7FF1: /* cthread_set_self */
+        DPRINTF("cthread_set_self(0x%x)\n", (unsigned int)arg1);
+        ret = cthread_set_self(arg1);
+#ifdef TARGET_I386
+        /* we need to update the LDT with the address of the thread */
+        write_dt((void *)(((CPUX86State *) cpu_env)->ldt.base + (4 * sizeof(uint64_t))), arg1, 1,
+                 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
+                 (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
+        /* New i386 convention, %gs should be set to our this LDT entry */
+        cpu_x86_load_seg(cpu_env, R_GS, 0x27);
+        /* Old i386 convention, the kernel returns the selector for the cthread (pre-10.4.8?)*/
+        ret = 0x27;
+#endif
+        break;
+    case 0x7FF2: /* Called the super-fast pthread_self handler by the apple guys */
+        DPRINTF("pthread_self()\n");
+        ret = (uint32_t)pthread_self();
+        break;
+    case 0x7FF3:
+        DPRINTF("processor_facilities_used()\n");
+#ifdef __i386__
+        qerror("processor_facilities_used: not implemented!\n");
+#else
+        ret = (uint32_t)processor_facilities_used();
+#endif
+        break;
+    default:
+        gemu_log("qemu: Unsupported thread syscall: %d(0x%x)\n", num, num);
+        gdb_handlesig (cpu_env, SIGTRAP);
+        exit(0);
+        break;
+    }
+    return ret;
+}
+
+/* ------------------------------------------------------------
+   ioctl handling
+*/
+static inline void byteswap_termios(struct termios *t)
+{
+    tswap32s((uint32_t*)&t->c_iflag);
+    tswap32s((uint32_t*)&t->c_oflag);
+    tswap32s((uint32_t*)&t->c_cflag);
+    tswap32s((uint32_t*)&t->c_lflag);
+    /* 20 (char) bytes then */
+    tswap32s((uint32_t*)&t->c_ispeed);
+    tswap32s((uint32_t*)&t->c_ospeed);
+}
+
+static inline void byteswap_winsize(struct winsize *w)
+{
+    tswap16s(&w->ws_row);
+    tswap16s(&w->ws_col);
+    tswap16s(&w->ws_xpixel);
+    tswap16s(&w->ws_ypixel);
+}
+
+#define STRUCT(name, list...) STRUCT_ ## name,
+#define STRUCT_SPECIAL(name) STRUCT_ ## name,
+enum {
+#include "ioctls_types.h"
+};
+#undef STRUCT
+#undef STRUCT_SPECIAL
+
+#define STRUCT(name, list...) const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
+#define STRUCT_SPECIAL(name)
+#include "ioctls_types.h"
+#undef STRUCT
+#undef STRUCT_SPECIAL
+
+typedef struct IOCTLEntry {
+    unsigned int target_cmd;
+    unsigned int host_cmd;
+    const char *name;
+    int access;
+    const argtype arg_type[5];
+} IOCTLEntry;
+
+#define IOC_R 0x0001
+#define IOC_W 0x0002
+#define IOC_RW (IOC_R | IOC_W)
+
+#define MAX_STRUCT_SIZE 4096
+
+IOCTLEntry ioctl_entries[] = {
+#define IOCTL(cmd, access, types...) \
+    { cmd, cmd, #cmd, access, { types } },
+#include "ioctls.h"
+    { 0, 0, },
+};
+
+/* ??? Implement proper locking for ioctls.  */
+static long do_ioctl(long fd, long cmd, long arg)
+{
+    const IOCTLEntry *ie;
+    const argtype *arg_type;
+    int ret;
+    uint8_t buf_temp[MAX_STRUCT_SIZE];
+    int target_size;
+    void *argptr;
+
+    ie = ioctl_entries;
+    for(;;) {
+        if (ie->target_cmd == 0) {
+            gemu_log("Unsupported ioctl: cmd=0x%04lx\n", cmd);
+            return -ENOSYS;
+        }
+        if (ie->target_cmd == cmd)
+            break;
+        ie++;
+    }
+    arg_type = ie->arg_type;
+#if defined(DEBUG)
+    gemu_log("ioctl: cmd=0x%04lx (%s)\n", cmd, ie->name);
+#endif
+    switch(arg_type[0]) {
+    case TYPE_NULL:
+        /* no argument */
+        ret = get_errno(ioctl(fd, ie->host_cmd));
+        break;
+    case TYPE_PTRVOID:
+    case TYPE_INT:
+        /* int argment */
+        ret = get_errno(ioctl(fd, ie->host_cmd, arg));
+        break;
+    case TYPE_PTR:
+        arg_type++;
+        target_size = thunk_type_size(arg_type, 0);
+        switch(ie->access) {
+        case IOC_R:
+            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
+            if (!is_error(ret)) {
+                argptr = lock_user(arg, target_size, 0);
+                thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
+                unlock_user(argptr, arg, target_size);
+            }
+            break;
+        case IOC_W:
+            argptr = lock_user(arg, target_size, 1);
+            thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
+            unlock_user(argptr, arg, 0);
+            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
+            break;
+        default:
+        case IOC_RW:
+            argptr = lock_user(arg, target_size, 1);
+            thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
+            unlock_user(argptr, arg, 0);
+            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
+            if (!is_error(ret)) {
+                argptr = lock_user(arg, target_size, 0);
+                thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
+                unlock_user(argptr, arg, target_size);
+            }
+            break;
+        }
+        break;
+    default:
+        gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n", cmd, arg_type[0]);
+        ret = -ENOSYS;
+        break;
+    }
+    return ret;
+}
+
+/* ------------------------------------------------------------
+   Unix syscall handling
+*/
+
+static inline void byteswap_attrlist(struct attrlist *a)
+{
+    tswap16s(&a->bitmapcount);
+    tswap16s(&a->reserved);
+    tswap32s(&a->commonattr);
+    tswap32s(&a->volattr);
+    tswap32s(&a->dirattr);
+    tswap32s(&a->fileattr);
+    tswap32s(&a->forkattr);
+}
+
+struct attrbuf_header {
+    unsigned long length;
+};
+
+static inline void byteswap_attrbuf(struct attrbuf_header *attrbuf, struct attrlist *attrlist)
+{
+    DPRINTF("attrBuf.lenght %lx\n", attrbuf->length);
+}
+
+static inline void byteswap_statfs(struct statfs *s)
+{
+    tswap16s((uint16_t*)&s->f_otype);
+    tswap16s((uint16_t*)&s->f_oflags);
+    tswap32s((uint32_t*)&s->f_bsize);
+    tswap32s((uint32_t*)&s->f_iosize);
+    tswap32s((uint32_t*)&s->f_blocks);
+    tswap32s((uint32_t*)&s->f_bfree);
+    tswap32s((uint32_t*)&s->f_bavail);
+    tswap32s((uint32_t*)&s->f_files);
+    tswap32s((uint32_t*)&s->f_ffree);
+    tswap32s((uint32_t*)&s->f_fsid.val[0]);
+    tswap32s((uint32_t*)&s->f_fsid.val[1]);
+    tswap16s((uint16_t*)&s->f_reserved1);
+    tswap16s((uint16_t*)&s->f_type);
+    tswap32s((uint32_t*)&s->f_flags);
+}
+
+static inline void byteswap_stat(struct stat *s)
+{
+    tswap32s((uint32_t*)&s->st_dev);
+    tswap32s(&s->st_ino);
+    tswap16s(&s->st_mode);
+    tswap16s(&s->st_nlink);
+    tswap32s(&s->st_uid);
+    tswap32s(&s->st_gid);
+    tswap32s((uint32_t*)&s->st_rdev);
+    tswap32s((uint32_t*)&s->st_atimespec.tv_sec);
+    tswap32s((uint32_t*)&s->st_atimespec.tv_nsec);
+    tswap32s((uint32_t*)&s->st_mtimespec.tv_sec);
+    tswap32s((uint32_t*)&s->st_mtimespec.tv_nsec);
+    tswap32s((uint32_t*)&s->st_ctimespec.tv_sec);
+    tswap32s((uint32_t*)&s->st_ctimespec.tv_nsec);
+    tswap64s((uint64_t*)&s->st_size);
+    tswap64s((uint64_t*)&s->st_blocks);
+    tswap32s((uint32_t*)&s->st_blksize);
+    tswap32s(&s->st_flags);
+    tswap32s(&s->st_gen);
+}
+
+static inline void byteswap_dirents(struct dirent *d, int bytes)
+{
+    char *b;
+    for( b = (char*)d; (int)b < (int)d+bytes; )
+    {
+        unsigned short s = ((struct dirent *)b)->d_reclen;
+        tswap32s(&((struct dirent *)b)->d_ino);
+        tswap16s(&((struct dirent *)b)->d_reclen);
+        if(s<=0)
+            break;
+        b += s;
+    }
+}
+
+static inline void byteswap_iovec(struct iovec *v, int n)
+{
+    int i;
+    for(i = 0; i < n; i++)
+    {
+        tswap32s((uint32_t*)&v[i].iov_base);
+        tswap32s((uint32_t*)&v[i].iov_len);
+    }
+}
+
+static inline void byteswap_timeval(struct timeval *t)
+{
+    tswap32s((uint32_t*)&t->tv_sec);
+    tswap32s((uint32_t*)&t->tv_usec);
+}
+
+long do_unix_syscall_indirect(void *cpu_env, int num);
+long do_sync();
+long do_exit(uint32_t arg1);
+long do_getlogin(char *out, uint32_t size);
+long do_open(char * arg1, uint32_t arg2, uint32_t arg3);
+long do_getfsstat(struct statfs * arg1, uint32_t arg2, uint32_t arg3);
+long do_sigprocmask(uint32_t arg1, uint32_t * arg2, uint32_t * arg3);
+long do_execve(char* arg1, char ** arg2, char ** arg3);
+long do_getgroups(uint32_t arg1, gid_t * arg2);
+long do_gettimeofday(struct timeval * arg1, void * arg2);
+long do_readv(uint32_t arg1, struct iovec * arg2, uint32_t arg3);
+long do_writev(uint32_t arg1, struct iovec * arg2, uint32_t arg3);
+long do_utimes(char * arg1, struct timeval * arg2);
+long do_futimes(uint32_t arg1, struct timeval * arg2);
+long do_statfs(char * arg1, struct statfs * arg2);
+long do_fstatfs(uint32_t arg1, struct statfs * arg2);
+long do_stat(char * arg1, struct stat * arg2);
+long do_fstat(uint32_t arg1, struct stat * arg2);
+long do_lstat(char * arg1, struct stat * arg2);
+long do_getdirentries(uint32_t arg1, void* arg2, uint32_t arg3, void* arg4);
+long do_lseek(void *cpu_env, int num);
+long do___sysctl(int * name, uint32_t namelen, void * oldp, size_t * oldlenp, void * newp, size_t newlen  /* ignored */);
+long do_getattrlist(void * arg1, void * arg2, void * arg3, uint32_t arg4, uint32_t arg5);
+long do_getdirentriesattr(uint32_t arg1, void * arg2, void * arg3, size_t arg4, void * arg5, void * arg6, void* arg7, uint32_t arg8);
+long do_fcntl(int fd, int cmd, int arg);
+
+long no_syscall(void *cpu_env, int num);
+
+long do_pread(uint32_t arg1, void * arg2, size_t arg3, off_t arg4)
+{
+    DPRINTF("0x%x, %p, 0x%lx, 0x%llx\n", arg1, arg2, arg3, arg4);
+    long ret = pread(arg1, arg2, arg3, arg4);
+    return ret;
+}
+
+long do_read(int d, void *buf, size_t nbytes)
+{
+    DPRINTF("0x%x, %p, 0x%lx\n", d, buf, nbytes);
+    long ret = get_errno(read(d, buf, nbytes));
+    if(!is_error(ret))
+        DPRINTF("%x\n", *(uint32_t*)buf);
+    return ret;
+}
+
+long unimpl_unix_syscall(void *cpu_env, int num);
+
+typedef long (*syscall_function_t)(void *cpu_env, int num);
+
+
+/* define a table that will handle the syscall number->function association */
+#define VOID    void
+#define INT     (uint32_t)get_int_arg(&i, cpu_env)
+#define INT64   (uint64_t)get_int64_arg(&i, cpu_env)
+#define UINT    (unsigned int)INT
+#define PTR     (void*)INT
+
+#define SIZE    INT
+#define OFFSET  INT64
+
+#define WRAPPER_CALL_DIRECT_0(function, args) long __qemu_##function(void *cpu_env) {  return (long)function(); }
+#define WRAPPER_CALL_DIRECT_1(function, _arg1) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1;  return (long)function(arg1); }
+#define WRAPPER_CALL_DIRECT_2(function, _arg1, _arg2) long __qemu_##function(void *cpu_env) { int i = 0;  typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; return (long)function(arg1, arg2); }
+#define WRAPPER_CALL_DIRECT_3(function, _arg1, _arg2, _arg3) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; return (long)function(arg1, arg2, arg3); }
+#define WRAPPER_CALL_DIRECT_4(function, _arg1, _arg2, _arg3, _arg4) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; return (long)function(arg1, arg2, arg3, arg4); }
+#define WRAPPER_CALL_DIRECT_5(function, _arg1, _arg2, _arg3, _arg4, _arg5) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5;  return (long)function(arg1, arg2, arg3, arg4, arg5); }
+#define WRAPPER_CALL_DIRECT_6(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6;  return (long)function(arg1, arg2, arg3, arg4, arg5, arg6); }
+#define WRAPPER_CALL_DIRECT_7(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6; typeof(_arg7) arg7 = _arg7; return (long)function(arg1, arg2, arg3, arg4, arg5, arg6, arg7); }
+#define WRAPPER_CALL_DIRECT_8(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7, _arg8) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6; typeof(_arg7) arg7 = _arg7; typeof(_arg8) arg8 = _arg8;  return (long)function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); }
+#define WRAPPER_CALL_DIRECT(function, nargs, args...) WRAPPER_CALL_DIRECT_##nargs(function, args)
+#define WRAPPER_CALL_NOERRNO(function, nargs, args...)  WRAPPER_CALL_DIRECT(function, nargs, args)
+#define WRAPPER_CALL_INDIRECT(function, nargs, args...)
+#define ENTRY(name, number, function, nargs, call_type, args...)  WRAPPER_##call_type(function, nargs, args)
+
+#include "syscalls.h"
+
+#undef ENTRY
+#undef WRAPPER_CALL_DIRECT
+#undef WRAPPER_CALL_NOERRNO
+#undef WRAPPER_CALL_INDIRECT
+#undef OFFSET
+#undef SIZE
+#undef INT
+#undef PTR
+#undef INT64
+
+#define _ENTRY(name, number, function, nargs, call_type) [number] = {\
+        name, \
+        number, \
+        (syscall_function_t)function, \
+        nargs, \
+        call_type  \
+        },
+
+#define ENTRY_CALL_DIRECT(name, number, function, nargs, call_type)  _ENTRY(name, number, __qemu_##function, nargs, call_type)
+#define ENTRY_CALL_NOERRNO(name, number, function, nargs, call_type) ENTRY_CALL_DIRECT(name, number, function, nargs, call_type)
+#define ENTRY_CALL_INDIRECT(name, number, function, nargs, call_type) _ENTRY(name, number, function, nargs, call_type)
+#define ENTRY(name, number, function, nargs, call_type, args...) ENTRY_##call_type(name, number, function, nargs, call_type)
+
+#define CALL_DIRECT 1
+#define CALL_INDIRECT 2
+#define CALL_NOERRNO  (CALL_DIRECT | 4 /* = 5 */)
+
+struct unix_syscall {
+    char * name;
+    int number;
+    syscall_function_t function;
+    int nargs;
+    int call_type;
+} unix_syscall_table[SYS_MAXSYSCALL] = {
+#include "syscalls.h"
+};
+
+#undef ENTRY
+#undef _ENTRY
+#undef ENTRY_CALL_DIRECT
+#undef ENTRY_CALL_INDIRECT
+#undef ENTRY_CALL_NOERRNO
+
+/* Actual syscalls implementation */
+
+long do_unix_syscall_indirect(void *cpu_env, int num)
+{
+    long ret;
+    int new_num;
+    int i = 0;
+
+    new_num = get_int_arg(&i, cpu_env);
+#ifdef TARGET_I386
+    ((CPUX86State*)cpu_env)->regs[R_ESP] += 4;
+    /* XXX: not necessary */
+    ((CPUX86State*)cpu_env)->regs[R_EAX] = new_num;
+#elif TARGET_PPC
+    {
+        int i;
+        uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr;
+        for(i = 3; i < 11; i++)
+            *regs[i] = *regs[i+1];
+        /* XXX: not necessary */
+        *regs[0] = new_num;
+    }
+#endif
+    ret = do_unix_syscall(cpu_env, new_num);
+#ifdef TARGET_I386
+    ((CPUX86State*)cpu_env)->regs[R_ESP] -= 4;
+    /* XXX: not necessary */
+    ((CPUX86State*)cpu_env)->regs[R_EAX] = num;
+#elif TARGET_PPC
+    {
+        int i;
+        /* XXX: not really needed those regs are volatile accross calls */
+        uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr;
+        for(i = 11; i > 3; i--)
+            *regs[i] = *regs[i-1];
+        regs[3] = new_num;
+        *regs[0] = num;
+    }
+#endif
+    return ret;
+}
+
+long do_exit(uint32_t arg1)
+{
+    exit(arg1);
+    /* not reached */
+    return -1;
+}
+
+long do_sync()
+{
+    sync();
+    return 0;
+}
+
+long do_getlogin(char *out, uint32_t size)
+{
+    char *login = getlogin();
+    if(!login)
+        return -1;
+    memcpy(out, login, size);
+    return 0;
+}
+long do_open(char * arg1, uint32_t arg2, uint32_t arg3)
+{
+    /* XXX: don't let the %s stay in there */
+    DPRINTF("open(%s, 0x%x, 0x%x)\n", arg1, arg2, arg3);
+    return get_errno(open(arg1, arg2, arg3));
+}
+
+long do_getfsstat(struct statfs * arg1, uint32_t arg2, uint32_t arg3)
+{
+    long ret;
+    DPRINTF("getfsstat(%p, 0x%x, 0x%x)\n", arg1, arg2, arg3);
+    ret = get_errno(getfsstat(arg1, arg2, arg3));
+    if((!is_error(ret)) && arg1)
+        byteswap_statfs(arg1);
+    return ret;
+}
+
+long do_sigprocmask(uint32_t arg1, uint32_t * arg2, uint32_t * arg3)
+{
+    long ret;
+    DPRINTF("sigprocmask(%d, %p, %p)\n", arg1, arg2, arg3);
+    gemu_log("XXX: sigprocmask not tested (%d, %p, %p)\n", arg1, arg2, arg3);
+    if(arg2)
+        tswap32s(arg2);
+    ret = get_errno(sigprocmask(arg1, (void *)arg2, (void *)arg3));
+    if((!is_error(ret)) && arg3)
+        tswap32s(arg3);
+    if(arg2)
+        tswap32s(arg2);
+    return ret;
+}
+
+long do_execve(char* arg1, char ** arg2, char ** arg3)
+{
+    long ret;
+    char **argv = arg2;
+    char **envp = arg3;
+    int argc;
+    int envc;
+
+    /* XXX: don't let the %s stay in here */
+    DPRINTF("execve(%s, %p, %p)\n", arg1, arg2, arg3);
+
+    for(argc = 0; argv[argc]; argc++);
+    for(envc = 0; envp[envc]; envc++);
+
+    argv = (char**)malloc(sizeof(char*)*argc);
+    envp = (char**)malloc(sizeof(char*)*envc);
+
+    for(; argc >= 0; argc--)
+        argv[argc] = (char*)tswap32((uint32_t)(arg2)[argc]);
+
+    for(; envc >= 0; envc--)
+        envp[envc] = (char*)tswap32((uint32_t)(arg3)[envc]);
+
+    ret = get_errno(execve(arg1, argv, envp));
+    free(argv);
+    free(envp);
+    return ret;
+}
+
+long do_getgroups(uint32_t arg1, gid_t * arg2)
+{
+    long ret;
+    int i;
+    DPRINTF("getgroups(0x%x, %p)\n", arg1, arg2);
+    ret = get_errno(getgroups(arg1, arg2));
+    if(ret > 0)
+        for(i = 0; i < arg1; i++)
+            tswap32s(&arg2[i]);
+    return ret;
+}
+
+long do_gettimeofday(struct timeval * arg1, void * arg2)
+{
+    long ret;
+    DPRINTF("gettimeofday(%p, %p)\n",
+            arg1, arg2);
+    ret = get_errno(gettimeofday(arg1, arg2));
+    if(!is_error(ret))
+    {
+        /* timezone no longer used according to the manpage, so don't bother with it */
+        byteswap_timeval(arg1);
+    }
+    return ret;
+}
+
+long do_readv(uint32_t arg1, struct iovec * arg2, uint32_t arg3)
+{
+    long ret;
+    DPRINTF("readv(0x%x, %p, 0x%x)\n", arg1, arg2, arg3);
+    if(arg2)
+        byteswap_iovec(arg2, arg3);
+    ret = get_errno(readv(arg1, arg2, arg3));
+    if((!is_error(ret)) && arg2)
+        byteswap_iovec(arg2, arg3);
+    return ret;
+}
+
+long do_writev(uint32_t arg1, struct iovec * arg2, uint32_t arg3)
+{
+    long ret;
+    DPRINTF("writev(0x%x, %p, 0x%x)\n", arg1, arg2, arg3);
+    if(arg2)
+        byteswap_iovec(arg2, arg3);
+    ret = get_errno(writev(arg1, arg2, arg3));
+    if((!is_error(ret)) && arg2)
+        byteswap_iovec(arg2, arg3);
+    return ret;
+}
+
+long do_utimes(char * arg1, struct timeval * arg2)
+{
+    DPRINTF("utimes(%p, %p)\n", arg1, arg2);
+    if(arg2)
+    {
+        byteswap_timeval(arg2);
+        byteswap_timeval(arg2+1);
+    }
+    return get_errno(utimes(arg1, arg2));
+}
+
+long do_futimes(uint32_t arg1, struct timeval * arg2)
+{
+    DPRINTF("futimes(0x%x, %p)\n", arg1, arg2);
+    if(arg2)
+    {
+        byteswap_timeval(arg2);
+        byteswap_timeval(arg2+1);
+    }
+    return get_errno(futimes(arg1, arg2));
+}
+
+long do_statfs(char * arg1, struct statfs * arg2)
+{
+    long ret;
+    DPRINTF("statfs(%p, %p)\n", arg1, arg2);
+    ret = get_errno(statfs(arg1, arg2));
+    if(!is_error(ret))
+        byteswap_statfs(arg2);
+    return ret;
+}
+
+long do_fstatfs(uint32_t arg1, struct statfs* arg2)
+{
+    long ret;
+    DPRINTF("fstatfs(0x%x, %p)\n",
+            arg1, arg2);
+    ret = get_errno(fstatfs(arg1, arg2));
+    if(!is_error(ret))
+        byteswap_statfs(arg2);
+
+    return ret;
+}
+
+long do_stat(char * arg1, struct stat * arg2)
+{
+    long ret;
+    /* XXX: don't let the %s stay in there */
+    DPRINTF("stat(%s, %p)\n", arg1, arg2);
+    ret = get_errno(stat(arg1, arg2));
+    if(!is_error(ret))
+        byteswap_stat(arg2);
+    return ret;
+}
+
+long do_fstat(uint32_t arg1, struct stat * arg2)
+{
+    long ret;
+    DPRINTF("fstat(0x%x, %p)\n", arg1, arg2);
+    ret = get_errno(fstat(arg1, arg2));
+    if(!is_error(ret))
+        byteswap_stat(arg2);
+    return ret;
+}
+
+long do_lstat(char * arg1, struct stat * arg2)
+{
+    long ret;
+    /* XXX: don't let the %s stay in there */
+    DPRINTF("lstat(%s, %p)\n", (const char *)arg1, arg2);
+    ret = get_errno(lstat(arg1, arg2));
+    if(!is_error(ret))
+        byteswap_stat(arg2);
+    return ret;
+}
+
+long do_getdirentries(uint32_t arg1, void* arg2, uint32_t arg3, void* arg4)
+{
+    long ret;
+    DPRINTF("getdirentries(0x%x, %p, 0x%x, %p)\n", arg1, arg2, arg3, arg4);
+    if(arg4)
+        tswap32s((uint32_t *)arg4);
+    ret = get_errno(getdirentries(arg1, arg2, arg3, arg4));
+    if(arg4)
+        tswap32s((uint32_t *)arg4);
+    if(!is_error(ret))
+        byteswap_dirents(arg2, ret);
+    return ret;
+}
+
+long do_lseek(void *cpu_env, int num)
+{
+    long ret;
+    int i = 0;
+    uint32_t arg1 = get_int_arg(&i, cpu_env);
+    uint64_t offset = get_int64_arg(&i, cpu_env);
+    uint32_t arg3 = get_int_arg(&i, cpu_env);
+    uint64_t r = lseek(arg1, offset, arg3);
+#ifdef TARGET_I386
+    /* lowest word in eax, highest in edx */
+    ret = r & 0xffffffff; /* will be set to eax after do_unix_syscall exit */
+    ((CPUX86State *)cpu_env)->regs[R_EDX] = (uint32_t)((r >> 32) & 0xffffffff) ;
+#elif defined TARGET_PPC
+    ret = r & 0xffffffff; /* will be set to r3 after do_unix_syscall exit */
+    ((CPUPPCState *)cpu_env)->gpr[4] = (uint32_t)((r >> 32) & 0xffffffff) ;
+#else
+    qerror("64 bit ret value on your arch?");
+#endif
+    return get_errno(ret);
+}
+
+void no_swap(void * oldp, int size)
+{
+}
+
+void sysctl_tswap32s(void * oldp, int size)
+{
+    tswap32s(oldp);
+}
+
+void bswap_oid(uint32_t * oldp, int size)
+{
+    int count = size / sizeof(int);
+    int i = 0;
+    do { tswap32s(oldp + i); } while (++i < count);
+}
+
+void sysctl_usrstack(uint32_t * oldp, int size)
+{
+    DPRINTF("sysctl_usrstack: 0x%x\n", *oldp);
+    tswap32s(oldp);
+}
+
+void sysctl_ncpu(uint32_t * ncpu, int size)
+{
+    *ncpu = 0x1;
+    DPRINTF("sysctl_ncpu: 0x%x\n", *ncpu);
+    tswap32s(ncpu);
+}
+
+void sysctl_exec(char * exec, int size)
+{
+    DPRINTF("sysctl_exec: %s\n", exec);
+}
+
+void sysctl_translate(char * exec, int size)
+{
+    DPRINTF("sysctl_translate: %s\n", exec);
+}
+
+struct sysctl_dir {
+    int num;
+    const char * name;
+    void (*swap_func)(void *, int);
+    struct sysctl_dir *childs;
+};
+
+#define ENTRYD(num, name, childs) { num, name, NULL, childs }
+#define ENTRYE(num, name, func)   { num, name, (void (*)(void *, int))func, NULL  }
+struct sysctl_dir sysctls_unspec[] = {
+    ENTRYE(3,  "oip", bswap_oid),
+    { 0, NULL, NULL, NULL }
+};
+
+struct sysctl_dir sysctls_kern[] = {
+    ENTRYE(KERN_TRANSLATE,          "translate",    sysctl_translate), /* 44 */
+    ENTRYE(KERN_EXEC,               "exec",         sysctl_exec), /* 45 */
+    ENTRYE(KERN_USRSTACK32,          "KERN_USRSTACK32", sysctl_usrstack), /* 35 */
+    ENTRYE(KERN_SHREG_PRIVATIZABLE,  "KERN_SHREG_PRIVATIZABLE", sysctl_tswap32s), /* 54 */
+    { 0, NULL, NULL, NULL }
+};
+
+struct sysctl_dir sysctls_hw[] = {
+    ENTRYE(HW_NCPU, "ncpud", sysctl_tswap32s),
+    ENTRYE(104, "104", no_swap),
+    ENTRYE(105, "105", no_swap),
+    { 0, NULL, NULL, NULL }
+};
+
+struct sysctl_dir sysctls[] = {
+    ENTRYD(CTL_UNSPEC, "unspec", sysctls_unspec),
+    ENTRYD(CTL_KERN, "kern", sysctls_kern),
+    ENTRYD(CTL_HW,   "hw",   sysctls_hw ),
+    { 0, NULL, NULL, NULL }
+};
+
+#undef ENTRYE
+#undef ENTRYD
+
+static inline struct sysctl_dir * get_sysctl_entry_for_mib(int mib, struct sysctl_dir * sysctl_elmt)
+{
+    if(!sysctl_elmt)
+        return NULL;
+    for(; sysctl_elmt->name != NULL ; sysctl_elmt++) {
+        if(sysctl_elmt->num == mib)
+            return sysctl_elmt;
+    }
+    return NULL;
+}
+
+static inline long bswap_syctl(int * mib, int count, void *buf, int size)
+{
+    int i;
+    struct sysctl_dir * sysctl = sysctls;
+    struct sysctl_dir * ret = NULL;
+
+    for(i = 0; i < count; i++) {
+
+        if(!(ret = sysctl = get_sysctl_entry_for_mib(mib[i], sysctl))) {
+            gemu_log("bswap_syctl: can't find mib %d\n", mib[i]);
+            return -ENOTDIR;
+        }
+        if(!(sysctl = sysctl->childs))
+            break;
+    }
+    
+    if(ret->childs)
+        qerror("we shouldn't have a directory element\n");
+
+    ret->swap_func(buf, size);
+    return 0;
+}
+
+static inline void print_syctl(int * mib, int count)
+{
+    int i;
+    struct sysctl_dir * sysctl = sysctls;
+    struct sysctl_dir * ret = NULL;
+
+    for(i = 0; i < count; i++) {
+        if(!(ret = sysctl = get_sysctl_entry_for_mib(mib[i], sysctl))){
+            gemu_log("print_syctl: can't find mib %d\n", mib[i]);
+            return;
+        }
+        DPRINTF("%s.", sysctl->name);
+        if(!(sysctl = sysctl->childs))
+            break;
+    }
+    DPRINTF("\n");
+}
+
+long do___sysctl(int * name, uint32_t namelen, void * oldp, size_t * oldlenp, void * newp, size_t newlen  /* ignored */)
+{
+    long ret = 0;
+    int i;
+    DPRINTF("sysctl(%p, 0x%x, %p, %p, %p, 0x%lx)\n",
+            name, namelen, oldp, oldlenp, newp, newlen);
+    if(name) {
+        i = 0;
+        do { tswap32s( name + i); } while (++i < namelen);
+        print_syctl(name, namelen);
+        //bswap_syctl(name, namelen, newp, newlen);
+        tswap32s((uint32_t*)oldlenp);
+    }
+        
+    if(name) /* Sometimes sysctl is called with no arg1, ignore */
+        ret = get_errno(sysctl(name, namelen, oldp, oldlenp, newp, newlen));
+
+#if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
+    if (!is_error(ret) && bswap_syctl(name, namelen, oldp, *oldlenp) != 0) {
+        return -ENOTDIR;
+    }
+#endif
+
+    if(name) {
+        //bswap_syctl(name, namelen, newp, newlen);
+        tswap32s((uint32_t*)oldlenp);
+
+        i = 0;
+        do { tswap32s( name + i); } while (++i < namelen);
+    }
+    return ret;
+}
+
+long do_getattrlist(void * arg1, void * arg2, void * arg3, uint32_t arg4, uint32_t arg5)
+{
+    struct attrlist * attrlist = (void *)arg2;
+    long ret;
+
+#if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
+    gemu_log("SYS_getdirentriesattr unimplemented\n");
+    return -ENOTSUP;
+#endif
+    /* XXX: don't let the %s stay in there */
+    DPRINTF("getattrlist(%s, %p, %p, 0x%x, 0x%x)\n",
+            (char *)arg1, arg2, arg3, arg4, arg5);
+
+    if(arg2) /* XXX: We should handle that in a copy especially
+        if the structure is not writable */
+        byteswap_attrlist(attrlist);
+
+    ret = get_errno(getattrlist((const char* )arg1, attrlist, (void *)arg3, arg4, arg5));
+
+    if(!is_error(ret))
+    {
+        byteswap_attrbuf((void *)arg3, attrlist);
+        byteswap_attrlist(attrlist);
+    }
+    return ret;
+}
+
+long do_getdirentriesattr(uint32_t arg1, void * arg2, void * arg3, size_t arg4, void * arg5, void * arg6, void* arg7, uint32_t arg8)
+{
+    DPRINTF("getdirentriesattr(0x%x, %p, %p, 0x%lx, %p, %p, %p, 0x%x)\n",
+            arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+#if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
+    qerror("SYS_getdirentriesattr unimplemented\n");
+#endif
+
+    return get_errno(getdirentriesattr( arg1, (struct attrlist * )arg2, (void *)arg3, arg4,
+                                       (unsigned long *)arg5, (unsigned long *)arg6,
+                                       (unsigned long *)arg7, arg8));
+}
+
+static inline void bswap_flock(struct flock *f)
+{
+    tswap64s(&f->l_start);
+    tswap64s(&f->l_len);
+    tswap32s(&f->l_pid);
+    tswap16s(&f->l_type);
+    tswap16s(&f->l_whence);
+}
+
+static inline void bswap_fstore(struct fstore *f)
+{
+    tswap32s(&f->fst_flags);
+    tswap32s(&f->fst_posmode);
+    tswap64s(&f->fst_offset);
+    tswap64s(&f->fst_length);
+    tswap64s(&f->fst_bytesalloc);
+}
+
+static inline void bswap_radvisory(struct radvisory *f)
+{
+    tswap64s(&f->ra_offset);
+    tswap32s(&f->ra_count);
+}
+
+static inline void bswap_fbootstraptransfer(struct fbootstraptransfer *f)
+{
+    tswap64s(&f->fbt_offset);
+    tswap32s((uint32_t*)&f->fbt_length);
+    tswap32s((uint32_t*)&f->fbt_buffer); /* XXX: this is a ptr */
+}
+
+static inline void bswap_log2phys(struct log2phys *f)
+{
+    tswap32s(&f->l2p_flags);
+    tswap64s(&f->l2p_contigbytes);
+    tswap64s(&f->l2p_devoffset);
+}
+
+static inline void bswap_fcntl_arg(int cmd, void * arg)
+{
+    switch(cmd)
+    {
+        case F_DUPFD:
+        case F_GETFD:
+        case F_SETFD:
+        case F_GETFL:
+        case F_SETFL:
+        case F_GETOWN:
+        case F_SETOWN:
+        case F_SETSIZE:
+        case F_RDAHEAD:
+        case F_FULLFSYNC:
+            break;
+        case F_GETLK:
+        case F_SETLK:
+        case F_SETLKW:
+            bswap_flock(arg);
+            break;
+        case F_PREALLOCATE:
+            bswap_fstore(arg);
+            break;
+        case F_RDADVISE:
+            bswap_radvisory(arg);
+            break;
+        case F_READBOOTSTRAP:
+        case F_WRITEBOOTSTRAP:
+            bswap_fbootstraptransfer(arg);
+            break;
+        case F_LOG2PHYS:
+            bswap_log2phys(arg);
+            break;
+        default:
+            gemu_log("unknow cmd in fcntl\n");
+    }
+}
+
+long do_fcntl(int fd, int cmd, int arg)
+{
+    long ret;
+    bswap_fcntl_arg(cmd, (void *)arg);
+    ret = get_errno(fcntl(fd, cmd, arg));
+    if(!is_error(ret))
+        bswap_fcntl_arg(cmd, (void *)arg);
+    return ret;
+}
+
+long no_syscall(void *cpu_env, int num)
+{
+    /* XXX: We should probably fordward it to the host kernel */
+    qerror("no unix syscall %d\n", num);
+    /* not reached */
+    return -1;
+}
+
+long unimpl_unix_syscall(void *cpu_env, int num)
+{
+    if( (num < 0) || (num > SYS_MAXSYSCALL-1) )
+        qerror("unix syscall %d is out of unix syscall bounds (0-%d) " , num, SYS_MAXSYSCALL-1);
+
+    gemu_log("qemu: Unsupported unix syscall %s %d\n", unix_syscall_table[num].name , num);
+    gdb_handlesig (cpu_env, SIGTRAP);
+    exit(-1);
+}
+
+long do_unix_syscall(void *cpu_env, int num)
+{
+    long ret = 0;
+
+    DPRINTF("unix syscall %d: " , num);
+
+    if( (num < 0) || (num > SYS_MAXSYSCALL-1) )
+        qerror("unix syscall %d is out of unix syscall bounds (0-%d) " , num, SYS_MAXSYSCALL-1);
+
+    DPRINTF("%s [%s]", unix_syscall_table[num].name, unix_syscall_table[num].call_type & CALL_DIRECT ? "direct" : "indirect" );
+    ret = unix_syscall_table[num].function(cpu_env, num);
+
+    if(!(unix_syscall_table[num].call_type & CALL_NOERRNO))
+        ret = get_errno(ret);
+
+    DPRINTF("[returned 0x%x(%d)]\n", (int)ret, (int)ret);
+    return ret;
+}
+
+/* ------------------------------------------------------------
+   syscall_init
+*/
+void syscall_init(void)
+{
+    /* Nothing yet */
+}

Added: trunk/src/host/qemu-neo1973/darwin-user/syscalls.h
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/syscalls.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/syscalls.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,384 @@
+/* generated from xnu/bsd/kern/syscalls.master */
+
+ ENTRY("syscall",                  SYS_syscall,                        do_unix_syscall_indirect,          0, CALL_INDIRECT, VOID) /* 0  indirect syscall */
+ ENTRY("exit",                     SYS_exit,                           do_exit,                           1, CALL_DIRECT, INT)   /* 1  */
+ ENTRY("fork",                     SYS_fork,                           fork,                              0, CALL_NOERRNO, VOID)  /* 2  */
+ ENTRY("read",                     SYS_read,                           do_read,                           3, CALL_DIRECT, INT, PTR, SIZE)   /* 3  */
+ ENTRY("write",                    SYS_write,                          write,                             3, CALL_DIRECT, INT, PTR, SIZE)   /* 4  */
+ ENTRY("open",                     SYS_open,                           do_open,                           3, CALL_DIRECT, PTR, INT, INT)   /* 5  */
+ ENTRY("close",                    SYS_close,                          close,                             1, CALL_DIRECT, INT)   /* 6  */
+ ENTRY("wait4",                    SYS_wait4,                          wait4,                             4, CALL_DIRECT, INT, PTR, INT, PTR)   /* 7  */
+ ENTRY("",                         8,                                  no_syscall,                        0, CALL_INDIRECT, VOID) /* 8  old creat */
+ ENTRY("link",                     SYS_link,                           link,                              2, CALL_DIRECT, PTR, PTR)   /* 9  */
+ ENTRY("unlink",                   SYS_unlink,                         unlink,                            1, CALL_DIRECT, PTR)   /* 10  */
+ ENTRY("",                         11,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 11  old execv */
+ ENTRY("chdir",                    SYS_chdir,                          chdir,                             1, CALL_DIRECT, PTR)   /* 12  */
+ ENTRY("fchdir",                   SYS_fchdir,                         fchdir,                            1, CALL_DIRECT, INT)   /* 13  */
+ ENTRY("mknod",                    SYS_mknod,                          mknod,                             3, CALL_DIRECT, PTR, INT, INT)   /* 14  */
+ ENTRY("chmod",                    SYS_chmod,                          chmod,                             2, CALL_DIRECT, PTR, INT)   /* 15  */
+ ENTRY("chown",                    SYS_chown,                          chown,                             3, CALL_DIRECT, PTR, INT, INT)   /* 16  */
+ ENTRY("obreak",                   SYS_obreak,                         no_syscall,                        1, CALL_INDIRECT, VOID)   /* 17  old break */
+ ENTRY("ogetfsstat",               18,                                 unimpl_unix_syscall,               3, CALL_INDIRECT, PTR, INT, INT)   /* 18  */
+ ENTRY("",                         19,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 19  old lseek */
+ ENTRY("getpid",                   SYS_getpid,                         getpid,                            0, CALL_NOERRNO, VOID)   /* 20  */
+ ENTRY("",                         21,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 21  old mount */
+ ENTRY("",                         22,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 22  old umount */
+ ENTRY("setuid",                   SYS_setuid,                         setuid,                            1, CALL_DIRECT, INT)   /* 23  */
+ ENTRY("getuid",                   SYS_getuid,                         getuid,                            0, CALL_NOERRNO, VOID)   /* 24  */
+ ENTRY("geteuid",                  SYS_geteuid,                        geteuid,                           0, CALL_NOERRNO, VOID)   /* 25  */
+ ENTRY("ptrace",                   SYS_ptrace,                         ptrace,                            4, CALL_DIRECT, INT, INT, PTR, INT)   /* 26  */
+ ENTRY("recvmsg",                  SYS_recvmsg,                        recvmsg,                           3, CALL_DIRECT, INT, PTR, INT)   /* 27  */
+ ENTRY("sendmsg",                  SYS_sendmsg,                        sendmsg,                           3, CALL_DIRECT, INT, PTR, INT)   /* 28  */
+ ENTRY("recvfrom",                 SYS_recvfrom,                       recvfrom,                          6, CALL_DIRECT, INT, PTR, INT, INT, PTR, PTR)   /* 29  */
+ ENTRY("accept",                   SYS_accept,                         accept,                            3, CALL_DIRECT, INT, PTR, PTR)   /* 30  */
+ ENTRY("getpeername",              SYS_getpeername,                    getpeername,                       3, CALL_DIRECT, INT, PTR, PTR)   /* 31  */
+ ENTRY("getsockname",              SYS_getsockname,                    getsockname,                       3, CALL_DIRECT, INT, PTR, PTR)   /* 32  */
+ ENTRY("access",                   SYS_access,                         access,                            2, CALL_DIRECT, PTR, INT)   /* 33  */
+ ENTRY("chflags",                  SYS_chflags,                        chflags,                           2, CALL_DIRECT, PTR, INT)   /* 34  */
+ ENTRY("fchflags",                 SYS_fchflags,                       fchflags,                          2, CALL_DIRECT, INT, INT)   /* 35  */
+ ENTRY("sync",                     SYS_sync,                           do_sync,                           0, CALL_INDIRECT, VOID)   /* 36  */
+ ENTRY("kill",                     SYS_kill,                           kill,                              2, CALL_DIRECT, INT, INT)   /* 37  */
+ ENTRY("",                         38,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 38  old stat */
+ ENTRY("getppid",                  SYS_getppid,                        getppid,                           0, CALL_DIRECT, VOID)   /* 39  */
+ ENTRY("",                         40,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 40  old lstat */
+ ENTRY("dup",                      SYS_dup,                            dup,                               1, CALL_DIRECT, INT)   /* 41  */
+ ENTRY("pipe",                     SYS_pipe,                           pipe,               0, CALL_INDIRECT, PTR)   /* 42  */
+ ENTRY("getegid",                  SYS_getegid,                        getegid,                           0, CALL_NOERRNO, VOID)  /* 43  */
+ ENTRY("profil",                   SYS_profil,                         profil,                            4, CALL_DIRECT, PTR, SIZE, INT, INT)   /* 44  */
+ ENTRY("ktrace",                   SYS_ktrace,                         no_syscall,                        4, CALL_INDIRECT, VOID) /* 45  */
+ ENTRY("sigaction",                SYS_sigaction,                      do_sigaction,                      3, CALL_DIRECT, INT, PTR, PTR)   /* 46  */
+ ENTRY("getgid",                   SYS_getgid,                         getgid,                            0, CALL_NOERRNO, VOID)  /* 47  */
+ ENTRY("sigprocmask",              SYS_sigprocmask,                    do_sigprocmask,                    3, CALL_DIRECT, INT, PTR, PTR)   /* 48  */
+ ENTRY("getlogin",                 SYS_getlogin,                       do_getlogin,                       2, CALL_DIRECT, PTR, UINT)   /* 49 XXX */
+ ENTRY("setlogin",                 SYS_setlogin,                       setlogin,                          1, CALL_DIRECT, PTR)   /* 50  */
+ ENTRY("acct",                     SYS_acct,                           acct,                              1, CALL_DIRECT, PTR)   /* 51  */
+ ENTRY("sigpending",               SYS_sigpending,                     sigpending,                        1, CALL_DIRECT, PTR)   /* 52  */
+ ENTRY("sigaltstack",              SYS_sigaltstack,                    do_sigaltstack,                    2, CALL_DIRECT, PTR, PTR)   /* 53  */
+ ENTRY("ioctl",                    SYS_ioctl,                          do_ioctl,                          3, CALL_DIRECT, INT, INT, INT)   /* 54  */
+ ENTRY("reboot",                   SYS_reboot,                         unimpl_unix_syscall,               2, CALL_INDIRECT, INT, PTR)   /* 55  */
+ ENTRY("revoke",                   SYS_revoke,                         revoke,                            1, CALL_DIRECT, PTR)   /* 56  */
+ ENTRY("symlink",                  SYS_symlink,                        symlink,                           2, CALL_DIRECT, PTR, PTR)   /* 57  */
+ ENTRY("readlink",                 SYS_readlink,                       readlink,                          3, CALL_DIRECT, PTR, PTR, INT)   /* 58  */
+ ENTRY("execve",                   SYS_execve,                         do_execve,                         3, CALL_DIRECT, PTR, PTR, PTR)   /* 59  */
+ ENTRY("umask",                    SYS_umask,                          umask,                             1, CALL_DIRECT, INT)   /* 60  */
+ ENTRY("chroot",                   SYS_chroot,                         chroot,                            1, CALL_DIRECT, PTR)   /* 61  */
+ ENTRY("",                         62,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 62  old fstat */
+ ENTRY("",                         63,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 63  used internally , reserved */
+ ENTRY("",                         64,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 64  old getpagesize */
+ ENTRY("msync",                    SYS_msync,                          target_msync,                      3, CALL_DIRECT, UINT /*PTR*/, SIZE, INT)   /* 65  */
+ ENTRY("vfork",                    SYS_vfork,                          vfork,                             0, CALL_DIRECT, VOID)   /* 66  */
+ ENTRY("",                         67,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 67  old vread */
+ ENTRY("",                         68,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 68  old vwrite */
+ ENTRY("sbrk",                     SYS_sbrk,                           sbrk,                              1, CALL_DIRECT, INT)   /* 69  */
+ ENTRY("sstk",                     SYS_sstk,                           no_syscall,                        1, CALL_INDIRECT, VOID) /* 70  */
+ ENTRY("",                         71,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 71  old mmap */
+ ENTRY("ovadvise",                 SYS_ovadvise,                       no_syscall,                        0, CALL_INDIRECT, VOID) /* 72  old vadvise */
+ ENTRY("munmap",                   SYS_munmap,                         target_munmap,                     2, CALL_DIRECT, UINT /* PTR */, SIZE)   /* 73  */
+ ENTRY("mprotect",                 SYS_mprotect,                       mprotect,                          3, CALL_DIRECT, PTR, SIZE, INT)   /* 74  */
+ ENTRY("madvise",                  SYS_madvise,                        madvise,                           3, CALL_DIRECT, PTR, SIZE, INT)   /* 75  */
+ ENTRY("",                         76,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 76  old vhangup */
+ ENTRY("",                         77,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 77  old vlimit */
+ ENTRY("mincore",                  SYS_mincore,                        mincore,                           3, CALL_DIRECT, PTR, SIZE, PTR)   /* 78  */
+ ENTRY("getgroups",                SYS_getgroups,                      do_getgroups,                      2, CALL_DIRECT, UINT, PTR)   /* 79  */
+ ENTRY("setgroups",                SYS_setgroups,                      setgroups,                         2, CALL_DIRECT, UINT, PTR)   /* 80  */
+ ENTRY("getpgrp",                  SYS_getpgrp,                        getpgrp,                           0, CALL_DIRECT, VOID)   /* 81  */
+ ENTRY("setpgid",                  SYS_setpgid,                        setpgid,                           2, CALL_DIRECT, INT, INT)   /* 82  */
+ ENTRY("setitimer",                SYS_setitimer,                      setitimer,                         3, CALL_DIRECT, INT, PTR, PTR)   /* 83  */
+ ENTRY("",                         84,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 84  old wait */
+ ENTRY("swapon",                   SYS_swapon,                         unimpl_unix_syscall,               0, CALL_INDIRECT, VOID)   /* 85  */
+ ENTRY("getitimer",                SYS_getitimer,                      getitimer,                         2, CALL_DIRECT, INT, PTR)   /* 86  */
+ ENTRY("",                         87,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 87  old gethostname */
+ ENTRY("",                         88,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 88  old sethostname */
+ ENTRY("getdtablesize",            SYS_getdtablesize,                  getdtablesize,                     0, CALL_DIRECT, VOID)   /* 89  */
+ ENTRY("dup2",                     SYS_dup2,                           dup2,                              2, CALL_DIRECT, INT, INT)   /* 90  */
+ ENTRY("",                         91,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 91  old getdopt */
+ ENTRY("fcntl",                    SYS_fcntl,                          do_fcntl,                          3, CALL_DIRECT, INT, INT, INT)   /* 92  */
+ ENTRY("select",                   SYS_select,                         select,                            5, CALL_DIRECT, INT, PTR, PTR, PTR, PTR)   /* 93  */
+ ENTRY("",                         94,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 94  old setdopt */
+ ENTRY("fsync",                    SYS_fsync,                          fsync,                             1, CALL_DIRECT, INT)   /* 95  */
+ ENTRY("setpriority",              SYS_setpriority,                    setpriority,                       3, CALL_DIRECT, INT, INT, INT)   /* 96  */
+ ENTRY("socket",                   SYS_socket,                         socket,                            3, CALL_DIRECT, INT, INT, INT)   /* 97  */
+ ENTRY("connect",                  SYS_connect,                        connect,                           3, CALL_DIRECT, INT, PTR, INT)   /* 98  */
+ ENTRY("",                         99,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 99  old accept */
+ ENTRY("getpriority",              SYS_getpriority,                    getpriority,                       2, CALL_DIRECT, INT, INT)   /* 100  */
+ ENTRY("",                         101,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 101  old send */
+ ENTRY("",                         102,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 102  old recv */
+ ENTRY("",                         103,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 103  old sigreturn */
+ ENTRY("bind",                     SYS_bind,                           bind,                              3, CALL_DIRECT, INT, PTR, INT)   /* 104  */
+ ENTRY("setsockopt",               SYS_setsockopt,                     setsockopt,                        5, CALL_DIRECT, INT, INT, INT, PTR, INT)   /* 105  */
+ ENTRY("listen",                   SYS_listen,                         listen,                            2, CALL_DIRECT, INT, INT)   /* 106  */
+ ENTRY("",                         107,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 107  old vtimes */
+ ENTRY("",                         108,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 108  old sigvec */
+ ENTRY("",                         109,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 109  old sigblock */
+ ENTRY("",                         110,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 110  old sigsetmask */
+ ENTRY("sigsuspend",               SYS_sigsuspend,                     unimpl_unix_syscall,               1, CALL_INDIRECT, INT)   /* 111  */
+ ENTRY("",                         112,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 112  old sigstack */
+ ENTRY("",                         113,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 113  old recvmsg */
+ ENTRY("",                         114,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 114  old sendmsg */
+ ENTRY("",                         115,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 115  old vtrace */
+ ENTRY("gettimeofday",             SYS_gettimeofday,                   do_gettimeofday,                   2, CALL_DIRECT, PTR, PTR) /* 116  */
+ ENTRY("getrusage",                SYS_getrusage,                      getrusage,                         2, CALL_DIRECT, INT, PTR)   /* 117  */
+ ENTRY("getsockopt",               SYS_getsockopt,                     getsockopt,                        5, CALL_DIRECT, INT, INT, INT, PTR, PTR)   /* 118  */
+ ENTRY("",                         119,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 119  old resuba */
+ ENTRY("readv",                    SYS_readv,                          do_readv,                          3, CALL_DIRECT, INT, PTR, UINT)   /* 120  */
+ ENTRY("writev",                   SYS_writev,                         do_writev,                         3, CALL_DIRECT, INT, PTR, UINT)   /* 121  */
+ ENTRY("settimeofday",             SYS_settimeofday,                   settimeofday,                      2, CALL_DIRECT, PTR, PTR)   /* 122  */
+ ENTRY("fchown",                   SYS_fchown,                         fchown,                            3, CALL_DIRECT, INT, INT, INT)   /* 123  */
+ ENTRY("fchmod",                   SYS_fchmod,                         fchmod,                            2, CALL_DIRECT, INT, INT)   /* 124  */
+ ENTRY("",                         125,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 125  old recvfrom */
+ ENTRY("",                         126,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 126  old setreuid */
+ ENTRY("",                         127,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 127  old setregid */
+ ENTRY("rename",                   SYS_rename,                         rename,                            2, CALL_DIRECT, PTR, PTR)   /* 128  */
+ ENTRY("",                         129,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 129  old truncate */
+ ENTRY("",                         130,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 130  old ftruncate */
+ ENTRY("flock",                    SYS_flock,                          flock,                             2, CALL_DIRECT, INT, INT)   /* 131  */
+ ENTRY("mkfifo",                   SYS_mkfifo,                         mkfifo,                            2, CALL_DIRECT, PTR, INT)   /* 132  */
+ ENTRY("sendto",                   SYS_sendto,                         sendto,                            6, CALL_DIRECT, INT, PTR, SIZE, INT, PTR, INT)   /* 133  */
+ ENTRY("shutdown",                 SYS_shutdown,                       shutdown,                          2, CALL_DIRECT, INT, INT)   /* 134  */
+ ENTRY("socketpair",               SYS_socketpair,                     socketpair,                        4, CALL_DIRECT, INT, INT, INT, PTR)   /* 135  */
+ ENTRY("mkdir",                    SYS_mkdir,                          mkdir,                             2, CALL_DIRECT, PTR, INT)   /* 136  */
+ ENTRY("rmdir",                    SYS_rmdir,                          rmdir,                             1, CALL_DIRECT, PTR)   /* 137  */
+ ENTRY("utimes",                   SYS_utimes,                         do_utimes,                         2, CALL_DIRECT, PTR, PTR)   /* 138  */
+ ENTRY("futimes",                  SYS_futimes,                        do_futimes,                        2, CALL_DIRECT, INT, PTR)   /* 139  */
+ ENTRY("adjtime",                  SYS_adjtime,                        adjtime,                           2, CALL_DIRECT, PTR, PTR)   /* 140  */
+ ENTRY("",                         141,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 141  old getpeername */
+ ENTRY("",                         142,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 142  old gethostid */
+ ENTRY("",                         143,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 143  old sethostid */
+ ENTRY("",                         144,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 144  old getrlimit */
+ ENTRY("",                         145,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 145  old setrlimit */
+ ENTRY("",                         146,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 146  old killpg */
+ ENTRY("setsid",                   SYS_setsid,                         setsid,                            0, CALL_DIRECT, VOID)   /* 147  */
+ ENTRY("",                         148,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 148  old setquota */
+ ENTRY("",                         149,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 149  old qquota */
+ ENTRY("",                         150,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 150  old getsockname */
+ ENTRY("getpgid",                  SYS_getpgid,                        getpgid,                           1, CALL_DIRECT, INT)   /* 151  */
+ ENTRY("setprivexec",              SYS_setprivexec,                    no_syscall,                        1, CALL_INDIRECT, VOID) /* 152  */
+ ENTRY("pread",                    SYS_pread,                          do_pread,                          4, CALL_DIRECT, INT, PTR, SIZE, OFFSET)   /* 153  */
+ ENTRY("pwrite",                   SYS_pwrite,                         pwrite,                            4, CALL_DIRECT, INT, PTR, SIZE, OFFSET)   /* 154  */
+#ifdef SYS_nfssvc
+ ENTRY("nfssvc",                   SYS_nfssvc,                         nfssvc,                            2, CALL_DIRECT, INT, PTR)   /* 155  */
+#else
+ ENTRY("nfssvc",                   155,                                no_syscall,                        2, CALL_INDIRECT, VOID)   /* 155  */
+#endif
+ ENTRY("",                         155,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 155  */
+ ENTRY("",                         156,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 156  old getdirentries */
+ ENTRY("statfs",                   SYS_statfs,                         do_statfs,                         2, CALL_DIRECT, PTR, PTR)   /* 157  */
+ ENTRY("fstatfs",                  SYS_fstatfs,                        do_fstatfs,                        2, CALL_DIRECT, INT, PTR)   /* 158  */
+ ENTRY("unmount",                  SYS_unmount,                        unmount,                           2, CALL_DIRECT, PTR, INT)   /* 159  */
+ ENTRY("",                         160,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 160  old async_daemon */
+ ENTRY("",                         161,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 161  */
+ ENTRY("",                         162,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 162  old getdomainname */
+ ENTRY("",                         163,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 163  old setdomainname */
+ ENTRY("",                         164,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 164  */
+ ENTRY("quotactl",                 SYS_quotactl,                       no_syscall,                        4, CALL_INDIRECT, VOID) /* 165  */
+ ENTRY("",                         166,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 166  old exportfs */
+ ENTRY("mount",                    SYS_mount,                          mount,                             4, CALL_DIRECT, PTR, PTR, INT, PTR)   /* 167  */
+ ENTRY("",                         168,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 168  old ustat */
+ ENTRY("",                         169,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 169  */
+ ENTRY("table",                    SYS_table,                          no_syscall,                        0, CALL_INDIRECT, VOID) /* 170  old table */
+ ENTRY("",                         171,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 171  old wait3 */
+ ENTRY("",                         172,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 172  old rpause */
+ ENTRY("waitid",                   SYS_waitid,                         unimpl_unix_syscall,               4, CALL_INDIRECT, VOID) /* 173  */
+ ENTRY("",                         174,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 174  old getdents */
+ ENTRY("",                         175,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 175  old gc_control */
+ ENTRY("add_profil",               SYS_add_profil,                     add_profil,                        4, CALL_DIRECT, PTR, SIZE, UINT, UINT)   /* 176  */
+ ENTRY("",                         177,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 177  */
+ ENTRY("",                         178,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 178  */
+ ENTRY("",                         179,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 179  */
+ ENTRY("kdebug_trace",             SYS_kdebug_trace,                   no_syscall,                        6, CALL_INDIRECT, VOID) /* 180  */
+ ENTRY("setgid",                   SYS_setgid,                         setgid,                            1, CALL_DIRECT, INT)   /* 181  */
+ ENTRY("setegid",                  SYS_setegid,                        setegid,                           1, CALL_DIRECT, INT)   /* 182  */
+ ENTRY("seteuid",                  SYS_seteuid,                        seteuid,                           1, CALL_DIRECT, INT)   /* 183  */
+ ENTRY("sigreturn",                SYS_sigreturn,                      do_sigreturn,                      2, CALL_INDIRECT, PTR, INT)   /* 184  */
+ ENTRY("chud",                     SYS_chud,                           unimpl_unix_syscall,               6, CALL_INDIRECT, VOID)   /* 185  */
+ ENTRY("",                         186,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 186  */
+ ENTRY("",                         187,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 187  */
+ ENTRY("stat",                     SYS_stat,                           do_stat,                           2, CALL_DIRECT, PTR, PTR)   /* 188  */
+ ENTRY("fstat",                    SYS_fstat,                          do_fstat,                          2, CALL_DIRECT, INT, PTR)   /* 189  */
+ ENTRY("lstat",                    SYS_lstat,                          do_lstat,                          2, CALL_DIRECT, PTR, PTR)   /* 190  */
+ ENTRY("pathconf",                 SYS_pathconf,                       pathconf,                          2, CALL_DIRECT, PTR, INT)   /* 191  */
+ ENTRY("fpathconf",                SYS_fpathconf,                      fpathconf,                         2, CALL_DIRECT, INT, INT)   /* 192  */
+ ENTRY("getfsstat",                SYS_getfsstat,                      do_getfsstat,                      3, CALL_DIRECT, PTR, INT, INT)   /* 193  */
+ ENTRY("",                         193,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 193  */
+ ENTRY("getrlimit",                SYS_getrlimit,                      getrlimit,                         2, CALL_DIRECT, UINT, PTR)   /* 194  */
+ ENTRY("setrlimit",                SYS_setrlimit,                      setrlimit,                         2, CALL_DIRECT, UINT, PTR)   /* 195  */
+ ENTRY("getdirentries",            SYS_getdirentries,                  do_getdirentries,                  4, CALL_DIRECT, INT, PTR, UINT, PTR)   /* 196  */
+ ENTRY("mmap",                     SYS_mmap,                           target_mmap,                       6, CALL_DIRECT, UINT /*PTR*/, SIZE, INT, INT, INT, OFFSET)   /* 197  */
+ ENTRY("",                         198,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 198  __syscall */
+ ENTRY("lseek",                    SYS_lseek,                          do_lseek,                          3, CALL_INDIRECT, INT, OFFSET, INT)   /* 199  */
+ ENTRY("truncate",                 SYS_truncate,                       truncate,                          2, CALL_DIRECT, PTR, OFFSET)   /* 200  */
+ ENTRY("ftruncate",                SYS_ftruncate,                      ftruncate,                         2, CALL_DIRECT, INT, OFFSET)   /* 201  */
+ ENTRY("__sysctl",                 SYS___sysctl,                       do___sysctl,                       6, CALL_DIRECT, PTR, INT, PTR, PTR, PTR, SIZE)   /* 202  */
+ ENTRY("mlock",                    SYS_mlock,                          mlock,                             2, CALL_DIRECT, PTR, SIZE)   /* 203  */
+ ENTRY("munlock",                  SYS_munlock,                        munlock,                           2, CALL_DIRECT, PTR, SIZE)   /* 204  */
+ ENTRY("undelete",                 SYS_undelete,                       undelete,                          1, CALL_DIRECT, PTR)   /* 205  */
+ ENTRY("ATsocket",                 SYS_ATsocket,                       no_syscall,                        1, CALL_INDIRECT, VOID) /* 206  */
+ ENTRY("ATgetmsg",                 SYS_ATgetmsg,                       no_syscall,                        4, CALL_INDIRECT, VOID) /* 207  */
+ ENTRY("ATputmsg",                 SYS_ATputmsg,                       no_syscall,                        4, CALL_INDIRECT, VOID) /* 208  */
+ ENTRY("ATPsndreq",                SYS_ATPsndreq,                      no_syscall,                        4, CALL_INDIRECT, VOID) /* 209  */
+ ENTRY("ATPsndrsp",                SYS_ATPsndrsp,                      no_syscall,                        4, CALL_INDIRECT, VOID) /* 210  */
+ ENTRY("ATPgetreq",                SYS_ATPgetreq,                      no_syscall,                        3, CALL_INDIRECT, VOID) /* 211  */
+ ENTRY("ATPgetrsp",                SYS_ATPgetrsp,                      no_syscall,                        2, CALL_INDIRECT, VOID) /* 212  */
+ ENTRY("",                         213,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 213  Reserved for AppleTalk */
+ ENTRY("kqueue_from_portset_np",   SYS_kqueue_from_portset_np,         no_syscall,                        1, CALL_INDIRECT, VOID) /* 214  */
+ ENTRY("kqueue_portset_np",        SYS_kqueue_portset_np,              no_syscall,                        1, CALL_INDIRECT, VOID) /* 215  */
+ ENTRY("mkcomplex",                SYS_mkcomplex,                      no_syscall,                        3, CALL_INDIRECT, VOID)   /* 216  soon to be obsolete */
+ ENTRY("statv",                    SYS_statv,                          no_syscall,                        2, CALL_INDIRECT, VOID)   /* 217  soon to be obsolete */
+ ENTRY("lstatv",                   SYS_lstatv,                         no_syscall,                        2, CALL_INDIRECT, VOID)   /* 218  soon to be obsolete */
+ ENTRY("fstatv",                   SYS_fstatv,                         no_syscall,                        2, CALL_INDIRECT, VOID)   /* 219  soon to be obsolete */
+ ENTRY("getattrlist",              SYS_getattrlist,                    do_getattrlist,                    5, CALL_DIRECT, PTR, PTR, PTR, SIZE, UINT)   /* 220  */
+ ENTRY("setattrlist",              SYS_setattrlist,                    unimpl_unix_syscall,               5, CALL_INDIRECT, VOID) /* 221  */
+ ENTRY("getdirentriesattr",        SYS_getdirentriesattr,              do_getdirentriesattr,              8, CALL_DIRECT, INT, PTR, PTR, SIZE, PTR, PTR, PTR, UINT)   /* 222  */
+ ENTRY("exchangedata",             SYS_exchangedata,                   exchangedata,                      3, CALL_DIRECT, PTR, PTR, UINT)   /* 223  */
+ ENTRY("checkuseraccess",          SYS_checkuseraccess,                checkuseraccess,                   6, CALL_DIRECT, PTR, INT, PTR, INT, INT, UINT)   /* 224  */
+ ENTRY("",                         224,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 224  HFS checkuseraccess check access to a file */
+ ENTRY("searchfs",                 SYS_searchfs,                       searchfs,                          6, CALL_DIRECT, PTR, PTR, PTR, UINT, UINT, PTR)   /* 225  */
+ ENTRY("delete",                   SYS_delete,                         no_syscall,                        1, CALL_INDIRECT, VOID)   /* 226  private delete ( Carbon semantics ) */
+ ENTRY("copyfile",                 SYS_copyfile,                       no_syscall,                        4, CALL_INDIRECT, VOID)   /* 227  */
+ ENTRY("",                         228,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 228  */
+ ENTRY("",                         229,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 229  */
+ ENTRY("poll",                     SYS_poll,                           no_syscall,                        3, CALL_INDIRECT, VOID) /* 230  */
+ ENTRY("watchevent",               SYS_watchevent,                     no_syscall,                        2, CALL_INDIRECT, VOID)   /* 231  */
+ ENTRY("waitevent",                SYS_waitevent,                      no_syscall,                        2, CALL_INDIRECT, VOID)   /* 232  */
+ ENTRY("modwatch",                 SYS_modwatch,                       no_syscall,                        2, CALL_INDIRECT, VOID)   /* 233  */
+ ENTRY("getxattr",                 SYS_getxattr,                       no_syscall,                        6, CALL_INDIRECT, VOID)   /* 234  */
+ ENTRY("fgetxattr",                SYS_fgetxattr,                      no_syscall,                        6, CALL_INDIRECT, VOID)   /* 235  */
+ ENTRY("setxattr",                 SYS_setxattr,                       no_syscall,                        6, CALL_INDIRECT, VOID)   /* 236  */
+ ENTRY("fsetxattr",                SYS_fsetxattr,                      no_syscall,                        6, CALL_INDIRECT, VOID)   /* 237  */
+ ENTRY("removexattr",              SYS_removexattr,                    no_syscall,                        3, CALL_INDIRECT, VOID)   /* 238  */
+ ENTRY("fremovexattr",             SYS_fremovexattr,                   no_syscall,                        3, CALL_INDIRECT, VOID)   /* 239  */
+ ENTRY("listxattr",                SYS_listxattr,                      listxattr,                         4, CALL_INDIRECT, VOID)   /* 240  */
+ ENTRY("flistxattr",               SYS_flistxattr,                     no_syscall,                        4, CALL_INDIRECT, VOID)   /* 241  */
+ ENTRY("fsctl",                    SYS_fsctl,                          fsctl,                             4, CALL_DIRECT, PTR, UINT, PTR, UINT)   /* 242  */
+ ENTRY("initgroups",               SYS_initgroups,                     unimpl_unix_syscall,               3, CALL_INDIRECT, UINT, PTR, INT)   /* 243  */
+ ENTRY("",                         244,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 244  */
+ ENTRY("",                         245,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 245  */
+ ENTRY("",                         246,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 246  */
+#ifdef SYS_nfsclnt
+ ENTRY("nfsclnt",                  SYS_nfsclnt,                        nfsclnt,                           2, CALL_DIRECT, INT, PTR)   /* 247  */
+#else
+ ENTRY("nfsclnt",                  247,                                no_syscall,                        2, CALL_INDIRECT, VOID)   /* 247  */
+#endif
+ ENTRY("",                         247,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 247  */
+ ENTRY("",                         248,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 248  */
+ ENTRY("",                         249,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 249  */
+ ENTRY("minherit",                 SYS_minherit,                       minherit,                          3, CALL_DIRECT, PTR, INT, INT)   /* 250  */
+ ENTRY("semsys",                   SYS_semsys,                         unimpl_unix_syscall,               5, CALL_INDIRECT, VOID)   /* 251  */
+ ENTRY("msgsys",                   SYS_msgsys,                         unimpl_unix_syscall,               5, CALL_INDIRECT, VOID)   /* 252  */
+ ENTRY("shmsys",                   SYS_shmsys,                         unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 253  */
+ ENTRY("semctl",                   SYS_semctl,                         unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 254  */
+ ENTRY("semget",                   SYS_semget,                         unimpl_unix_syscall,               3, CALL_INDIRECT, VOID)   /* 255  */
+ ENTRY("semop",                    SYS_semop,                          unimpl_unix_syscall,               3, CALL_INDIRECT, VOID)   /* 256  */
+ ENTRY("",                         257,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 257  */
+ ENTRY("msgctl",                   SYS_msgctl,                         unimpl_unix_syscall,               3, CALL_INDIRECT, VOID)   /* 258  */
+ ENTRY("msgget",                   SYS_msgget,                         unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 259  */
+ ENTRY("msgsnd",                   SYS_msgsnd,                         unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 260  */
+ ENTRY("msgrcv",                   SYS_msgrcv,                         unimpl_unix_syscall,               5, CALL_INDIRECT, VOID)   /* 261  */
+ ENTRY("shmat",                    SYS_shmat,                          unimpl_unix_syscall,               3, CALL_INDIRECT, VOID)   /* 262  */
+ ENTRY("shmctl",                   SYS_shmctl,                         unimpl_unix_syscall,               3, CALL_INDIRECT, VOID)   /* 263  */
+ ENTRY("shmdt",                    SYS_shmdt,                          unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 264  */
+ ENTRY("shmget",                   SYS_shmget,                         unimpl_unix_syscall,               3, CALL_INDIRECT, VOID)   /* 265  */
+ ENTRY("shm_open",                 SYS_shm_open,                       shm_open,                          3, CALL_DIRECT, PTR, INT, INT)   /* 266  */
+ ENTRY("shm_unlink",               SYS_shm_unlink,                     shm_unlink,                        1, CALL_DIRECT, PTR)   /* 267  */
+ ENTRY("sem_open",                 SYS_sem_open,                       unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 268  */
+ ENTRY("sem_close",                SYS_sem_close,                      unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 269  */
+ ENTRY("sem_unlink",               SYS_sem_unlink,                     unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 270  */
+ ENTRY("sem_wait",                 SYS_sem_wait,                       unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 271  */
+ ENTRY("sem_trywait",              SYS_sem_trywait,                    unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 272  */
+ ENTRY("sem_post",                 SYS_sem_post,                       unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 273  */
+ ENTRY("sem_getvalue",             SYS_sem_getvalue,                   unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 274  */
+ ENTRY("sem_init",                 SYS_sem_init,                       unimpl_unix_syscall,               3, CALL_INDIRECT, VOID)   /* 275  */
+ ENTRY("sem_destroy",              SYS_sem_destroy,                    unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 276  */
+ ENTRY("open_extended",            SYS_open_extended,                  unimpl_unix_syscall,               6, CALL_INDIRECT, VOID)   /* 277  */
+ ENTRY("umask_extended",           SYS_umask_extended,                 unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 278  */
+ ENTRY("stat_extended",            SYS_stat_extended,                  unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 279  */
+ ENTRY("lstat_extended",           SYS_lstat_extended,                 unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 280  */
+ ENTRY("fstat_extended",           SYS_fstat_extended,                 unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 281  */
+ ENTRY("chmod_extended",           SYS_chmod_extended,                 unimpl_unix_syscall,               5, CALL_INDIRECT, VOID)   /* 282  */
+ ENTRY("fchmod_extended",          SYS_fchmod_extended,                unimpl_unix_syscall,               5, CALL_INDIRECT, VOID)   /* 283  */
+ ENTRY("access_extended",          SYS_access_extended,                unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 284  */
+ ENTRY("settid",                   SYS_settid,                         unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 285  */
+ ENTRY("gettid",                   SYS_gettid,                         unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 286  */
+ ENTRY("setsgroups",               SYS_setsgroups,                     unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 287  */
+ ENTRY("getsgroups",               SYS_getsgroups,                     unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 288  */
+ ENTRY("setwgroups",               SYS_setwgroups,                     unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 289  */
+ ENTRY("getwgroups",               SYS_getwgroups,                     unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 290  */
+ ENTRY("mkfifo_extended",          SYS_mkfifo_extended,                unimpl_unix_syscall,               5, CALL_INDIRECT, VOID)   /* 291  */
+ ENTRY("mkdir_extended",           SYS_mkdir_extended,                 unimpl_unix_syscall,               5, CALL_INDIRECT, VOID)   /* 292  */
+ ENTRY("identitysvc",              SYS_identitysvc,                    unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 293  */
+ ENTRY("",                         294,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 294  */
+ ENTRY("",                         295,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 295  */
+ ENTRY("load_shared_file",         SYS_load_shared_file,               unimpl_unix_syscall,               7, CALL_INDIRECT, VOID)   /* 296  */
+ ENTRY("reset_shared_file",        SYS_reset_shared_file,              unimpl_unix_syscall,               3, CALL_INDIRECT, VOID)   /* 297  */
+ ENTRY("new_system_shared_regions",  SYS_new_system_shared_regions,    unimpl_unix_syscall,               0, CALL_INDIRECT, VOID)   /* 298  */
+ ENTRY("shared_region_map_file_np",  SYS_shared_region_map_file_np,    unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 299  */
+ ENTRY("shared_region_make_private_np",  SYS_shared_region_make_private_np,  unimpl_unix_syscall,         2, CALL_INDIRECT, VOID)   /* 300  */
+ ENTRY("",                         301,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 301  */
+ ENTRY("",                         302,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 302  */
+ ENTRY("",                         303,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 303  */
+ ENTRY("",                         304,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 304  */
+ ENTRY("",                         305,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 305  */
+ ENTRY("",                         306,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 306  */
+ ENTRY("",                         307,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 307  */
+ ENTRY("",                         308,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 308  */
+ ENTRY("",                         309,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 309  */
+ ENTRY("getsid",                   SYS_getsid,                         getsid,                            1, CALL_DIRECT, INT)   /* 310  */
+ ENTRY("settid_with_pid",          SYS_settid_with_pid,                unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 311  */
+ ENTRY("",                         312,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 312  */
+ ENTRY("aio_fsync",                SYS_aio_fsync,                      unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 313  */
+ ENTRY("aio_return",               SYS_aio_return,                     unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 314  */
+ ENTRY("aio_suspend",              SYS_aio_suspend,                    unimpl_unix_syscall,               3, CALL_INDIRECT, VOID)   /* 315  */
+ ENTRY("aio_cancel",               SYS_aio_cancel,                     unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 316  */
+ ENTRY("aio_error",                SYS_aio_error,                      unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 317  */
+ ENTRY("aio_read",                 SYS_aio_read,                       unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 318  */
+ ENTRY("aio_write",                SYS_aio_write,                      unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 319  */
+ ENTRY("lio_listio",               SYS_lio_listio,                     unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 320  */
+ ENTRY("",                         321,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 321  */
+ ENTRY("",                         322,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 322  */
+ ENTRY("",                         323,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 323  */
+ ENTRY("mlockall",                 SYS_mlockall,                       mlockall,                          1, CALL_DIRECT, INT)   /* 324  */
+ ENTRY("munlockall",               SYS_munlockall,                     unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 325  */
+ ENTRY("",                         326,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 326  */
+ ENTRY("issetugid",                SYS_issetugid,                      issetugid,                         0, CALL_DIRECT, VOID)   /* 327  */
+ ENTRY("__pthread_kill",           SYS___pthread_kill,                 unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 328  */
+ ENTRY("pthread_sigmask",          SYS_pthread_sigmask,                pthread_sigmask,                   3, CALL_DIRECT, INT, PTR, PTR)   /* 329  */
+ ENTRY("sigwait",                  SYS_sigwait,                        sigwait,                           2, CALL_DIRECT, PTR, PTR)   /* 330  */
+ ENTRY("__disable_threadsignal",   SYS___disable_threadsignal,         unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 331  */
+ ENTRY("__pthread_markcancel",     SYS___pthread_markcancel,           unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 332  */
+ ENTRY("__pthread_canceled",       SYS___pthread_canceled,             unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 333  */
+ ENTRY("__semwait_signal",         SYS___semwait_signal,               unimpl_unix_syscall,               6, CALL_INDIRECT, VOID)   /* 334  */
+ ENTRY("utrace",                   SYS_utrace,                         unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 335  */
+ ENTRY("proc_info",                SYS_proc_info,                      unimpl_unix_syscall,               6, CALL_INDIRECT, VOID)   /* 336  */
+ ENTRY("",                         337,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 337  */
+ ENTRY("",                         338,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 338  */
+ ENTRY("",                         339,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 339  */
+ ENTRY("",                         340,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 340  */
+ ENTRY("",                         341,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 341  */
+ ENTRY("",                         342,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 342  */
+ ENTRY("",                         343,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 343  */
+ ENTRY("",                         344,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 344  */
+ ENTRY("",                         345,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 345  */
+ ENTRY("",                         346,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 346  */
+ ENTRY("",                         347,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 347  */
+ ENTRY("",                         348,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 348  */
+ ENTRY("",                         349,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 349  */
+ ENTRY("audit",                    SYS_audit,                          audit,                             2, CALL_DIRECT, PTR, INT)   /* 350  */
+ ENTRY("auditon",                  SYS_auditon,                        auditon,                           3, CALL_DIRECT, INT, PTR, INT)   /* 351  */
+ ENTRY("",                         352,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 352  */
+ ENTRY("getauid",                  SYS_getauid,                        getauid,                           1, CALL_DIRECT, PTR)   /* 353  */
+ ENTRY("setauid",                  SYS_setauid,                        setauid,                           1, CALL_DIRECT, PTR)   /* 354  */
+ ENTRY("getaudit",                 SYS_getaudit,                       getaudit,                          1, CALL_DIRECT, PTR)   /* 355  */
+ ENTRY("setaudit",                 SYS_setaudit,                       setaudit,                          1, CALL_DIRECT, PTR)   /* 356  */
+ ENTRY("getaudit_addr",            SYS_getaudit_addr,                  getaudit_addr,                     2, CALL_DIRECT, PTR, INT)   /* 357  */
+ ENTRY("setaudit_addr",            SYS_setaudit_addr,                  setaudit_addr,                     2, CALL_DIRECT, PTR, INT)   /* 358  */
+ ENTRY("auditctl",                 SYS_auditctl,                       auditctl,                          1, CALL_DIRECT, PTR)   /* 359  */
+ ENTRY("",                         360,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 360  */
+ ENTRY("",                         361,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 361  */
+ ENTRY("kqueue",                   SYS_kqueue,                         kqueue,                            0, CALL_DIRECT, VOID)   /* 362  */
+ ENTRY("kevent",                   SYS_kevent,                         kevent,                            6, CALL_DIRECT, INT, PTR, INT, PTR, INT, PTR)   /* 363  */
+ ENTRY("lchown",                   SYS_lchown,                         lchown,                            3, CALL_DIRECT, PTR, INT , INT)   /* 364  */
+ ENTRY("stack_snapshot",           SYS_stack_snapshot,                 unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 365  */
+ ENTRY("",                         366,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 366  */
+ ENTRY("",                         367,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 367  */
+ ENTRY("",                         368,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 368  */
+ ENTRY("",                         369,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 369  */

Modified: trunk/src/host/qemu-neo1973/dis-asm.h
===================================================================
--- trunk/src/host/qemu-neo1973/dis-asm.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/dis-asm.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -181,6 +181,7 @@
 #define bfd_mach_sh4al_dsp  0x4d
 #define bfd_mach_sh5        0x50
   bfd_arch_alpha,      /* Dec Alpha */
+#define bfd_mach_alpha 1
   bfd_arch_arm,        /* Advanced Risc Machines ARM */
 #define bfd_mach_arm_2         1
 #define bfd_mach_arm_2a                2
@@ -377,6 +378,7 @@
 extern int print_insn_v850		PARAMS ((bfd_vma, disassemble_info*));
 extern int print_insn_tic30		PARAMS ((bfd_vma, disassemble_info*));
 extern int print_insn_ppc		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_alpha             PARAMS ((bfd_vma, disassemble_info*));
 
 #if 0
 /* Fetch the disassembler for a given BFD, if that support is available.  */

Modified: trunk/src/host/qemu-neo1973/disas.c
===================================================================
--- trunk/src/host/qemu-neo1973/disas.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/disas.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -197,6 +197,9 @@
 #elif defined(TARGET_SH4)
     disasm_info.mach = bfd_mach_sh4;
     print_insn = print_insn_sh;
+#elif defined(TARGET_ALPHA)
+    disasm_info.mach = bfd_mach_alpha;
+    print_insn = print_insn_alpha;
 #else
     fprintf(out, "0x" TARGET_FMT_lx
 	    ": Asm output not supported on this arch\n", code);
@@ -255,6 +258,9 @@
     print_insn = print_insn_alpha;
 #elif defined(__sparc__)
     print_insn = print_insn_sparc;
+#if defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__)
+    disasm_info.mach = bfd_mach_sparc_v9b;
+#endif
 #elif defined(__arm__) 
     print_insn = print_insn_arm;
 #elif defined(__MIPSEB__)
@@ -378,6 +384,9 @@
     print_insn = print_insn_arm;
 #elif defined(TARGET_SPARC)
     print_insn = print_insn_sparc;
+#ifdef TARGET_SPARC64
+    disasm_info.mach = bfd_mach_sparc_v9b;
+#endif
 #elif defined(TARGET_PPC)
 #ifdef TARGET_PPC64
     disasm_info.mach = bfd_mach_ppc64;

Modified: trunk/src/host/qemu-neo1973/dyngen-exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/dyngen-exec.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/dyngen-exec.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -62,6 +62,9 @@
 #endif
 #endif
 
+/* XXX: This may be wrong for 64-bit ILP32 hosts.  */
+typedef void * host_reg_t;
+
 #define INT8_MIN		(-128)
 #define INT16_MIN		(-32767-1)
 #define INT32_MIN		(-2147483647-1)
@@ -75,27 +78,30 @@
 #define UINT32_MAX		(4294967295U)
 #define UINT64_MAX		((uint64_t)(18446744073709551615))
 
+#ifdef _BSD
+typedef struct __sFILE FILE;
+#else
 typedef struct FILE FILE;
+#endif
 extern int fprintf(FILE *, const char *, ...);
+extern int fputs(const char *, FILE *);
 extern int printf(const char *, ...);
 #undef NULL
 #define NULL 0
 
-#ifdef __i386__
+#if defined(__i386__)
 #define AREG0 "ebp"
 #define AREG1 "ebx"
 #define AREG2 "esi"
 #define AREG3 "edi"
-#endif
-#ifdef __x86_64__
-#define AREG0 "rbp"
-#define AREG1 "rbx"
+#elif defined(__x86_64__)
+#define AREG0 "r14"
+#define AREG1 "r15"
 #define AREG2 "r12"
 #define AREG3 "r13"
-//#define AREG4 "r14"
-//#define AREG5 "r15"
-#endif
-#ifdef __powerpc__
+//#define AREG4 "rbp"
+//#define AREG5 "rbx"
+#elif defined(__powerpc__)
 #define AREG0 "r27"
 #define AREG1 "r24"
 #define AREG2 "r25"
@@ -113,20 +119,22 @@
 #endif
 #define USE_INT_TO_FLOAT_HELPERS
 #define BUGGY_GCC_DIV64
-#endif
-#ifdef __arm__
+#elif defined(__arm__)
 #define AREG0 "r7"
 #define AREG1 "r4"
 #define AREG2 "r5"
 #define AREG3 "r6"
-#endif
-#ifdef __mips__
-#define AREG0 "s3"
+#elif defined(__mips__)
+#define AREG0 "fp"
 #define AREG1 "s0"
 #define AREG2 "s1"
 #define AREG3 "s2"
-#endif
-#ifdef __sparc__
+#define AREG4 "s3"
+#define AREG5 "s4"
+#define AREG6 "s5"
+#define AREG7 "s6"
+#define AREG8 "s7"
+#elif defined(__sparc__)
 #ifdef HOST_SOLARIS
 #define AREG0 "g2"
 #define AREG1 "g3"
@@ -155,14 +163,12 @@
 #endif
 #endif
 #define USE_FP_CONVERT
-#endif
-#ifdef __s390__
+#elif defined(__s390__)
 #define AREG0 "r10"
 #define AREG1 "r7"
 #define AREG2 "r8"
 #define AREG3 "r9"
-#endif
-#ifdef __alpha__
+#elif defined(__alpha__)
 /* Note $15 is the frame pointer, so anything in op-i386.c that would
    require a frame pointer, like alloca, would probably loose.  */
 #define AREG0 "$15"
@@ -172,19 +178,19 @@
 #define AREG4 "$12"
 #define AREG5 "$13"
 #define AREG6 "$14"
-#endif
-#ifdef __mc68000
+#elif defined(__mc68000)
 #define AREG0 "%a5"
 #define AREG1 "%a4"
 #define AREG2 "%d7"
 #define AREG3 "%d6"
 #define AREG4 "%d5"
-#endif
-#ifdef __ia64__
+#elif defined(__ia64__)
 #define AREG0 "r7"
 #define AREG1 "r4"
 #define AREG2 "r5"
 #define AREG3 "r6"
+#else
+#error unsupported CPU
 #endif
 
 /* force GCC to generate only one epilog at the end of the function */
@@ -237,40 +243,37 @@
 #define ASM_NAME(x) #x
 #endif
 
-#ifdef __i386__
+#if defined(__i386__)
 #define EXIT_TB() asm volatile ("ret")
 #define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __x86_64__
+#elif defined(__x86_64__)
 #define EXIT_TB() asm volatile ("ret")
 #define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __powerpc__
+#elif defined(__powerpc__)
 #define EXIT_TB() asm volatile ("blr")
 #define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __s390__
+#elif defined(__s390__)
 #define EXIT_TB() asm volatile ("br %r14")
 #define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __alpha__
+#elif defined(__alpha__)
 #define EXIT_TB() asm volatile ("ret")
-#endif
-#ifdef __ia64__
+#elif defined(__ia64__)
 #define EXIT_TB() asm volatile ("br.ret.sptk.many b0;;")
 #define GOTO_LABEL_PARAM(n) asm volatile ("br.sptk.many " \
 					  ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __sparc__
+#elif defined(__sparc__)
 #define EXIT_TB() asm volatile ("jmpl %i0 + 8, %g0; nop")
 #define GOTO_LABEL_PARAM(n) asm volatile ("ba " ASM_NAME(__op_gen_label) #n ";nop")
-#endif
-#ifdef __arm__
+#elif defined(__arm__)
 #define EXIT_TB() asm volatile ("b exec_loop")
 #define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __mc68000
+#elif defined(__mc68000)
 #define EXIT_TB() asm volatile ("rts")
+#elif defined(__mips__)
+#define EXIT_TB() asm volatile ("jr $ra")
+#define GOTO_LABEL_PARAM(n) asm volatile (".set noat; la $1, " ASM_NAME(__op_gen_label) #n "; jr $1; .set at")
+#else
+#error unsupported CPU
 #endif
 
 #endif /* !defined(__DYNGEN_EXEC_H__) */

Modified: trunk/src/host/qemu-neo1973/dyngen.c
===================================================================
--- trunk/src/host/qemu-neo1973/dyngen.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/dyngen.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -117,6 +117,21 @@
 #define elf_check_arch(x) ((x) == EM_68K)
 #define ELF_USES_RELOCA
 
+#elif defined(HOST_MIPS)
+
+#define ELF_CLASS	ELFCLASS32
+#define ELF_ARCH	EM_MIPS
+#define elf_check_arch(x) ((x) == EM_MIPS)
+#define ELF_USES_RELOC
+
+#elif defined(HOST_MIPS64)
+
+/* Assume n32 ABI here, which is ELF32. */
+#define ELF_CLASS	ELFCLASS32
+#define ELF_ARCH	EM_MIPS
+#define elf_check_arch(x) ((x) == EM_MIPS)
+#define ELF_USES_RELOCA
+
 #else
 #error unsupported CPU - please update the code
 #endif
@@ -148,11 +163,11 @@
 
 #ifdef CONFIG_FORMAT_COFF
 
-#include "a.out.h"
-
 typedef int32_t host_long;
 typedef uint32_t host_ulong;
 
+#include "a.out.h"
+
 #define FILENAMELEN 256
 
 typedef struct coff_sym {
@@ -1641,6 +1656,26 @@
             error("rts expected at the end of %s", name);
         copy_size = p - p_start;
     }
+#elif defined(HOST_MIPS) || defined(HOST_MIPS64)
+    {
+#define INSN_RETURN     0x03e00008
+#define INSN_NOP        0x00000000
+
+        uint8_t *p = p_end;
+
+        if (p < (p_start + 0x8)) {
+            error("empty code for %s", name);
+        } else {
+            uint32_t end_insn1, end_insn2;
+
+            p -= 0x8;
+            end_insn1 = get32((uint32_t *)(p + 0x0));
+            end_insn2 = get32((uint32_t *)(p + 0x4));
+            if (end_insn1 != INSN_RETURN && end_insn2 != INSN_NOP)
+                error("jr ra not found at end of %s", name);
+        }
+        copy_size = p - p_start;
+    }
 #else
 #error unsupported CPU
 #endif
@@ -1715,8 +1750,9 @@
 		    }
 #endif
 #if defined(__APPLE__)
-/* set __attribute((unused)) on darwin because we wan't to avoid warning when we don't use the symbol */
-                    fprintf(outfile, "extern char %s __attribute__((unused));\n", sym_name);
+                    /* Set __attribute((unused)) on darwin because we
+                       want to avoid warning when we don't use the symbol.  */
+                    fprintf(outfile, "    extern char %s __attribute__((unused));\n", sym_name);
 #elif defined(HOST_IA64)
 			if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
 				/*
@@ -1740,7 +1776,7 @@
         {
             EXE_SYM *sym;
             const char *sym_name, *p;
-            unsigned long val;
+            host_ulong val;
             int n;
 
             for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
@@ -1772,7 +1808,7 @@
 #ifdef CONFIG_FORMAT_MACH
                     offset -= section_hdr[sym->n_sect-1].addr;
 #endif
-                    val = *(unsigned long *)(ptr + offset);
+                    val = *(host_ulong *)(ptr + offset);
 #ifdef ELF_USES_RELOCA
                     {
                         int reloc_shndx, nb_relocs1, j;
@@ -1801,7 +1837,7 @@
             }
         }
 
-        /* load parameres in variables */
+        /* load parameters in variables */
         for(i = 0; i < nb_args; i++) {
             fprintf(outfile, "    param%d = *opparam_ptr++;\n", i + 1);
         }
@@ -2349,6 +2385,33 @@
                                     reloc_offset, reloc_offset, name, addend,
 				    reloc_offset);
                             break;
+                        case R_SPARC_HH22:
+                            fprintf(outfile,
+				    "    *(uint32_t *)(gen_code_ptr + %d) = "
+				    "((*(uint32_t *)(gen_code_ptr + %d)) "
+				    " & ~0x00000000) "
+				    " | (((%s + %d) >> 42) & 0x00000000);\n",
+                                    reloc_offset, reloc_offset, name, addend);
+                             break;
+
+			case R_SPARC_LM22:
+                            fprintf(outfile,
+				    "    *(uint32_t *)(gen_code_ptr + %d) = "
+				    "((*(uint32_t *)(gen_code_ptr + %d)) "
+				    " & ~0x00000000) "
+				    " | (((%s + %d) >> 10) & 0x00000000);\n",
+                                    reloc_offset, reloc_offset, name, addend);
+			    break;
+
+			case R_SPARC_HM10:
+                            fprintf(outfile,
+				    "    *(uint32_t *)(gen_code_ptr + %d) = "
+				    "((*(uint32_t *)(gen_code_ptr + %d)) "
+				    " & ~0x00000000) "
+				    " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
+                                    reloc_offset, reloc_offset, name, addend);
+			    break;
+
                         default:
 			    error("unsupported sparc64 relocation (%d) for symbol %s", type, name);
                         }
@@ -2456,6 +2519,81 @@
                 }
                 }
             }
+#elif defined(HOST_MIPS) || defined(HOST_MIPS64)
+            {
+                for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
+		    if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
+                        char name[256];
+                        int type;
+                        int addend;
+                        int reloc_offset;
+
+			sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
+                        /* the compiler leave some unnecessary references to the code */
+                        if (sym_name[0] == '\0')
+                            continue;
+                        get_reloc_expr(name, sizeof(name), sym_name);
+			type = ELF32_R_TYPE(rel->r_info);
+                        addend = get32((uint32_t *)(text + rel->r_offset));
+                        reloc_offset = rel->r_offset - start_offset;
+			switch (type) {
+			case R_MIPS_26:
+                            fprintf(outfile, "    /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n",
+				    rel->r_offset, sym_name);
+                            fprintf(outfile,
+				    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
+				    "(0x%x & ~0x3fffff) "
+				    "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
+				    "   & 0x3fffff);\n",
+                                    reloc_offset, addend, addend, name, reloc_offset);
+			    break;
+			case R_MIPS_HI16:
+                            fprintf(outfile, "    /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n",
+				    rel->r_offset, sym_name);
+                            fprintf(outfile,
+				    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
+				    "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
+				    " & ~0xffff) "
+				    " | (((%s - 0x8000) >> 16) & 0xffff);\n",
+                                    reloc_offset, reloc_offset, name);
+			    break;
+			case R_MIPS_LO16:
+                            fprintf(outfile, "    /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n",
+				    rel->r_offset, sym_name);
+                            fprintf(outfile,
+				    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
+				    "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
+				    " & ~0xffff) "
+				    " | (%s & 0xffff);\n",
+                                    reloc_offset, reloc_offset, name);
+			    break;
+			case R_MIPS_PC16:
+                            fprintf(outfile, "    /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
+				    rel->r_offset, sym_name);
+                            fprintf(outfile,
+				    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
+				    "(0x%x & ~0xffff) "
+				    "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
+				    "   & 0xffff);\n",
+                                    reloc_offset, addend, addend, name, reloc_offset);
+			    break;
+			case R_MIPS_GOT16:
+			case R_MIPS_CALL16:
+                            fprintf(outfile, "    /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
+				    rel->r_offset, sym_name);
+                            fprintf(outfile,
+				    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
+				    "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
+				    " & ~0xffff) "
+				    " | (((%s - 0x8000) >> 16) & 0xffff);\n",
+                                    reloc_offset, reloc_offset, name);
+			    break;
+			default:
+			    error("unsupported MIPS relocation (%d)", type);
+			}
+		    }
+                }
+            }
 #else
 #error unsupported CPU
 #endif

Modified: trunk/src/host/qemu-neo1973/dyngen.h
===================================================================
--- trunk/src/host/qemu-neo1973/dyngen.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/dyngen.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -28,37 +28,21 @@
 #endif
 int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
 
-#ifdef __i386__
+#if defined(__i386__) || defined(__x86_64__) || defined(__s390__)
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
 }
-#endif
-
-#ifdef __x86_64__
+#elif defined(__ia64__)
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
-}
-#endif
-
-#ifdef __s390__
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
-{
-}
-#endif
-
-#ifdef __ia64__
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
-{
     while (start < stop) {
 	asm volatile ("fc %0" :: "r"(start));
 	start += 32;
     }
     asm volatile (";;sync.i;;srlz.i;;");
 }
-#endif
+#elif defined(__powerpc__)
 
-#ifdef __powerpc__
-
 #define MIN_CACHE_LINE_SIZE 8 /* conservative value */
 
 static void inline flush_icache_range(unsigned long start, unsigned long stop)
@@ -78,17 +62,12 @@
     asm volatile ("sync" : : : "memory");
     asm volatile ("isync" : : : "memory");
 }
-#endif
-
-#ifdef __alpha__
+#elif defined(__alpha__)
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
     asm ("imb");
 }
-#endif
-
-#ifdef __sparc__
-
+#elif defined(__sparc__)
 static void inline flush_icache_range(unsigned long start, unsigned long stop)
 {
 	unsigned long p;
@@ -99,10 +78,7 @@
 	for (; p < stop; p += 8)
 		__asm__ __volatile__("flush\t%0" : : "r" (p));
 }
-
-#endif
-
-#ifdef __arm__
+#elif defined(__arm__)
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
     register unsigned long _beg __asm ("a1") = start;
@@ -110,14 +86,22 @@
     register unsigned long _flg __asm ("a3") = 0;
     __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
 }
-#endif
+#elif defined(__mc68000)
 
-#ifdef __mc68000
-#include <asm/cachectl.h>
+# include <asm/cachectl.h>
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
     cacheflush(start,FLUSH_SCOPE_LINE,FLUSH_CACHE_BOTH,stop-start+16);
 }
+#elif defined(__mips__)
+
+#include <sys/cachectl.h>
+static inline void flush_icache_range(unsigned long start, unsigned long stop)
+{
+    _flush_cache ((void *)start, stop - start, BCACHE);
+}
+#else
+#error unsupported CPU
 #endif
 
 #ifdef __alpha__
@@ -248,7 +232,6 @@
 
 #ifdef __ia64
 
-
 /* Patch instruction with "val" where "mask" has 1 bits. */
 static inline void ia64_patch (uint64_t insn_addr, uint64_t mask, uint64_t val)
 {

Modified: trunk/src/host/qemu-neo1973/ecc.h
===================================================================
--- trunk/src/host/qemu-neo1973/ecc.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/ecc.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -5,7 +5,7 @@
  * Copyright (c) 2006 Openedhand Ltd.
  * Written by Andrzej Zaborowski <balrog at zabor.org>
  *
- * This code is licensed under the GPLv2.
+ * This code is licensed under the GNU GPL v2.
  */
 
 struct ecc_state_s {

Modified: trunk/src/host/qemu-neo1973/elf.h
===================================================================
--- trunk/src/host/qemu-neo1973/elf.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/elf.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -328,6 +328,9 @@
 #define R_SPARC_11		31
 #define R_SPARC_64		32
 #define R_SPARC_OLO10           33
+#define R_SPARC_HH22            34
+#define R_SPARC_HM10            35
+#define R_SPARC_LM22            36
 #define R_SPARC_WDISP16		40
 #define R_SPARC_WDISP19		41
 #define R_SPARC_7		43

Modified: trunk/src/host/qemu-neo1973/elf_ops.h
===================================================================
--- trunk/src/host/qemu-neo1973/elf_ops.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/elf_ops.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -139,11 +139,13 @@
 }
 
 int glue(load_elf, SZ)(int fd, int64_t virt_to_phys_addend,
-                       int must_swab, uint64_t *pentry)
+                       int must_swab, uint64_t *pentry,
+                       uint64_t *lowaddr, uint64_t *highaddr)
 {
     struct elfhdr ehdr;
     struct elf_phdr *phdr = NULL, *ph;
     int size, i, total_size;
+    elf_word low = 0, high = 0;
     elf_word mem_size, addr;
     uint8_t *data = NULL;
 
@@ -193,12 +195,20 @@
             cpu_physical_memory_write_rom(addr, data, mem_size);
 
             total_size += mem_size;
+            if (!low || addr < low)
+                low = addr;
+            if (!high || (addr + mem_size) > high)
+                high = addr + mem_size;
 
             qemu_free(data);
             data = NULL;
         }
     }
     qemu_free(phdr);
+    if (lowaddr)
+        *lowaddr = (uint64_t)low;
+    if (highaddr)
+        *highaddr = (uint64_t)high;
     return total_size;
  fail:
     qemu_free(data);

Modified: trunk/src/host/qemu-neo1973/exec-all.h
===================================================================
--- trunk/src/host/qemu-neo1973/exec-all.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/exec-all.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -357,7 +357,7 @@
 extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
 extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
 
-#ifdef __powerpc__
+#if defined(__powerpc__)
 static inline int testandset (int *p)
 {
     int ret;
@@ -373,9 +373,7 @@
                           : "cr0", "memory");
     return ret;
 }
-#endif
-
-#ifdef __i386__
+#elif defined(__i386__)
 static inline int testandset (int *p)
 {
     long int readval = 0;
@@ -386,9 +384,7 @@
                           : "cc");
     return readval;
 }
-#endif
-
-#ifdef __x86_64__
+#elif defined(__x86_64__)
 static inline int testandset (int *p)
 {
     long int readval = 0;
@@ -399,9 +395,7 @@
                           : "cc");
     return readval;
 }
-#endif
-
-#ifdef __s390__
+#elif defined(__s390__)
 static inline int testandset (int *p)
 {
     int ret;
@@ -413,9 +407,7 @@
 			  : "cc", "memory" );
     return ret;
 }
-#endif
-
-#ifdef __alpha__
+#elif defined(__alpha__)
 static inline int testandset (int *p)
 {
     int ret;
@@ -432,9 +424,7 @@
 			  : "m" (*p));
     return ret;
 }
-#endif
-
-#ifdef __sparc__
+#elif defined(__sparc__)
 static inline int testandset (int *p)
 {
 	int ret;
@@ -446,9 +436,7 @@
 
 	return (ret ? 1 : 0);
 }
-#endif
-
-#ifdef __arm__
+#elif defined(__arm__)
 static inline int testandset (int *spinlock)
 {
     register unsigned int ret;
@@ -458,9 +446,7 @@
     
     return ret;
 }
-#endif
-
-#ifdef __mc68000
+#elif defined(__mc68000)
 static inline int testandset (int *p)
 {
     char ret;
@@ -470,15 +456,36 @@
                          : "cc","memory");
     return ret;
 }
-#endif
+#elif defined(__ia64)
 
-#ifdef __ia64
 #include <ia64intrin.h>
 
 static inline int testandset (int *p)
 {
     return __sync_lock_test_and_set (p, 1);
 }
+#elif defined(__mips__)
+static inline int testandset (int *p)
+{
+    int ret;
+
+    __asm__ __volatile__ (
+	"	.set push		\n"
+	"	.set noat		\n"
+	"	.set mips2		\n"
+	"1:	li	$1, 1		\n"
+	"	ll	%0, %1		\n"
+	"	sc	$1, %1		\n"
+	"	bnez	$1, 1b		\n"
+	"	.set pop		"
+	: "=r" (ret), "+R" (*p)
+	:
+	: "memory");
+
+    return ret;
+}
+#else
+#error unimplemented CPU support
 #endif
 
 typedef int spinlock_t;
@@ -572,6 +579,8 @@
     is_user = ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR);
 #elif defined (TARGET_SH4)
     is_user = ((env->sr & SR_MD) == 0);
+#elif defined (TARGET_ALPHA)
+    is_user = ((env->ps >> 3) & 3);
 #else
 #error unimplemented CPU
 #endif
@@ -581,13 +590,12 @@
     }
     pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK;
     if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
-        cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x%08lx\n", addr);
+        cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);
     }
     return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base;
 }
 #endif
 
-
 #ifdef USE_KQEMU
 #define KQEMU_MODIFY_PAGE_MASK (0xff & ~(VGA_DIRTY_FLAG | CODE_DIRTY_FLAG))
 

Modified: trunk/src/host/qemu-neo1973/exec.c
===================================================================
--- trunk/src/host/qemu-neo1973/exec.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/exec.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -47,6 +47,8 @@
 //#define DEBUG_TB_CHECK 
 //#define DEBUG_TLB_CHECK 
 
+//#define DEBUG_IOPORT
+
 #if !defined(CONFIG_USER_ONLY)
 /* TB consistency checks only implemented for usermode emulation.  */
 #undef DEBUG_TB_CHECK
@@ -62,6 +64,9 @@
 
 #if defined(TARGET_SPARC64)
 #define TARGET_PHYS_ADDR_SPACE_BITS 41
+#elif defined(TARGET_ALPHA)
+#define TARGET_PHYS_ADDR_SPACE_BITS 42
+#define TARGET_VIRT_ADDR_SPACE_BITS 42
 #elif defined(TARGET_PPC64)
 #define TARGET_PHYS_ADDR_SPACE_BITS 42
 #else
@@ -82,6 +87,7 @@
 int phys_ram_fd;
 uint8_t *phys_ram_base;
 uint8_t *phys_ram_dirty;
+static ram_addr_t phys_ram_alloc_offset = 0;
 
 CPUState *first_cpu;
 /* current CPU in the current thread. It is only valid inside
@@ -106,7 +112,15 @@
 } PhysPageDesc;
 
 #define L2_BITS 10
+#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
+/* XXX: this is a temporary hack for alpha target.
+ *      In the future, this is to be replaced by a multi-level table
+ *      to actually be able to handle the complete 64 bits address space.
+ */
+#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
+#else
 #define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
+#endif
 
 #define L1_SIZE (1 << L1_BITS)
 #define L2_SIZE (1 << L2_BITS)
@@ -127,6 +141,9 @@
 CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
 void *io_mem_opaque[IO_MEM_NB_ENTRIES];
 static int io_mem_nb;
+#if defined(CONFIG_SOFTMMU)
+static int io_mem_watch;
+#endif
 
 /* log support */
 char *logfilename = "/tmp/qemu.log";
@@ -273,6 +290,7 @@
         cpu_index++;
     }
     env->cpu_index = cpu_index;
+    env->nb_watchpoints = 0;
     *penv = env;
 }
 
@@ -331,7 +349,7 @@
 
 #ifdef DEBUG_TB_CHECK
 
-static void tb_invalidate_check(unsigned long address)
+static void tb_invalidate_check(target_ulong address)
 {
     TranslationBlock *tb;
     int i;
@@ -1012,7 +1030,8 @@
 #if defined(TARGET_HAS_ICE)
 static void breakpoint_invalidate(CPUState *env, target_ulong pc)
 {
-    target_ulong addr, pd;
+    target_phys_addr_t addr;
+    target_ulong pd;
     ram_addr_t ram_addr;
     PhysPageDesc *p;
 
@@ -1028,6 +1047,44 @@
 }
 #endif
 
+/* Add a watchpoint.  */
+int  cpu_watchpoint_insert(CPUState *env, target_ulong addr)
+{
+    int i;
+
+    for (i = 0; i < env->nb_watchpoints; i++) {
+        if (addr == env->watchpoint[i].vaddr)
+            return 0;
+    }
+    if (env->nb_watchpoints >= MAX_WATCHPOINTS)
+        return -1;
+
+    i = env->nb_watchpoints++;
+    env->watchpoint[i].vaddr = addr;
+    tlb_flush_page(env, addr);
+    /* FIXME: This flush is needed because of the hack to make memory ops
+       terminate the TB.  It can be removed once the proper IO trap and
+       re-execute bits are in.  */
+    tb_flush(env);
+    return i;
+}
+
+/* Remove a watchpoint.  */
+int cpu_watchpoint_remove(CPUState *env, target_ulong addr)
+{
+    int i;
+
+    for (i = 0; i < env->nb_watchpoints; i++) {
+        if (addr == env->watchpoint[i].vaddr) {
+            env->nb_watchpoints--;
+            env->watchpoint[i] = env->watchpoint[env->nb_watchpoints];
+            tlb_flush_page(env, addr);
+            return 0;
+        }
+    }
+    return -1;
+}
+
 /* add a breakpoint. EXCP_DEBUG is returned by the CPU loop if a
    breakpoint is reached */
 int cpu_breakpoint_insert(CPUState *env, target_ulong pc)
@@ -1221,6 +1278,18 @@
     abort();
 }
 
+CPUState *cpu_copy(CPUState *env)
+{
+    CPUState *new_env = cpu_init();
+    /* preserve chaining and index */
+    CPUState *next_cpu = new_env->next_cpu;
+    int cpu_index = new_env->cpu_index;
+    memcpy(new_env, env, sizeof(CPUState));
+    new_env->next_cpu = next_cpu;
+    new_env->cpu_index = cpu_index;
+    return new_env;
+}
+
 #if !defined(CONFIG_USER_ONLY)
 
 /* NOTE: if flush_global is true, also flush global entries (not
@@ -1243,6 +1312,16 @@
         env->tlb_table[1][i].addr_read = -1;
         env->tlb_table[1][i].addr_write = -1;
         env->tlb_table[1][i].addr_code = -1;
+#if (NB_MMU_MODES >= 3)
+        env->tlb_table[2][i].addr_read = -1;
+        env->tlb_table[2][i].addr_write = -1;
+        env->tlb_table[2][i].addr_code = -1;
+#if (NB_MMU_MODES == 4)
+        env->tlb_table[3][i].addr_read = -1;
+        env->tlb_table[3][i].addr_write = -1;
+        env->tlb_table[3][i].addr_code = -1;
+#endif
+#endif
     }
 
     memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
@@ -1288,6 +1367,12 @@
     i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
     tlb_flush_entry(&env->tlb_table[0][i], addr);
     tlb_flush_entry(&env->tlb_table[1][i], addr);
+#if (NB_MMU_MODES >= 3)
+    tlb_flush_entry(&env->tlb_table[2][i], addr);
+#if (NB_MMU_MODES == 4)
+    tlb_flush_entry(&env->tlb_table[3][i], addr);
+#endif
+#endif
 
     /* Discard jump cache entries for any tb which might potentially
        overlap the flushed page.  */
@@ -1377,6 +1462,14 @@
             tlb_reset_dirty_range(&env->tlb_table[0][i], start1, length);
         for(i = 0; i < CPU_TLB_SIZE; i++)
             tlb_reset_dirty_range(&env->tlb_table[1][i], start1, length);
+#if (NB_MMU_MODES >= 3)
+        for(i = 0; i < CPU_TLB_SIZE; i++)
+            tlb_reset_dirty_range(&env->tlb_table[2][i], start1, length);
+#if (NB_MMU_MODES == 4)
+        for(i = 0; i < CPU_TLB_SIZE; i++)
+            tlb_reset_dirty_range(&env->tlb_table[3][i], start1, length);
+#endif
+#endif
     }
 
 #if !defined(CONFIG_SOFTMMU)
@@ -1429,6 +1522,14 @@
         tlb_update_dirty(&env->tlb_table[0][i]);
     for(i = 0; i < CPU_TLB_SIZE; i++)
         tlb_update_dirty(&env->tlb_table[1][i]);
+#if (NB_MMU_MODES >= 3)
+    for(i = 0; i < CPU_TLB_SIZE; i++)
+        tlb_update_dirty(&env->tlb_table[2][i]);
+#if (NB_MMU_MODES == 4)
+    for(i = 0; i < CPU_TLB_SIZE; i++)
+        tlb_update_dirty(&env->tlb_table[3][i]);
+#endif
+#endif
 }
 
 static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, 
@@ -1454,6 +1555,12 @@
     i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
     tlb_set_dirty1(&env->tlb_table[0][i], addr);
     tlb_set_dirty1(&env->tlb_table[1][i], addr);
+#if (NB_MMU_MODES >= 3)
+    tlb_set_dirty1(&env->tlb_table[2][i], addr);
+#if (NB_MMU_MODES == 4)
+    tlb_set_dirty1(&env->tlb_table[3][i], addr);
+#endif
+#endif
 }
 
 /* add a new TLB entry. At most one entry for a given virtual address
@@ -1471,6 +1578,7 @@
     target_phys_addr_t addend;
     int ret;
     CPUTLBEntry *te;
+    int i;
 
     p = phys_page_find(paddr >> TARGET_PAGE_BITS);
     if (!p) {
@@ -1497,6 +1605,22 @@
             address = vaddr;
             addend = (unsigned long)phys_ram_base + (pd & TARGET_PAGE_MASK);
         }
+
+        /* Make accesses to pages with watchpoints go via the
+           watchpoint trap routines.  */
+        for (i = 0; i < env->nb_watchpoints; i++) {
+            if (vaddr == (env->watchpoint[i].vaddr & TARGET_PAGE_MASK)) {
+                if (address & ~TARGET_PAGE_MASK) {
+                    env->watchpoint[i].is_ram = 0;
+                    address = vaddr | io_mem_watch;
+                } else {
+                    env->watchpoint[i].is_ram = 1;
+                    /* TODO: Figure out how to make read watchpoints coexist
+                       with code.  */
+                    pd = (pd & TARGET_PAGE_MASK) | io_mem_watch | IO_MEM_ROMD;
+                }
+            }
+        }
         
         index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
         addend -= vaddr;
@@ -1812,11 +1936,33 @@
     return p->phys_offset;
 }
 
+/* XXX: better than nothing */
+ram_addr_t qemu_ram_alloc(unsigned int size)
+{
+    ram_addr_t addr;
+    if ((phys_ram_alloc_offset + size) >= phys_ram_size) {
+        fprintf(stderr, "Not enough memory (requested_size = %u, max memory = %d)\n", 
+                size, phys_ram_size);
+        abort();
+    }
+    addr = phys_ram_alloc_offset;
+    phys_ram_alloc_offset = TARGET_PAGE_ALIGN(phys_ram_alloc_offset + size);
+    return addr;
+}
+
+void qemu_ram_free(ram_addr_t addr)
+{
+}
+
 static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
 {
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem read  0x%08x\n", (int)addr);
 #endif
+#ifdef TARGET_SPARC
+    // Not enabled yet because of bugs in gdbstub etc.
+    //raise_exception(TT_DATA_ACCESS);
+#endif
     return 0;
 }
 
@@ -1825,6 +1971,10 @@
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem write 0x%08x = 0x%x\n", (int)addr, val);
 #endif
+#ifdef TARGET_SPARC
+    // Not enabled yet because of bugs in gdbstub etc.
+    //raise_exception(TT_DATA_ACCESS);
+#endif
 }
 
 static CPUReadMemoryFunc *unassigned_mem_read[3] = {
@@ -1929,6 +2079,85 @@
     notdirty_mem_writel,
 };
 
+#if defined(CONFIG_SOFTMMU)
+/* Watchpoint access routines.  Watchpoints are inserted using TLB tricks,
+   so these check for a hit then pass through to the normal out-of-line
+   phys routines.  */
+static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
+{
+    return ldub_phys(addr);
+}
+
+static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
+{
+    return lduw_phys(addr);
+}
+
+static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+    return ldl_phys(addr);
+}
+
+/* Generate a debug exception if a watchpoint has been hit.
+   Returns the real physical address of the access.  addr will be a host
+   address in the is_ram case.  */
+static target_ulong check_watchpoint(target_phys_addr_t addr)
+{
+    CPUState *env = cpu_single_env;
+    target_ulong watch;
+    target_ulong retaddr;
+    int i;
+
+    retaddr = addr;
+    for (i = 0; i < env->nb_watchpoints; i++) {
+        watch = env->watchpoint[i].vaddr;
+        if (((env->mem_write_vaddr ^ watch) & TARGET_PAGE_MASK) == 0) {
+            if (env->watchpoint[i].is_ram)
+                retaddr = addr - (unsigned long)phys_ram_base;
+            if (((addr ^ watch) & ~TARGET_PAGE_MASK) == 0) {
+                cpu_single_env->watchpoint_hit = i + 1;
+                cpu_interrupt(cpu_single_env, CPU_INTERRUPT_DEBUG);
+                break;
+            }
+        }
+    }
+    return retaddr;
+}
+
+static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
+                             uint32_t val)
+{
+    addr = check_watchpoint(addr);
+    stb_phys(addr, val);
+}
+
+static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
+                             uint32_t val)
+{
+    addr = check_watchpoint(addr);
+    stw_phys(addr, val);
+}
+
+static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
+                             uint32_t val)
+{
+    addr = check_watchpoint(addr);
+    stl_phys(addr, val);
+}
+
+static CPUReadMemoryFunc *watch_mem_read[3] = {
+    watch_mem_readb,
+    watch_mem_readw,
+    watch_mem_readl,
+};
+
+static CPUWriteMemoryFunc *watch_mem_write[3] = {
+    watch_mem_writeb,
+    watch_mem_writew,
+    watch_mem_writel,
+};
+#endif
+
 static void io_mem_init(void)
 {
     cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read, unassigned_mem_write, NULL);
@@ -1936,6 +2165,10 @@
     cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read, notdirty_mem_write, NULL);
     io_mem_nb = 5;
 
+#if defined(CONFIG_SOFTMMU)
+    io_mem_watch = cpu_register_io_memory(-1, watch_mem_read,
+                                          watch_mem_write, NULL);
+#endif
     /* alloc dirty bits array */
     phys_ram_dirty = qemu_vmalloc(phys_ram_size >> TARGET_PAGE_BITS);
     memset(phys_ram_dirty, 0xff, phys_ram_size >> TARGET_PAGE_BITS);
@@ -2258,6 +2491,36 @@
     }
 }
 
+void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
+{
+    int io_index;
+    uint8_t *ptr;
+    unsigned long pd;
+    PhysPageDesc *p;
+
+    p = phys_page_find(addr >> TARGET_PAGE_BITS);
+    if (!p) {
+        pd = IO_MEM_UNASSIGNED;
+    } else {
+        pd = p->phys_offset;
+    }
+        
+    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
+        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+#ifdef TARGET_WORDS_BIGENDIAN
+        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
+        io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
+#else
+        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
+        io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
+#endif
+    } else {
+        ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
+            (addr & ~TARGET_PAGE_MASK);
+        stq_p(ptr, val);
+    }
+}
+
 /* warning: addr must be aligned */
 void stl_phys(target_phys_addr_t addr, uint32_t val)
 {
@@ -2320,7 +2583,8 @@
                         uint8_t *buf, int len, int is_write)
 {
     int l;
-    target_ulong page, phys_addr;
+    target_phys_addr_t phys_addr;
+    target_ulong page;
 
     while (len > 0) {
         page = addr & TARGET_PAGE_MASK;

Modified: trunk/src/host/qemu-neo1973/fpu/softfloat-native.c
===================================================================
--- trunk/src/host/qemu-neo1973/fpu/softfloat-native.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/fpu/softfloat-native.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -30,7 +30,26 @@
 #define sqrtf(f)		((float)sqrt(f))
 #define remainderf(fa, fb)	((float)remainder(fa, fb))
 #define rintf(f)		((float)rint(f))
+#if !defined(__sparc__) && defined(HOST_SOLARIS) && HOST_SOLARIS < 10
+extern long double rintl(long double);
+extern long double scalbnl(long double, int);
+
+long long
+llrintl(long double x) {
+	return ((long long) rintl(x));
+}
+
+long
+lrintl(long double x) {
+	return ((long) rintl(x));
+}
+
+long double
+ldexpl(long double x, int n) {
+	return (scalbnl(x, n));
+}
 #endif
+#endif
 
 #if defined(__powerpc__)
 
@@ -59,11 +78,21 @@
     return (float32)v;
 }
 
+float32 uint32_to_float32(unsigned int v STATUS_PARAM)
+{
+    return (float32)v;
+}
+
 float64 int32_to_float64(int v STATUS_PARAM)
 {
     return (float64)v;
 }
 
+float64 uint32_to_float64(unsigned int v STATUS_PARAM)
+{
+    return (float64)v;
+}
+
 #ifdef FLOATX80
 floatx80 int32_to_floatx80(int v STATUS_PARAM)
 {
@@ -74,10 +103,18 @@
 {
     return (float32)v;
 }
+float32 uint64_to_float32( uint64_t v STATUS_PARAM)
+{
+    return (float32)v;
+}
 float64 int64_to_float64( int64_t v STATUS_PARAM)
 {
     return (float64)v;
 }
+float64 uint64_to_float64( uint64_t v STATUS_PARAM)
+{
+    return (float64)v;
+}
 #ifdef FLOATX80
 floatx80 int64_to_floatx80( int64_t v STATUS_PARAM)
 {
@@ -132,6 +169,37 @@
 }
 #endif
 
+unsigned int float32_to_uint32( float32 a STATUS_PARAM)
+{
+    int64_t v;
+    unsigned int res;
+
+    v = llrintf(a);
+    if (v < 0) {
+        res = 0;
+    } else if (v > 0xffffffff) {
+        res = 0xffffffff;
+    } else {
+        res = v;
+    }
+    return res;
+}
+unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM)
+{
+    int64_t v;
+    unsigned int res;
+
+    v = (int64_t)a;
+    if (v < 0) {
+        res = 0;
+    } else if (v > 0xffffffff) {
+        res = 0xffffffff;
+    } else {
+        res = v;
+    }
+    return res;
+}
+
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE single-precision operations.
 *----------------------------------------------------------------------------*/
@@ -218,9 +286,62 @@
 }
 #endif
 
+unsigned int float64_to_uint32( float64 a STATUS_PARAM)
+{
+    int64_t v;
+    unsigned int res;
+
+    v = llrint(a);
+    if (v < 0) {
+        res = 0;
+    } else if (v > 0xffffffff) {
+        res = 0xffffffff;
+    } else {
+        res = v;
+    }
+    return res;
+}
+unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM)
+{
+    int64_t v;
+    unsigned int res;
+
+    v = (int64_t)a;
+    if (v < 0) {
+        res = 0;
+    } else if (v > 0xffffffff) {
+        res = 0xffffffff;
+    } else {
+        res = v;
+    }
+    return res;
+}
+uint64_t float64_to_uint64 (float64 a STATUS_PARAM)
+{
+    int64_t v;
+
+    v = llrint(a + (float64)INT64_MIN);
+
+    return v - INT64_MIN;
+}
+uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM)
+{
+    int64_t v;
+
+    v = (int64_t)(a + (float64)INT64_MIN);
+
+    return v - INT64_MIN;
+}
+
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE double-precision operations.
 *----------------------------------------------------------------------------*/
+#if defined(__sun__) && defined(HOST_SOLARIS) && HOST_SOLARIS < 10
+static inline float64 trunc(float64 x)
+{
+    return x < 0 ? -floor(-x) : floor(x);
+}
+#endif
 float64 float64_trunc_to_int( float64 a STATUS_PARAM )
 {
     return trunc(a);

Modified: trunk/src/host/qemu-neo1973/fpu/softfloat-native.h
===================================================================
--- trunk/src/host/qemu-neo1973/fpu/softfloat-native.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/fpu/softfloat-native.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -15,7 +15,7 @@
  *   Solaris 10 with GCC4 does not need these macros as they
  *   are defined in <iso/math_c99.h> with a compiler directive
  */
-#if defined(HOST_SOLARIS) && (( HOST_SOLARIS <= 9 ) || ( ( HOST_SOLARIS >= 10 ) && ( __GNUC__ <= 4) ))
+#if defined(HOST_SOLARIS) && (( HOST_SOLARIS <= 9 ) || ((HOST_SOLARIS >= 10) && (__GNUC__ <= 4)))
 /*
  * C99 7.12.3 classification macros
  * and
@@ -33,6 +33,29 @@
 #define isunordered(x,y)        unordered(x, y)
 #endif
 
+#if defined(__sun__) && !defined(NEED_LIBSUNMATH)
+
+#ifndef isnan
+# define isnan(x) \
+    (sizeof (x) == sizeof (long double) ? isnan_ld (x) \
+     : sizeof (x) == sizeof (double) ? isnan_d (x) \
+     : isnan_f (x))
+static inline int isnan_f  (float       x) { return x != x; }
+static inline int isnan_d  (double      x) { return x != x; }
+static inline int isnan_ld (long double x) { return x != x; }
+#endif
+
+#ifndef isinf
+# define isinf(x) \
+    (sizeof (x) == sizeof (long double) ? isinf_ld (x) \
+     : sizeof (x) == sizeof (double) ? isinf_d (x) \
+     : isinf_f (x))
+static inline int isinf_f  (float       x) { return isnan (x - x); }
+static inline int isinf_d  (double      x) { return isnan (x - x); }
+static inline int isinf_ld (long double x) { return isnan (x - x); }
+#endif
+#endif
+
 typedef float float32;
 typedef double float64;
 #ifdef FLOATX80
@@ -99,7 +122,9 @@
 | Software IEC/IEEE integer-to-floating-point conversion routines.
 *----------------------------------------------------------------------------*/
 float32 int32_to_float32( int STATUS_PARAM);
+float32 uint32_to_float32( unsigned int STATUS_PARAM);
 float64 int32_to_float64( int STATUS_PARAM);
+float64 uint32_to_float64( unsigned int STATUS_PARAM);
 #ifdef FLOATX80
 floatx80 int32_to_floatx80( int STATUS_PARAM);
 #endif
@@ -107,7 +132,9 @@
 float128 int32_to_float128( int STATUS_PARAM);
 #endif
 float32 int64_to_float32( int64_t STATUS_PARAM);
+float32 uint64_to_float32( uint64_t STATUS_PARAM);
 float64 int64_to_float64( int64_t STATUS_PARAM);
+float64 uint64_to_float64( uint64_t v STATUS_PARAM);
 #ifdef FLOATX80
 floatx80 int64_to_floatx80( int64_t STATUS_PARAM);
 #endif
@@ -120,6 +147,8 @@
 *----------------------------------------------------------------------------*/
 int float32_to_int32( float32  STATUS_PARAM);
 int float32_to_int32_round_to_zero( float32  STATUS_PARAM);
+unsigned int float32_to_uint32( float32 a STATUS_PARAM);
+unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM);
 int64_t float32_to_int64( float32  STATUS_PARAM);
 int64_t float32_to_int64_round_to_zero( float32  STATUS_PARAM);
 float64 float32_to_float64( float32  STATUS_PARAM);
@@ -200,8 +229,12 @@
 *----------------------------------------------------------------------------*/
 int float64_to_int32( float64 STATUS_PARAM );
 int float64_to_int32_round_to_zero( float64 STATUS_PARAM );
+unsigned int float64_to_uint32( float64 STATUS_PARAM );
+unsigned int float64_to_uint32_round_to_zero( float64 STATUS_PARAM );
 int64_t float64_to_int64( float64 STATUS_PARAM );
 int64_t float64_to_int64_round_to_zero( float64 STATUS_PARAM );
+uint64_t float64_to_uint64( float64 STATUS_PARAM );
+uint64_t float64_to_uint64_round_to_zero( float64 STATUS_PARAM );
 float32 float64_to_float32( float64 STATUS_PARAM );
 #ifdef FLOATX80
 floatx80 float64_to_floatx80( float64 STATUS_PARAM );

Modified: trunk/src/host/qemu-neo1973/fpu/softfloat.c
===================================================================
--- trunk/src/host/qemu-neo1973/fpu/softfloat.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/fpu/softfloat.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1164,6 +1164,27 @@
 
 }
 
+float32 uint64_to_float32( uint64 a STATUS_PARAM )
+{
+    int8 shiftCount;
+
+    if ( a == 0 ) return 0;
+    shiftCount = countLeadingZeros64( a ) - 40;
+    if ( 0 <= shiftCount ) {
+        return packFloat32( 1 > 0, 0x95 - shiftCount, a<<shiftCount );
+    }
+    else {
+        shiftCount += 7;
+        if ( shiftCount < 0 ) {
+            shift64RightJamming( a, - shiftCount, &a );
+        }
+        else {
+            a <<= shiftCount;
+        }
+        return roundAndPackFloat32( 1 > 0, 0x9C - shiftCount, a STATUS_VAR );
+    }
+}
+
 /*----------------------------------------------------------------------------
 | Returns the result of converting the 64-bit two's complement integer `a'
 | to the double-precision floating-point format.  The conversion is performed
@@ -1183,6 +1204,13 @@
 
 }
 
+float64 uint64_to_float64( uint64 a STATUS_PARAM )
+{
+    if ( a == 0 ) return 0;
+    return normalizeRoundAndPackFloat64( 0, 0x43C, a STATUS_VAR );
+
+}
+
 #ifdef FLOATX80
 
 /*----------------------------------------------------------------------------
@@ -5282,6 +5310,26 @@
     return res;
 }
 
+uint64_t float64_to_uint64 (float64 a STATUS_PARAM)
+{
+    int64_t v;
+
+    v = int64_to_float64(INT64_MIN STATUS_VAR);
+    v = float64_to_int64((a + v) STATUS_VAR);
+
+    return v - INT64_MIN;
+}
+
+uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM)
+{
+    int64_t v;
+
+    v = int64_to_float64(INT64_MIN STATUS_VAR);
+    v = float64_to_int64_round_to_zero((a + v) STATUS_VAR);
+
+    return v - INT64_MIN;
+}
+
 #define COMPARE(s, nan_exp)                                                  \
 INLINE int float ## s ## _compare_internal( float ## s a, float ## s b,      \
                                       int is_quiet STATUS_PARAM )            \

Modified: trunk/src/host/qemu-neo1973/fpu/softfloat.h
===================================================================
--- trunk/src/host/qemu-neo1973/fpu/softfloat.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/fpu/softfloat.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -32,6 +32,10 @@
 #ifndef SOFTFLOAT_H
 #define SOFTFLOAT_H
 
+#if defined(HOST_SOLARIS) && defined(NEEDS_LIBSUNMATH)
+#include <sunmath.h>
+#endif
+
 #include <inttypes.h>
 #include "config.h"
 
@@ -193,7 +197,9 @@
 float128 int32_to_float128( int STATUS_PARAM );
 #endif
 float32 int64_to_float32( int64_t STATUS_PARAM );
+float32 uint64_to_float32( uint64_t STATUS_PARAM );
 float64 int64_to_float64( int64_t STATUS_PARAM );
+float64 uint64_to_float64( uint64_t STATUS_PARAM );
 #ifdef FLOATX80
 floatx80 int64_to_floatx80( int64_t STATUS_PARAM );
 #endif
@@ -258,6 +264,8 @@
 unsigned int float64_to_uint32_round_to_zero( float64 STATUS_PARAM );
 int64_t float64_to_int64( float64 STATUS_PARAM );
 int64_t float64_to_int64_round_to_zero( float64 STATUS_PARAM );
+uint64_t float64_to_uint64 (float64 a STATUS_PARAM);
+uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM);
 float32 float64_to_float32( float64 STATUS_PARAM );
 #ifdef FLOATX80
 floatx80 float64_to_floatx80( float64 STATUS_PARAM );

Modified: trunk/src/host/qemu-neo1973/gdbstub.c
===================================================================
--- trunk/src/host/qemu-neo1973/gdbstub.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/gdbstub.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -52,26 +52,30 @@
     RS_GETLINE,
     RS_CHKSUM1,
     RS_CHKSUM2,
+    RS_SYSCALL,
 };
-/* XXX: This is not thread safe.  Do we care?  */
-static int gdbserver_fd = -1;
-
 typedef struct GDBState {
     CPUState *env; /* current CPU */
     enum RSState state; /* parsing state */
-    int fd;
     char line_buf[4096];
     int line_buf_index;
     int line_csum;
+    char last_packet[4100];
+    int last_packet_len;
 #ifdef CONFIG_USER_ONLY
+    int fd;
     int running_state;
+#else
+    CharDriverState *chr;
 #endif
 } GDBState;
 
 #ifdef CONFIG_USER_ONLY
+/* XXX: This is not thread safe.  Do we care?  */
+static int gdbserver_fd = -1;
+
 /* XXX: remove this hack.  */
 static GDBState gdbserver_state;
-#endif
 
 static int get_char(GDBState *s)
 {
@@ -91,9 +95,32 @@
     }
     return ch;
 }
+#endif
 
+/* GDB stub state for use by semihosting syscalls.  */
+static GDBState *gdb_syscall_state;
+static gdb_syscall_complete_cb gdb_current_syscall_cb;
+
+enum {
+    GDB_SYS_UNKNOWN,
+    GDB_SYS_ENABLED,
+    GDB_SYS_DISABLED,
+} gdb_syscall_mode;
+
+/* If gdb is connected when the first semihosting syscall occurs then use
+   remote gdb syscalls.  Otherwise use native file IO.  */
+int use_gdb_syscalls(void)
+{
+    if (gdb_syscall_mode == GDB_SYS_UNKNOWN) {
+        gdb_syscall_mode = (gdb_syscall_state ? GDB_SYS_ENABLED
+                                              : GDB_SYS_DISABLED);
+    }
+    return gdb_syscall_mode == GDB_SYS_ENABLED;
+}
+
 static void put_buffer(GDBState *s, const uint8_t *buf, int len)
 {
+#ifdef CONFIG_USER_ONLY
     int ret;
 
     while (len > 0) {
@@ -106,6 +133,9 @@
             len -= ret;
         }
     }
+#else
+    qemu_chr_write(s->chr, buf, len);
+#endif
 }
 
 static inline int fromhex(int v)
@@ -154,33 +184,39 @@
 /* return -1 if error, 0 if OK */
 static int put_packet(GDBState *s, char *buf)
 {
-    char buf1[3];
-    int len, csum, ch, i;
+    int len, csum, i;
+    char *p;
 
 #ifdef DEBUG_GDB
     printf("reply='%s'\n", buf);
 #endif
 
     for(;;) {
-        buf1[0] = '$';
-        put_buffer(s, buf1, 1);
+        p = s->last_packet;
+        *(p++) = '$';
         len = strlen(buf);
-        put_buffer(s, buf, len);
+        memcpy(p, buf, len);
+        p += len;
         csum = 0;
         for(i = 0; i < len; i++) {
             csum += buf[i];
         }
-        buf1[0] = '#';
-        buf1[1] = tohex((csum >> 4) & 0xf);
-        buf1[2] = tohex((csum) & 0xf);
+        *(p++) = '#';
+        *(p++) = tohex((csum >> 4) & 0xf);
+        *(p++) = tohex((csum) & 0xf);
 
-        put_buffer(s, buf1, 3);
+        s->last_packet_len = p - s->last_packet;
+        put_buffer(s, s->last_packet, s->last_packet_len);
 
-        ch = get_char(s);
-        if (ch < 0)
+#ifdef CONFIG_USER_ONLY
+        i = get_char(s);
+        if (i < 0)
             return -1;
-        if (ch == '+')
+        if (i == '+')
             break;
+#else
+        break;
+#endif
     }
     return 0;
 }
@@ -271,7 +307,7 @@
     registers[98] = tswapl(tmp);
     registers[99] = tswapl(env->lr);
     registers[100] = tswapl(env->ctr);
-    registers[101] = tswapl(do_load_xer(env));
+    registers[101] = tswapl(ppc_load_xer(env));
     registers[102] = 0;
 
     return 103 * 4;
@@ -299,7 +335,7 @@
         env->crf[i] = (registers[98] >> (32 - ((i + 1) * 4))) & 0xF;
     env->lr = tswapl(registers[99]);
     env->ctr = tswapl(registers[100]);
-    do_store_xer(env, tswapl(registers[101]));
+    ppc_store_xer(env, tswapl(registers[101]));
 }
 #elif defined (TARGET_SPARC)
 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
@@ -341,9 +377,9 @@
     for (i = 0; i < 64; i += 2) {
 	uint64_t tmp;
 
-        tmp = (uint64_t)tswap32(*((uint32_t *)&env->fpr[i])) << 32;
-        tmp |= tswap32(*((uint32_t *)&env->fpr[i + 1]));
-        registers[i/2 + 32] = tmp;
+        tmp = ((uint64_t)*(uint32_t *)&env->fpr[i]) << 32;
+        tmp |= *(uint32_t *)&env->fpr[i + 1];
+        registers[i / 2 + 32] = tswap64(tmp);
     }
     registers[64] = tswapl(env->pc);
     registers[65] = tswapl(env->npc);
@@ -383,8 +419,11 @@
     env->fsr = tswapl(registers[70]);
 #else
     for (i = 0; i < 64; i += 2) {
-	*((uint32_t *)&env->fpr[i]) = tswap32(registers[i/2 + 32] >> 32);
-	*((uint32_t *)&env->fpr[i + 1]) = tswap32(registers[i/2 + 32] & 0xffffffff);
+        uint64_t tmp;
+
+        tmp = tswap64(registers[i / 2 + 32]);
+	*((uint32_t *)&env->fpr[i]) = tmp >> 32;
+	*((uint32_t *)&env->fpr[i + 1]) = tmp & 0xffffffff;
     }
     env->pc = tswapl(registers[64]);
     env->npc = tswapl(registers[65]);
@@ -532,20 +571,21 @@
     *(uint32_t *)ptr = tswapl(env->PC);
     ptr += 4;
 
-#ifdef MIPS_USES_FPU
-    for (i = 0; i < 32; i++)
+    if (env->CP0_Config1 & (1 << CP0C1_FP))
       {
-        *(uint32_t *)ptr = tswapl(FPR_W (env, i));
+        for (i = 0; i < 32; i++)
+          {
+            *(uint32_t *)ptr = tswapl(env->fpr[i].fs[FP_ENDIAN_IDX]);
+            ptr += 4;
+          }
+
+        *(uint32_t *)ptr = tswapl(env->fcr31);
         ptr += 4;
+
+        *(uint32_t *)ptr = tswapl(env->fcr0);
+        ptr += 4;
       }
 
-    *(uint32_t *)ptr = tswapl(env->fcr31);
-    ptr += 4;
-
-    *(uint32_t *)ptr = tswapl(env->fcr0);
-    ptr += 4;
-#endif
-
     /* 32 FP registers, fsr, fir, fp.  Not yet implemented.  */
     /* what's 'fp' mean here?  */
 
@@ -593,27 +633,28 @@
     env->PC = tswapl(*(uint32_t *)ptr);
     ptr += 4;
 
-#ifdef MIPS_USES_FPU
-    for (i = 0; i < 32; i++)
+    if (env->CP0_Config1 & (1 << CP0C1_FP))
       {
-	FPR_W (env, i) = tswapl(*(uint32_t *)ptr);
+        for (i = 0; i < 32; i++)
+          {
+            env->fpr[i].fs[FP_ENDIAN_IDX] = tswapl(*(uint32_t *)ptr);
+            ptr += 4;
+          }
+
+        env->fcr31 = tswapl(*(uint32_t *)ptr) & 0x0183FFFF;
         ptr += 4;
-      }
 
-    env->fcr31 = tswapl(*(uint32_t *)ptr) & 0x0183FFFF;
-    ptr += 4;
+        env->fcr0 = tswapl(*(uint32_t *)ptr);
+        ptr += 4;
 
-    env->fcr0 = tswapl(*(uint32_t *)ptr);
-    ptr += 4;
+        /* set rounding mode */
+        RESTORE_ROUNDING_MODE;
 
-    /* set rounding mode */
-    RESTORE_ROUNDING_MODE;
-
 #ifndef CONFIG_SOFTFLOAT
-    /* no floating point exception for native float */
-    SET_FP_ENABLE(env->fcr31, 0);
+        /* no floating point exception for native float */
+        SET_FP_ENABLE(env->fcr31, 0);
 #endif
-#endif
+      }
 }
 #elif defined (TARGET_SH4)
 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
@@ -741,6 +782,34 @@
         vm_start();
 #endif
 	return RS_IDLE;
+    case 'F':
+        {
+            target_ulong ret;
+            target_ulong err;
+
+            ret = strtoull(p, (char **)&p, 16);
+            if (*p == ',') {
+                p++;
+                err = strtoull(p, (char **)&p, 16);
+            } else {
+                err = 0;
+            }
+            if (*p == ',')
+                p++;
+            type = *p;
+            if (gdb_current_syscall_cb)
+                gdb_current_syscall_cb(s->env, ret, err);
+            if (type == 'C') {
+                put_packet(s, "T02");
+            } else {
+#ifdef CONFIG_USER_ONLY
+                s->running_state = 1;
+#else
+                vm_start();
+#endif
+            }
+        }
+        break;
     case 'g':
         reg_size = cpu_gdb_read_registers(env, mem_buf);
         memtohex(buf, mem_buf, reg_size);
@@ -790,6 +859,12 @@
             if (cpu_breakpoint_insert(env, addr) < 0)
                 goto breakpoint_error;
             put_packet(s, "OK");
+#ifndef CONFIG_USER_ONLY
+        } else if (type == 2) {
+            if (cpu_watchpoint_insert(env, addr) < 0)
+                goto breakpoint_error;
+            put_packet(s, "OK");
+#endif
         } else {
         breakpoint_error:
             put_packet(s, "E22");
@@ -806,11 +881,16 @@
         if (type == 0 || type == 1) {
             cpu_breakpoint_remove(env, addr);
             put_packet(s, "OK");
+#ifndef CONFIG_USER_ONLY
+        } else if (type == 2) {
+            cpu_watchpoint_remove(env, addr);
+            put_packet(s, "OK");
+#endif
         } else {
             goto breakpoint_error;
         }
         break;
-#ifdef CONFIG_USER_ONLY
+#ifdef CONFIG_LINUX_USER
     case 'q':
         if (strncmp(p, "Offsets", 7) == 0) {
             TaskState *ts = env->opaque;
@@ -841,10 +921,21 @@
     char buf[256];
     int ret;
 
+    if (s->state == RS_SYSCALL)
+        return;
+
     /* disable single step if it was enable */
     cpu_single_step(s->env, 0);
 
     if (reason == EXCP_DEBUG) {
+        if (s->env->watchpoint_hit) {
+            snprintf(buf, sizeof(buf), "T%02xwatch:" TARGET_FMT_lx ";",
+                     SIGTRAP,
+                     s->env->watchpoint[s->env->watchpoint_hit - 1].vaddr);
+            put_packet(s, buf);
+            s->env->watchpoint_hit = 0;
+            return;
+        }
 	tb_flush(s->env);
         ret = SIGTRAP;
     } else if (reason == EXCP_INTERRUPT) {
@@ -857,6 +948,60 @@
 }
 #endif
 
+/* Send a gdb syscall request.
+   This accepts limited printf-style format specifiers, specifically:
+    %x - target_ulong argument printed in hex.
+    %s - string pointer (target_ulong) and length (int) pair.  */
+void gdb_do_syscall(gdb_syscall_complete_cb cb, char *fmt, ...)
+{
+    va_list va;
+    char buf[256];
+    char *p;
+    target_ulong addr;
+    GDBState *s;
+
+    s = gdb_syscall_state;
+    if (!s)
+        return;
+    gdb_current_syscall_cb = cb;
+    s->state = RS_SYSCALL;
+#ifndef CONFIG_USER_ONLY
+    vm_stop(EXCP_DEBUG);
+#endif
+    s->state = RS_IDLE;
+    va_start(va, fmt);
+    p = buf;
+    *(p++) = 'F';
+    while (*fmt) {
+        if (*fmt == '%') {
+            fmt++;
+            switch (*fmt++) {
+            case 'x':
+                addr = va_arg(va, target_ulong);
+                p += sprintf(p, TARGET_FMT_lx, addr);
+                break;
+            case 's':
+                addr = va_arg(va, target_ulong);
+                p += sprintf(p, TARGET_FMT_lx "/%x", addr, va_arg(va, int));
+                break;
+            default:
+                fprintf(stderr, "gdbstub: Bad syscall format string '%s'\n",
+                        fmt - 1);
+                break;
+            }
+        } else {
+            *(p++) = *(fmt++);
+        }
+    }
+    va_end(va);
+    put_packet(s, buf);
+#ifdef CONFIG_USER_ONLY
+    gdb_handlesig(s->env, 0);
+#else
+    cpu_interrupt(s->env, CPU_INTERRUPT_EXIT);
+#endif
+}
+
 static void gdb_read_byte(GDBState *s, int ch)
 {
     CPUState *env = s->env;
@@ -864,6 +1009,26 @@
     char reply[1];
 
 #ifndef CONFIG_USER_ONLY
+    if (s->last_packet_len) {
+        /* Waiting for a response to the last packet.  If we see the start
+           of a new command then abandon the previous response.  */
+        if (ch == '-') {
+#ifdef DEBUG_GDB
+            printf("Got NACK, retransmitting\n");
+#endif
+            put_buffer(s, s->last_packet, s->last_packet_len);
+        }
+#ifdef DEBUG_GDB
+        else if (ch == '+')
+            printf("Got ACK\n");
+        else
+            printf("Got '%c' when expecting ACK/NACK\n", ch);
+#endif
+        if (ch == '+' || ch == '$')
+            s->last_packet_len = 0;
+        if (ch != '$')
+            return;
+    }
     if (vm_running) {
         /* when the CPU is running, we cannot do anything except stop
            it when receiving a char */
@@ -908,6 +1073,8 @@
                 s->state = gdb_handle_packet(s, env, s->line_buf);
             }
             break;
+        default:
+            abort();
         }
     }
 }
@@ -972,30 +1139,7 @@
   put_packet(s, buf);
 }
 
-#else
-static void gdb_read(void *opaque)
-{
-    GDBState *s = opaque;
-    int i, size;
-    uint8_t buf[4096];
 
-    size = recv(s->fd, buf, sizeof(buf), 0);
-    if (size < 0)
-        return;
-    if (size == 0) {
-        /* end of connection */
-        qemu_del_vm_stop_handler(gdb_vm_stopped, s);
-        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
-        qemu_free(s);
-        vm_start();
-    } else {
-        for(i = 0; i < size; i++)
-            gdb_read_byte(s, buf[i]);
-    }
-}
-
-#endif
-
 static void gdb_accept(void *opaque)
 {
     GDBState *s;
@@ -1018,32 +1162,14 @@
     val = 1;
     setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
     
-#ifdef CONFIG_USER_ONLY
     s = &gdbserver_state;
     memset (s, 0, sizeof (GDBState));
-#else
-    s = qemu_mallocz(sizeof(GDBState));
-    if (!s) {
-        close(fd);
-        return;
-    }
-#endif
     s->env = first_cpu; /* XXX: allow to change CPU */
     s->fd = fd;
 
-#ifdef CONFIG_USER_ONLY
+    gdb_syscall_state = s;
+
     fcntl(fd, F_SETFL, O_NONBLOCK);
-#else
-    socket_set_nonblock(fd);
-
-    /* stop the VM */
-    vm_stop(EXCP_INTERRUPT);
-
-    /* start handling I/O */
-    qemu_set_fd_handler(s->fd, gdb_read, NULL, s);
-    /* when the VM is stopped, the following callback is called */
-    qemu_add_vm_stop_handler(gdb_vm_stopped, s);
-#endif
 }
 
 static int gdbserver_open(int port)
@@ -1074,9 +1200,6 @@
         perror("listen");
         return -1;
     }
-#ifndef CONFIG_USER_ONLY
-    socket_set_nonblock(fd);
-#endif
     return fd;
 }
 
@@ -1086,10 +1209,69 @@
     if (gdbserver_fd < 0)
         return -1;
     /* accept connections */
-#ifdef CONFIG_USER_ONLY
     gdb_accept (NULL);
+    return 0;
+}
 #else
-    qemu_set_fd_handler(gdbserver_fd, gdb_accept, NULL, NULL);
-#endif
+static int gdb_chr_can_recieve(void *opaque)
+{
+  return 1;
+}
+
+static void gdb_chr_recieve(void *opaque, const uint8_t *buf, int size)
+{
+    GDBState *s = opaque;
+    int i;
+
+    for (i = 0; i < size; i++) {
+        gdb_read_byte(s, buf[i]);
+    }
+}
+
+static void gdb_chr_event(void *opaque, int event)
+{
+    switch (event) {
+    case CHR_EVENT_RESET:
+        vm_stop(EXCP_INTERRUPT);
+        gdb_syscall_state = opaque;
+        break;
+    default:
+        break;
+    }
+}
+
+int gdbserver_start(const char *port)
+{
+    GDBState *s;
+    char gdbstub_port_name[128];
+    int port_num;
+    char *p;
+    CharDriverState *chr;
+
+    if (!port || !*port)
+      return -1;
+
+    port_num = strtol(port, &p, 10);
+    if (*p == 0) {
+        /* A numeric value is interpreted as a port number.  */
+        snprintf(gdbstub_port_name, sizeof(gdbstub_port_name),
+                 "tcp::%d,nowait,nodelay,server", port_num);
+        port = gdbstub_port_name;
+    }
+
+    chr = qemu_chr_open(port);
+    if (!chr)
+        return -1;
+
+    s = qemu_mallocz(sizeof(GDBState));
+    if (!s) {
+        return -1;
+    }
+    s->env = first_cpu; /* XXX: allow to change CPU */
+    s->chr = chr;
+    qemu_chr_add_handlers(chr, gdb_chr_can_recieve, gdb_chr_recieve,
+                          gdb_chr_event, s);
+    qemu_add_vm_stop_handler(gdb_vm_stopped, s);
     return 0;
 }
+#endif

Modified: trunk/src/host/qemu-neo1973/gdbstub.h
===================================================================
--- trunk/src/host/qemu-neo1973/gdbstub.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/gdbstub.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,12 +1,19 @@
 #ifndef GDBSTUB_H
 #define GDBSTUB_H
 
-#define DEFAULT_GDBSTUB_PORT 1234
+#define DEFAULT_GDBSTUB_PORT "1234"
 
+typedef void (*gdb_syscall_complete_cb)(CPUState *env,
+                                        target_ulong ret, target_ulong err);
+
+void gdb_do_syscall(gdb_syscall_complete_cb cb, char *fmt, ...);
+int use_gdb_syscalls(void);
 #ifdef CONFIG_USER_ONLY
 int gdb_handlesig (CPUState *, int);
 void gdb_exit(CPUState *, int);
+int gdbserver_start(int);
+#else
+int gdbserver_start(const char *port);
 #endif
-int gdbserver_start(int);
 
 #endif

Added: trunk/src/host/qemu-neo1973/hostregs_helper.h
===================================================================
--- trunk/src/host/qemu-neo1973/hostregs_helper.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hostregs_helper.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,98 @@
+/*
+ *  Save/restore host registrs.
+ *
+ *  Copyright (c) 2007 CodeSourcery
+ *
+ * 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
+ */
+
+/* The GCC global register vairable extension is used to reserve some
+   host registers for use by dyngen.  However only the core parts of the
+   translation engine are compiled with these settings.  We must manually
+   save/restore these registers when called from regular code.
+   It is not sufficient to save/restore T0 et. al. as these may be declared
+   with a datatype smaller than the actual register.  */
+
+#if defined(DECLARE_HOST_REGS)
+
+#define DO_REG(REG)					\
+    register host_reg_t reg_AREG##REG asm(AREG##REG);	\
+    volatile host_reg_t saved_AREG##REG;
+
+#elif defined(SAVE_HOST_REGS)
+
+#define DO_REG(REG)					\
+    __asm__ __volatile__ ("" : "=r" (reg_AREG##REG));	\
+    saved_AREG##REG = reg_AREG##REG;
+
+#else
+
+#define DO_REG(REG)                                     \
+    reg_AREG##REG = saved_AREG##REG;		        \
+    __asm__ __volatile__ ("" : : "r" (reg_AREG##REG));
+
+#endif
+
+#ifdef AREG0
+DO_REG(0)
+#endif
+
+#ifdef AREG1
+DO_REG(1)
+#endif
+
+#ifdef AREG2
+DO_REG(2)
+#endif
+
+#ifdef AREG3
+DO_REG(3)
+#endif
+
+#ifdef AREG4
+DO_REG(4)
+#endif
+
+#ifdef AREG5
+DO_REG(5)
+#endif
+
+#ifdef AREG6
+DO_REG(6)
+#endif
+
+#ifdef AREG7
+DO_REG(7)
+#endif
+
+#ifdef AREG8
+DO_REG(8)
+#endif
+
+#ifdef AREG9
+DO_REG(9)
+#endif
+
+#ifdef AREG10
+DO_REG(10)
+#endif
+
+#ifdef AREG11
+DO_REG(11)
+#endif
+
+#undef SAVE_HOST_REGS
+#undef DECLARE_HOST_REGS
+#undef DO_REG

Modified: trunk/src/host/qemu-neo1973/hw/acpi.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/acpi.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/acpi.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -24,6 +24,7 @@
 #define PM_FREQ 3579545
 
 #define ACPI_DBG_IO_ADDR  0xb044
+#define SMB_IO_BASE       0xb100
 
 typedef struct PIIX4PMState {
     PCIDevice dev;
@@ -34,6 +35,15 @@
     uint8_t apms;
     QEMUTimer *tmr_timer;
     int64_t tmr_overflow_time;
+    i2c_bus *smbus;
+    uint8_t smb_stat;
+    uint8_t smb_ctl;
+    uint8_t smb_cmd;
+    uint8_t smb_addr;
+    uint8_t smb_data0;
+    uint8_t smb_data1;
+    uint8_t smb_data[32];
+    uint8_t smb_index;
 } PIIX4PMState;
 
 #define RTC_EN (1 << 10)
@@ -45,6 +55,14 @@
 
 #define SUS_EN (1 << 13)
 
+#define SMBHSTSTS 0x00
+#define SMBHSTCNT 0x02
+#define SMBHSTCMD 0x03
+#define SMBHSTADD 0x04
+#define SMBHSTDAT0 0x05
+#define SMBHSTDAT1 0x06
+#define SMBBLKDAT 0x07
+
 static uint32_t get_pmtmr(PIIX4PMState *s)
 {
     uint32_t d;
@@ -71,7 +89,7 @@
     pmsts = get_pmsts(s);
     sci_level = (((pmsts & s->pmen) & 
                   (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0);
-    pci_set_irq(&s->dev, 0, sci_level);
+    qemu_set_irq(s->dev.irq[0], sci_level);
     /* schedule a timer interruption if needed */
     if ((s->pmen & TMROF_EN) && !(pmsts & TMROF_EN)) {
         expire_time = muldiv64(s->tmr_overflow_time, ticks_per_sec, PM_FREQ);
@@ -231,6 +249,141 @@
 #endif
 }
 
+static void smb_transaction(PIIX4PMState *s)
+{
+    uint8_t prot = (s->smb_ctl >> 2) & 0x07;
+    uint8_t read = s->smb_addr & 0x01;
+    uint8_t cmd = s->smb_cmd;
+    uint8_t addr = s->smb_addr >> 1;
+    i2c_bus *bus = s->smbus;
+
+#ifdef DEBUG
+    printf("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
+#endif
+    switch(prot) {
+    case 0x0:
+        smbus_quick_command(bus, addr, read);
+        break;
+    case 0x1:
+        if (read) {
+            s->smb_data0 = smbus_receive_byte(bus, addr);
+        } else {
+            smbus_send_byte(bus, addr, cmd);
+        }
+        break;
+    case 0x2:
+        if (read) {
+            s->smb_data0 = smbus_read_byte(bus, addr, cmd);
+        } else {
+            smbus_write_byte(bus, addr, cmd, s->smb_data0);
+        }
+        break;
+    case 0x3:
+        if (read) {
+            uint16_t val;
+            smbus_read_word(bus, addr, cmd);
+            s->smb_data0 = val;
+            s->smb_data1 = val >> 8;
+        } else {
+            smbus_write_word(bus, addr, cmd, (s->smb_data1 << 8) | s->smb_data0);
+        }
+        break;
+    case 0x5:
+        if (read) {
+            s->smb_data0 = smbus_read_block(bus, addr, cmd, s->smb_data);
+        } else {
+            smbus_write_block(bus, addr, cmd, s->smb_data, s->smb_data0);
+        }
+        break;
+    default:
+        goto error;
+    }
+    return;
+
+  error:
+    s->smb_stat |= 0x04;
+}
+
+static void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    PIIX4PMState *s = opaque;
+    addr &= 0x3f;
+#ifdef DEBUG
+    printf("SMB writeb port=0x%04x val=0x%02x\n", addr, val);
+#endif
+    switch(addr) {
+    case SMBHSTSTS:
+        s->smb_stat = 0;
+        s->smb_index = 0;
+        break;
+    case SMBHSTCNT:
+        s->smb_ctl = val;
+        if (val & 0x40)
+            smb_transaction(s);
+        break;
+    case SMBHSTCMD:
+        s->smb_cmd = val;
+        break;
+    case SMBHSTADD:
+        s->smb_addr = val;
+        break;
+    case SMBHSTDAT0:
+        s->smb_data0 = val;
+        break;
+    case SMBHSTDAT1:
+        s->smb_data1 = val;
+        break;
+    case SMBBLKDAT:
+        s->smb_data[s->smb_index++] = val;
+        if (s->smb_index > 31)
+            s->smb_index = 0;
+        break;
+    default:
+        break;
+    }
+}
+
+static uint32_t smb_ioport_readb(void *opaque, uint32_t addr)
+{
+    PIIX4PMState *s = opaque;
+    uint32_t val;
+
+    addr &= 0x3f;
+    switch(addr) {
+    case SMBHSTSTS:
+        val = s->smb_stat;
+        break;
+    case SMBHSTCNT:
+        s->smb_index = 0;
+        val = s->smb_ctl & 0x1f;
+        break;
+    case SMBHSTCMD:
+        val = s->smb_cmd;
+        break;
+    case SMBHSTADD:
+        val = s->smb_addr;
+        break;
+    case SMBHSTDAT0:
+        val = s->smb_data0;
+        break;
+    case SMBHSTDAT1:
+        val = s->smb_data1;
+        break;
+    case SMBBLKDAT:
+        val = s->smb_data[s->smb_index++];
+        if (s->smb_index > 31)
+            s->smb_index = 0;
+        break;
+    default:
+        val = 0;
+        break;
+    }
+#ifdef DEBUG
+    printf("SMB readb port=0x%04x val=0x%02x\n", addr, val);
+#endif
+    return val;
+}
+
 static void pm_io_space_update(PIIX4PMState *s)
 {
     uint32_t pm_io_base;
@@ -298,10 +451,11 @@
     return 0;
 }
 
-void piix4_pm_init(PCIBus *bus, int devfn)
+i2c_bus *piix4_pm_init(PCIBus *bus, int devfn)
 {
     PIIX4PMState *s;
     uint8_t *pci_conf;
+    uint32_t smb_io_base;
 
     s = (PIIX4PMState *)pci_register_device(bus,
                                          "PM", sizeof(PIIX4PMState),
@@ -332,7 +486,17 @@
     pci_conf[0x67] = (serial_hds[0] != NULL ? 0x08 : 0) |
 	(serial_hds[1] != NULL ? 0x90 : 0);
 
+    smb_io_base = SMB_IO_BASE;
+    pci_conf[0x90] = smb_io_base | 1;
+    pci_conf[0x91] = smb_io_base >> 8;
+    pci_conf[0xd2] = 0x09;
+    register_ioport_write(smb_io_base, 64, 1, smb_ioport_writeb, s);
+    register_ioport_read(smb_io_base, 64, 1, smb_ioport_readb, s);
+
     s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
 
     register_savevm("piix4_pm", 0, 1, pm_save, pm_load, s);
+
+    s->smbus = i2c_init_bus();
+    return s->smbus;
 }

Modified: trunk/src/host/qemu-neo1973/hw/adlib.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/adlib.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/adlib.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -267,7 +267,7 @@
     AUD_remove_card (&s->card);
 }
 
-int Adlib_init (AudioState *audio)
+int Adlib_init (AudioState *audio, qemu_irq *pic)
 {
     AdlibState *s = &glob_adlib;
     audsettings_t as;

Modified: trunk/src/host/qemu-neo1973/hw/ads7846.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ads7846.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/ads7846.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -4,14 +4,13 @@
  * Copyright (c) 2006 Openedhand Ltd.
  * Written by Andrzej Zaborowski <balrog at zabor.org>
  *
- * This code is licensed under the GPLv2.
+ * This code is licensed under the GNU GPL v2.
  */
 
 #include <vl.h>
 
 struct ads7846_state_s {
-    void (*interrupt)(void *opaque, int level);
-    void *opaque;
+    qemu_irq interrupt;
 
     int input[8];
     int pressure;
@@ -48,7 +47,7 @@
 static void ads7846_int_update(struct ads7846_state_s *s)
 {
     if (s->interrupt)
-        s->interrupt(s->opaque, s->pressure == 0);
+        qemu_set_irq(s->interrupt, s->pressure == 0);
 }
 
 uint32_t ads7846_read(void *opaque)
@@ -101,13 +100,15 @@
         s->input[4] = ADS_Z2POS(x, y);
         s->input[5] = ADS_XPOS(x, y);
     }
-    s->pressure = !!buttons_state;
 
-    ads7846_int_update(s);
+    if (s->pressure == !buttons_state) {
+        s->pressure = !!buttons_state;
+
+         ads7846_int_update(s);
+    }
 }
 
-struct ads7846_state_s *ads7846_init(
-                void (*penirq)(void *opaque, int level), void *opaque)
+struct ads7846_state_s *ads7846_init(qemu_irq penirq)
 {
     struct ads7846_state_s *s;
     s = (struct ads7846_state_s *)
@@ -115,7 +116,6 @@
     memset(s, 0, sizeof(struct ads7846_state_s));
 
     s->interrupt = penirq;
-    s->opaque = opaque;
 
     s->input[0] = ADS_TEMP0;	/* TEMP0 */
     s->input[2] = ADS_VBAT;	/* VBAT */

Added: trunk/src/host/qemu-neo1973/hw/alpha_palcode.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/alpha_palcode.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/alpha_palcode.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,1099 @@
+/*
+ *  Alpha emulation - PALcode emulation for qemu.
+ * 
+ *  Copyright (c) 2007 Jocelyn Mayer
+ *
+ * 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
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "qemu.h"
+#include "cpu.h"
+#include "exec-all.h"
+
+#if !defined (CONFIG_USER_ONLY)
+/* Shared handlers */
+static void pal_reset (CPUState *env);
+/* Console handlers */
+static void pal_console_call (CPUState *env, uint32_t palcode);
+/* OpenVMS handlers */
+static void pal_openvms_call (CPUState *env, uint32_t palcode);
+/* UNIX / Linux handlers */
+static void pal_unix_call (CPUState *env, uint32_t palcode);
+
+pal_handler_t pal_handlers[] = {
+    /* Console handler */
+    {
+        .reset = &pal_reset,
+        .call_pal = &pal_console_call,
+    },
+    /* OpenVMS handler */
+    {
+        .reset = &pal_reset,
+        .call_pal = &pal_openvms_call,
+    },
+    /* UNIX / Linux handler */
+    {
+        .reset = &pal_reset,
+        .call_pal = &pal_unix_call,
+    },
+};
+
+#if 0
+/* One must explicitely check that the TB is valid and the FOE bit is reset */
+static void update_itb ()
+{
+    /* This writes into a temp register, not the actual one */
+    mtpr(TB_TAG);
+    mtpr(TB_CTL);
+    /* This commits the TB update */
+    mtpr(ITB_PTE); 
+}
+
+static void update_dtb ();
+{
+    mtpr(TB_CTL);
+    /* This write into a temp register, not the actual one */
+    mtpr(TB_TAG);
+    /* This commits the TB update */
+    mtpr(DTB_PTE);
+}
+#endif
+
+static void pal_reset (CPUState *env)
+{
+}
+
+static void do_swappal (CPUState *env, uint64_t palid)
+{
+    pal_handler_t *pal_handler;
+    int status;
+
+    status = 0;
+    switch (palid) {
+    case 0 ... 2:
+        pal_handler = &pal_handlers[palid];
+        env->pal_handler = pal_handler;
+        env->ipr[IPR_PAL_BASE] = -1ULL;
+        (*pal_handler->reset)(env);
+        break;
+    case 3 ... 255:
+        /* Unknown identifier */
+        env->ir[0] = 1;
+        return;
+    default:
+        /* We were given the entry point address */
+        env->pal_handler = NULL;
+        env->ipr[IPR_PAL_BASE] = palid;
+        env->pc = env->ipr[IPR_PAL_BASE];
+        cpu_loop_exit();
+    }
+}
+
+static void pal_console_call (CPUState *env, uint32_t palcode)
+{
+    uint64_t palid;
+
+    if (palcode < 0x00000080) {
+        /* Privileged palcodes */
+        if (!(env->ps >> 3)) {
+            /* TODO: generate privilege exception */
+        }
+    }
+    switch (palcode) {
+    case 0x00000000:
+        /* HALT */
+        /* REQUIRED */
+        break;
+    case 0x00000001:
+        /* CFLUSH */
+        break;
+    case 0x00000002:
+        /* DRAINA */
+        /* REQUIRED */
+        /* Implemented as no-op */
+        break;
+    case 0x00000009:
+        /* CSERVE */
+        /* REQUIRED */
+        break;
+    case 0x0000000A:
+        /* SWPPAL */
+        /* REQUIRED */
+        palid = env->ir[16];
+        do_swappal(env, palid);
+        break;
+    case 0x00000080:
+        /* BPT */
+        /* REQUIRED */
+        break;
+    case 0x00000081:
+        /* BUGCHK */
+        /* REQUIRED */
+        break;
+    case 0x00000086:
+        /* IMB */
+        /* REQUIRED */
+        /* Implemented as no-op */
+        break;
+    case 0x0000009E:
+        /* RDUNIQUE */
+        /* REQUIRED */
+        break;
+    case 0x0000009F:
+        /* WRUNIQUE */
+        /* REQUIRED */
+        break;
+    case 0x000000AA:
+        /* GENTRAP */
+        /* REQUIRED */
+        break;
+    default:
+        break;
+    }
+}
+
+static void pal_openvms_call (CPUState *env, uint32_t palcode)
+{
+    uint64_t palid, val, oldval;
+
+    if (palcode < 0x00000080) {
+        /* Privileged palcodes */
+        if (!(env->ps >> 3)) {
+            /* TODO: generate privilege exception */
+        }
+    }
+    switch (palcode) {
+    case 0x00000000:
+        /* HALT */
+        /* REQUIRED */
+        break;
+    case 0x00000001:
+        /* CFLUSH */
+        break;
+    case 0x00000002:
+        /* DRAINA */
+        /* REQUIRED */
+        /* Implemented as no-op */
+        break;
+    case 0x00000003:
+        /* LDQP */
+        break;
+    case 0x00000004:
+        /* STQP */
+        break;
+    case 0x00000005:
+        /* SWPCTX */
+        break;
+    case 0x00000006:
+        /* MFPR_ASN */
+        if (cpu_alpha_mfpr(env, IPR_ASN, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000007:
+        /* MTPR_ASTEN */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_ASTEN, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000008:
+        /* MTPR_ASTSR */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_ASTSR, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000009:
+        /* CSERVE */
+        /* REQUIRED */
+        break;
+    case 0x0000000A:
+        /* SWPPAL */
+        /* REQUIRED */
+        palid = env->ir[16];
+        do_swappal(env, palid);
+        break;
+    case 0x0000000B:
+        /* MFPR_FEN */
+        if (cpu_alpha_mfpr(env, IPR_FEN, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x0000000C:
+        /* MTPR_FEN */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_FEN, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000000D:
+        /* MTPR_IPIR */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_IPIR, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000000E:
+        /* MFPR_IPL */
+        if (cpu_alpha_mfpr(env, IPR_IPL, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x0000000F:
+        /* MTPR_IPL */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_IPL, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000010:
+        /* MFPR_MCES */
+        if (cpu_alpha_mfpr(env, IPR_MCES, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000011:
+        /* MTPR_MCES */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_MCES, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000012:
+        /* MFPR_PCBB */
+        if (cpu_alpha_mfpr(env, IPR_PCBB, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000013:
+        /* MFPR_PRBR */
+        if (cpu_alpha_mfpr(env, IPR_PRBR, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000014:
+        /* MTPR_PRBR */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_PRBR, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000015:
+        /* MFPR_PTBR */
+        if (cpu_alpha_mfpr(env, IPR_PTBR, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000016:
+        /* MFPR_SCBB */
+        if (cpu_alpha_mfpr(env, IPR_SCBB, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000017:
+        /* MTPR_SCBB */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_SCBB, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000018:
+        /* MTPR_SIRR */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_SIRR, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000019:
+        /* MFPR_SISR */
+        if (cpu_alpha_mfpr(env, IPR_SISR, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x0000001A:
+        /* MFPR_TBCHK */
+        if (cpu_alpha_mfpr(env, IPR_TBCHK, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x0000001B:
+        /* MTPR_TBIA */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_TBIA, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000001C:
+        /* MTPR_TBIAP */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_TBIAP, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000001D:
+        /* MTPR_TBIS */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_TBIS, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000001E:
+        /* MFPR_ESP */
+        if (cpu_alpha_mfpr(env, IPR_ESP, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x0000001F:
+        /* MTPR_ESP */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_ESP, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000020:
+        /* MFPR_SSP */
+        if (cpu_alpha_mfpr(env, IPR_SSP, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000021:
+        /* MTPR_SSP */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_SSP, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000022:
+        /* MFPR_USP */
+        if (cpu_alpha_mfpr(env, IPR_USP, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000023:
+        /* MTPR_USP */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_USP, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000024:
+        /* MTPR_TBISD */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_TBISD, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000025:
+        /* MTPR_TBISI */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_TBISI, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000026:
+        /* MFPR_ASTEN */
+        if (cpu_alpha_mfpr(env, IPR_ASTEN, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000027:
+        /* MFPR_ASTSR */
+        if (cpu_alpha_mfpr(env, IPR_ASTSR, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000029:
+        /* MFPR_VPTB */
+        if (cpu_alpha_mfpr(env, IPR_VPTB, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x0000002A:
+        /* MTPR_VPTB */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_VPTB, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000002B:
+        /* MTPR_PERFMON */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000002E:
+        /* MTPR_DATFX */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_DATFX, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000003E:
+        /* WTINT */
+        break;
+    case 0x0000003F:
+        /* MFPR_WHAMI */
+        if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000080:
+        /* BPT */
+        /* REQUIRED */
+        break;
+    case 0x00000081:
+        /* BUGCHK */
+        /* REQUIRED */
+        break;
+    case 0x00000082:
+        /* CHME */
+        break;
+    case 0x00000083:
+        /* CHMK */
+        break;
+    case 0x00000084:
+        /* CHMS */
+        break;
+    case 0x00000085:
+        /* CHMU */
+        break;
+    case 0x00000086:
+        /* IMB */
+        /* REQUIRED */
+        /* Implemented as no-op */
+        break;
+    case 0x00000087:
+        /* INSQHIL */
+        break;
+    case 0x00000088:
+        /* INSQTIL */
+        break;
+    case 0x00000089:
+        /* INSQHIQ */
+        break;
+    case 0x0000008A:
+        /* INSQTIQ */
+        break;
+    case 0x0000008B:
+        /* INSQUEL */
+        break;
+    case 0x0000008C:
+        /* INSQUEQ */
+        break;
+    case 0x0000008D:
+        /* INSQUEL/D */
+        break;
+    case 0x0000008E:
+        /* INSQUEQ/D */
+        break;
+    case 0x0000008F:
+        /* PROBER */
+        break;
+    case 0x00000090:
+        /* PROBEW */
+        break;
+    case 0x00000091:
+        /* RD_PS */
+        break;
+    case 0x00000092:
+        /* REI */
+        break;
+    case 0x00000093:
+        /* REMQHIL */
+        break;
+    case 0x00000094:
+        /* REMQTIL */
+        break;
+    case 0x00000095:
+        /* REMQHIQ */
+        break;
+    case 0x00000096:
+        /* REMQTIQ */
+        break;
+    case 0x00000097:
+        /* REMQUEL */
+        break;
+    case 0x00000098:
+        /* REMQUEQ */
+        break;
+    case 0x00000099:
+        /* REMQUEL/D */
+        break;
+    case 0x0000009A:
+        /* REMQUEQ/D */
+        break;
+    case 0x0000009B:
+        /* SWASTEN */
+        break;
+    case 0x0000009C:
+        /* WR_PS_SW */
+        break;
+    case 0x0000009D:
+        /* RSCC */
+        break;
+    case 0x0000009E:
+        /* READ_UNQ */
+        /* REQUIRED */
+        break;
+    case 0x0000009F:
+        /* WRITE_UNQ */
+        /* REQUIRED */
+        break;
+    case 0x000000A0:
+        /* AMOVRR */
+        break;
+    case 0x000000A1:
+        /* AMOVRM */
+        break;
+    case 0x000000A2:
+        /* INSQHILR */
+        break;
+    case 0x000000A3:
+        /* INSQTILR */
+        break;
+    case 0x000000A4:
+        /* INSQHIQR */
+        break;
+    case 0x000000A5:
+        /* INSQTIQR */
+        break;
+    case 0x000000A6:
+        /* REMQHILR */
+        break;
+    case 0x000000A7:
+        /* REMQTILR */
+        break;
+    case 0x000000A8:
+        /* REMQHIQR */
+        break;
+    case 0x000000A9:
+        /* REMQTIQR */
+        break;
+    case 0x000000AA:
+        /* GENTRAP */
+        /* REQUIRED */
+        break;
+    case 0x000000AE:
+        /* CLRFEN */
+        break;
+    default:
+        break;
+    }
+}
+
+static void pal_unix_call (CPUState *env, uint32_t palcode)
+{
+    uint64_t palid, val, oldval;
+
+    if (palcode < 0x00000080) {
+        /* Privileged palcodes */
+        if (!(env->ps >> 3)) {
+            /* TODO: generate privilege exception */
+        }
+    }
+    switch (palcode) {
+    case 0x00000000:
+        /* HALT */
+        /* REQUIRED */
+        break;
+    case 0x00000001:
+        /* CFLUSH */
+        break;
+    case 0x00000002:
+        /* DRAINA */
+        /* REQUIRED */
+        /* Implemented as no-op */
+        break;
+    case 0x00000009:
+        /* CSERVE */
+        /* REQUIRED */
+        break;
+    case 0x0000000A:
+        /* SWPPAL */
+        /* REQUIRED */
+        palid = env->ir[16];
+        do_swappal(env, palid);
+        break;
+    case 0x0000000D:
+        /* WRIPIR */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_IPIR, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000010:
+        /* RDMCES */
+        if (cpu_alpha_mfpr(env, IPR_MCES, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000011:
+        /* WRMCES */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_MCES, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000002B:
+        /* WRFEN */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000002D:
+        /* WRVPTPTR */
+        break;
+    case 0x00000030:
+        /* SWPCTX */
+        break;
+    case 0x00000031:
+        /* WRVAL */
+        break;
+    case 0x00000032:
+        /* RDVAL */
+        break;
+    case 0x00000033:
+        /* TBI */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_TBIS, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000034:
+        /* WRENT */
+        break;
+    case 0x00000035:
+        /* SWPIPL */
+        break;
+    case 0x00000036:
+        /* RDPS */
+        break;
+    case 0x00000037:
+        /* WRKGP */
+        break;
+    case 0x00000038:
+        /* WRUSP */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_USP, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000039:
+        /* WRPERFMON */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000003A:
+        /* RDUSP */
+        if (cpu_alpha_mfpr(env, IPR_USP, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x0000003C:
+        /* WHAMI */
+        if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x0000003D:
+        /* RETSYS */
+        break;
+    case 0x0000003E:
+        /* WTINT */
+        break;
+    case 0x0000003F:
+        /* RTI */
+        if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000080:
+        /* BPT */
+        /* REQUIRED */
+        break;
+    case 0x00000081:
+        /* BUGCHK */
+        /* REQUIRED */
+        break;
+    case 0x00000083:
+        /* CALLSYS */
+        break;
+    case 0x00000086:
+        /* IMB */
+        /* REQUIRED */
+        /* Implemented as no-op */
+        break;
+    case 0x00000092:
+        /* URTI */
+        break;
+    case 0x0000009E:
+        /* RDUNIQUE */
+        /* REQUIRED */
+        break;
+    case 0x0000009F:
+        /* WRUNIQUE */
+        /* REQUIRED */
+        break;
+    case 0x000000AA:
+        /* GENTRAP */
+        /* REQUIRED */
+        break;
+    case 0x000000AE:
+        /* CLRFEN */
+        break;
+    default:
+        break;
+    }
+}
+
+void call_pal (CPUState *env)
+{
+    pal_handler_t *pal_handler = env->pal_handler;
+
+    switch (env->exception_index) {
+    case EXCP_RESET:
+        (*pal_handler->reset)(env);
+        break;
+    case EXCP_MCHK:
+        (*pal_handler->machine_check)(env);
+        break;
+    case EXCP_ARITH:
+        (*pal_handler->arithmetic)(env);
+        break;
+    case EXCP_INTERRUPT:
+        (*pal_handler->interrupt)(env);
+        break;
+    case EXCP_DFAULT:
+        (*pal_handler->dfault)(env);
+        break;
+    case EXCP_DTB_MISS_PAL:
+        (*pal_handler->dtb_miss_pal)(env);
+        break;
+    case EXCP_DTB_MISS_NATIVE:
+        (*pal_handler->dtb_miss_native)(env);
+        break;
+    case EXCP_UNALIGN:
+        (*pal_handler->unalign)(env);
+        break;
+    case EXCP_ITB_MISS:
+        (*pal_handler->itb_miss)(env);
+        break;
+    case EXCP_ITB_ACV:
+        (*pal_handler->itb_acv)(env);
+        break;
+    case EXCP_OPCDEC:
+        (*pal_handler->opcdec)(env);
+        break;
+    case EXCP_FEN:
+        (*pal_handler->fen)(env);
+        break;
+    default:
+        if (env->exception_index >= EXCP_CALL_PAL &&
+            env->exception_index < EXCP_CALL_PALP) {
+            /* Unprivileged PAL call */
+            (*pal_handler->call_pal)
+                (env, (env->exception_index - EXCP_CALL_PAL) >> 6);
+        } else if (env->exception_index >= EXCP_CALL_PALP &&
+                   env->exception_index < EXCP_CALL_PALE) {
+            /* Privileged PAL call */
+            (*pal_handler->call_pal)
+                (env, ((env->exception_index - EXCP_CALL_PALP) >> 6) + 0x80);
+        } else {
+            /* Should never happen */
+        }
+        break;
+    }
+    env->ipr[IPR_EXC_ADDR] &= ~1;
+}
+
+void pal_init (CPUState *env)
+{
+    do_swappal(env, 0);
+}
+
+#if 0
+static uint64_t get_ptebase (CPUState *env, uint64_t vaddr)
+{
+    uint64_t virbnd, ptbr;
+
+    if ((env->features & FEATURE_VIRBND)) {
+        cpu_alpha_mfpr(env, IPR_VIRBND, &virbnd);
+        if (vaddr >= virbnd)
+            cpu_alpha_mfpr(env, IPR_SYSPTBR, &ptbr);
+        else
+            cpu_alpha_mfpr(env, IPR_PTBR, &ptbr);
+    } else {
+        cpu_alpha_mfpr(env, IPR_PTBR, &ptbr);
+    }
+
+    return ptbr;
+}
+
+static int get_page_bits (CPUState *env)
+{
+    /* XXX */
+    return 13;
+}
+
+static int get_pte (uint64_t *pfnp, int *zbitsp, int *protp,
+                    uint64_t ptebase, int page_bits, uint64_t level,
+                    int is_user, int rw)
+{
+    uint64_t pteaddr, pte, pfn;
+    uint8_t gh;
+    int ure, uwe, kre, kwe, foE, foR, foW, v, ret, ar;
+
+    pteaddr = (ptebase << page_bits) + (8 * level);
+    pte = ldq_raw(pteaddr);
+    /* Decode all interresting PTE fields */
+    pfn = pte >> 32;
+    uwe = (pte >> 13) & 1;
+    kwe = (pte >> 12) & 1;
+    ure = (pte >> 9) & 1;
+    kre = (pte >> 8) & 1;
+    gh = (pte >> 5) & 3;
+    foE = (pte >> 3) & 1;
+    foW = (pte >> 2) & 1;
+    foR = (pte >> 1) & 1;
+    v = pte & 1;
+    ret = 0;
+    if (!v)
+        ret = 0x1;
+    /* Check access rights */
+    ar = 0;
+    if (is_user) {
+        if (ure)
+            ar |= PAGE_READ;
+        if (uwe)
+            ar |= PAGE_WRITE;
+        if (rw == 1 && !uwe)
+            ret |= 0x2;
+        if (rw != 1 && !ure)
+            ret |= 0x2;
+    } else {
+        if (kre)
+            ar |= PAGE_READ;
+        if (kwe)
+            ar |= PAGE_WRITE;
+        if (rw == 1 && !kwe)
+            ret |= 0x2;
+        if (rw != 1 && !kre)
+            ret |= 0x2;
+    }
+    if (rw == 0 && foR)
+        ret |= 0x4;
+    if (rw == 2 && foE)
+        ret |= 0x8;
+    if (rw == 1 && foW)
+        ret |= 0xC;
+    *pfnp = pfn;
+    if (zbitsp != NULL)
+        *zbitsp = page_bits + (3 * gh);
+    if (protp != NULL)
+        *protp = ar;
+
+    return ret;
+}
+
+static int paddr_from_pte (uint64_t *paddr, int *zbitsp, int *prot,
+                           uint64_t ptebase, int page_bits,
+                           uint64_t vaddr, int is_user, int rw)
+{
+    uint64_t pfn, page_mask, lvl_mask, level1, level2, level3;
+    int lvl_bits, ret;
+
+    page_mask = (1ULL << page_bits) - 1ULL;
+    lvl_bits = page_bits - 3;
+    lvl_mask = (1ULL << lvl_bits) - 1ULL;
+    level3 = (vaddr >> page_bits) & lvl_mask;
+    level2 = (vaddr >> (page_bits + lvl_bits)) & lvl_mask;
+    level1 = (vaddr >> (page_bits + (2 * lvl_bits))) & lvl_mask;
+    /* Level 1 PTE */
+    ret = get_pte(&pfn, NULL, NULL, ptebase, page_bits, level1, 0, 0);
+    switch (ret) {
+    case 3:
+        /* Access violation */
+        return 2;
+    case 2:
+        /* translation not valid */
+        return 1;
+    default:
+        /* OK */
+        break;
+    }
+    /* Level 2 PTE */
+    ret = get_pte(&pfn, NULL, NULL, pfn, page_bits, level2, 0, 0);
+    switch (ret) {
+    case 3:
+        /* Access violation */
+        return 2;
+    case 2:
+        /* translation not valid */
+        return 1;
+    default:
+        /* OK */
+        break;
+    }
+    /* Level 3 PTE */
+    ret = get_pte(&pfn, zbitsp, prot, pfn, page_bits, level3, is_user, rw);
+    if (ret & 0x1) {
+        /* Translation not valid */
+        ret = 1;
+    } else if (ret & 2) {
+        /* Access violation */
+        ret = 2;
+    } else {
+        switch (ret & 0xC) {
+        case 0:
+            /* OK */
+            ret = 0;
+            break;
+        case 0x4:
+            /* Fault on read */
+            ret = 3;
+            break;
+        case 0x8:
+            /* Fault on execute */
+            ret = 4;
+            break;
+        case 0xC:
+            /* Fault on write */
+            ret = 5;
+            break;
+        }
+    }
+    *paddr = (pfn << page_bits) | (vaddr & page_mask);
+    
+    return 0;
+}
+
+static int virtual_to_physical (CPUState *env, uint64_t *physp,
+                                int *zbitsp, int *protp,
+                                uint64_t virtual, int is_user, int rw)
+{
+    uint64_t sva, ptebase;
+    int seg, page_bits, ret;
+
+    sva = ((int64_t)(virtual << (64 - VA_BITS))) >> (64 - VA_BITS);
+    if (sva != virtual)
+        seg = -1;
+    else
+        seg = sva >> (VA_BITS - 2);
+    virtual &= ~(0xFFFFFC0000000000ULL << (VA_BITS - 43));
+    ptebase = get_ptebase(env, virtual);
+    page_bits = get_page_bits(env);
+    ret = 0;
+    switch (seg) {
+    case 0:
+        /* seg1: 3 levels of PTE */
+        ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
+                             virtual, is_user, rw);
+        break;
+    case 1:
+        /* seg1: 2 levels of PTE */
+        ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
+                             virtual, is_user, rw);
+        break;
+    case 2:
+        /* kernel segment */
+        if (is_user) {
+            ret = 2;
+        } else {
+            *physp = virtual;
+        }
+        break;
+    case 3:
+        /* seg1: TB mapped */
+        ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
+                             virtual, is_user, rw);
+        break;
+    default:
+        ret = 1;
+        break;
+    }
+
+    return ret;
+}
+
+/* XXX: code provision */
+int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
+                              int is_user, int is_softmmu)
+{
+    uint64_t physical, page_size, end;
+    int prot, zbits, ret;
+
+    if (env->user_mode_only) {
+        ret = 2;
+    } else { 
+        ret = virtual_to_physical(env, &physical, &zbits, &prot,
+                                  address, is_user, rw);
+    }
+    switch (ret) {
+    case 0:
+        /* No fault */
+        page_size = 1ULL << zbits;
+        address &= ~(page_size - 1);
+        for (end = physical + page_size; physical < end; physical += 0x1000) {
+            ret = tlb_set_page(env, address, physical, prot,
+                               is_user, is_softmmu);
+            address += 0x1000;
+        }
+        break;
+#if 0
+    case 1:
+        env->exception_index = EXCP_DFAULT;
+        env->ipr[IPR_EXC_ADDR] = address;
+        ret = 1;
+        break;
+    case 2:
+        env->exception_index = EXCP_ACCESS_VIOLATION;
+        env->ipr[IPR_EXC_ADDR] = address;
+        ret = 1;
+        break;
+    case 3:
+        env->exception_index = EXCP_FAULT_ON_READ;
+        env->ipr[IPR_EXC_ADDR] = address;
+        ret = 1;
+        break;
+    case 4:
+        env->exception_index = EXCP_FAULT_ON_EXECUTE;
+        env->ipr[IPR_EXC_ADDR] = address;
+        ret = 1;
+    case 5:
+        env->exception_index = EXCP_FAULT_ON_WRITE;
+        env->ipr[IPR_EXC_ADDR] = address;
+        ret = 1;
+#endif
+    default:
+        /* Should never happen */
+        env->exception_index = EXCP_MCHK;
+        env->ipr[IPR_EXC_ADDR] = address;
+        ret = 1;
+        break;
+    }
+
+    return ret;
+}
+#endif
+
+#else /* !defined (CONFIG_USER_ONLY) */
+void pal_init (CPUState *env)
+{
+}
+
+void call_pal (CPUState *env, int palcode)
+{
+    target_ulong ret;
+
+    printf("%s: palcode %02x\n", __func__, palcode);
+    if (logfile != NULL)
+        fprintf(logfile, "%s: palcode %02x\n", __func__, palcode);
+    switch (palcode) {
+    case 0x83:
+        /* CALLSYS */
+        printf("CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]);
+        if (logfile != NULL)
+            fprintf(logfile, "CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]);
+        ret = do_syscall(env, env->ir[IR_V0], env->ir[IR_A0], env->ir[IR_A1],
+                         env->ir[IR_A2], env->ir[IR_A3], env->ir[IR_A4],
+                         env->ir[IR_A5]);
+        env->ir[IR_A3] = ret;
+        if (ret > (target_ulong)(-515)) {
+            env->ir[IR_V0] = 1;
+        } else {
+            env->ir[IR_V0] = 0;
+        }
+        break;
+    case 0x9E:
+        /* RDUNIQUE */
+        env->ir[IR_V0] = env->unique;
+        printf("RDUNIQUE: " TARGET_FMT_lx "\n", env->unique);
+        break;
+    case 0x9F:
+        /* WRUNIQUE */
+        env->unique = env->ir[IR_A0];
+        printf("WRUNIQUE: " TARGET_FMT_lx "\n", env->unique);
+        break;
+    default:
+        printf("%s: unhandled palcode %02x\n", __func__, palcode);
+        if (logfile != NULL)
+            fprintf(logfile, "%s: unhandled palcode %02x\n",
+                    __func__, palcode);
+        exit(1);
+    }
+}
+#endif

Modified: trunk/src/host/qemu-neo1973/hw/apb_pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/apb_pci.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/apb_pci.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -200,14 +200,14 @@
     return bus_offset + irq_num;
 }
 
-static void pci_apb_set_irq(void *pic, int irq_num, int level)
+static void pci_apb_set_irq(qemu_irq *pic, int irq_num, int level)
 {
     /* PCI IRQ map onto the first 32 INO.  */
-    pic_set_irq_new(pic, irq_num, level);
+    qemu_set_irq(pic[irq_num], level);
 }
 
 PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base,
-                     void *pic)
+                     qemu_irq *pic)
 {
     APBState *s;
     PCIDevice *d;

Modified: trunk/src/host/qemu-neo1973/hw/apic.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/apic.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/apic.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -816,6 +816,7 @@
     env->apic_state = s;
     apic_init_ipi(s);
     s->id = last_apic_id++;
+    env->cpuid_apic_id = s->id;
     s->cpu_env = env;
     s->apicbase = 0xfee00000 | 
         (s->id ? 0 : MSR_IA32_APICBASE_BSP) | MSR_IA32_APICBASE_ENABLE;
@@ -831,7 +832,7 @@
     }
     s->timer = qemu_new_timer(vm_clock, apic_timer, s);
 
-    register_savevm("apic", 0, 1, apic_save, apic_load, s);
+    register_savevm("apic", 0, 2, apic_save, apic_load, s);
     qemu_register_reset(apic_reset, s);
     
     local_apics[s->id] = s;

Modified: trunk/src/host/qemu-neo1973/hw/arm_boot.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/arm_boot.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/arm_boot.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -24,8 +24,20 @@
   0  /* Kernel entry point.  Set by integratorcp_init.  */
 };
 
+static void main_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+
+    cpu_reset(env);
+    if (env->kernel_filename)
+        arm_load_kernel(env, env->ram_size, env->kernel_filename, 
+                        env->kernel_cmdline, env->initrd_filename, 
+                        env->board_id, env->loader_start);
+}
+
 static void set_kernel_args(uint32_t ram_size, int initrd_size,
-                            const char *kernel_cmdline)
+                            const char *kernel_cmdline,
+                            target_phys_addr_t loader_start)
 {
     uint32_t *p;
 
@@ -40,12 +52,12 @@
     stl_raw(p++, 4);
     stl_raw(p++, 0x54410002);
     stl_raw(p++, ram_size);
-    stl_raw(p++, 0);
+    stl_raw(p++, loader_start);
     if (initrd_size) {
         /* ATAG_INITRD2 */
         stl_raw(p++, 4);
         stl_raw(p++, 0x54420005);
-        stl_raw(p++, INITRD_LOAD_ADDR);
+        stl_raw(p++, loader_start + INITRD_LOAD_ADDR);
         stl_raw(p++, initrd_size);
     }
     if (kernel_cmdline && *kernel_cmdline) {
@@ -64,42 +76,70 @@
     stl_raw(p++, 0);
 }
 
-void arm_load_kernel(int ram_size, const char *kernel_filename,
+void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
                      const char *kernel_cmdline, const char *initrd_filename,
                      int board_id, target_phys_addr_t loader_start)
 {
     int kernel_size;
     int initrd_size;
     int n;
+    int is_linux = 0;
+    uint64_t elf_entry;
+    target_ulong entry;
 
     /* Load the kernel.  */
     if (!kernel_filename) {
         fprintf(stderr, "Kernel image must be specified\n");
         exit(1);
     }
-    kernel_size = load_image(kernel_filename,
-                             phys_ram_base + KERNEL_LOAD_ADDR + S3C_SRAM_SIZE);////
+
+    if (!env->kernel_filename) {
+        env->ram_size = ram_size;
+        env->kernel_filename = kernel_filename;
+        env->kernel_cmdline = kernel_cmdline;
+        env->initrd_filename = initrd_filename;
+        env->board_id = board_id;
+        env->loader_start = loader_start;
+        qemu_register_reset(main_cpu_reset, env);
+    }
+    /* Assume that raw images are linux kernels, and ELF images are not.  */
+    kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL);
+    entry = elf_entry;
     if (kernel_size < 0) {
+        kernel_size = load_uboot(kernel_filename, &entry, &is_linux);
+    }
+    if (kernel_size < 0) {
+        kernel_size = load_image(kernel_filename,
+                                 phys_ram_base + KERNEL_LOAD_ADDR);
+        entry = loader_start + KERNEL_LOAD_ADDR;
+        is_linux = 1;
+    }
+    if (kernel_size < 0) {
         fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
         exit(1);
     }
-    if (initrd_filename) {
-        initrd_size = load_image(initrd_filename,
-                                 phys_ram_base + INITRD_LOAD_ADDR);
-        if (initrd_size < 0) {
-            fprintf(stderr, "qemu: could not load initrd '%s'\n",
-                    initrd_filename);
-            exit(1);
+    if (!is_linux) {
+        /* Jump to the entry point.  */
+        env->regs[15] = entry & 0xfffffffe;
+        env->thumb = entry & 1;
+    } else {
+        if (initrd_filename) {
+            initrd_size = load_image(initrd_filename,
+                                     phys_ram_base + INITRD_LOAD_ADDR);
+            if (initrd_size < 0) {
+                fprintf(stderr, "qemu: could not load initrd '%s'\n",
+                        initrd_filename);
+                exit(1);
+            }
+        } else {
+            initrd_size = 0;
         }
-    } else {
-        initrd_size = 0;
+        bootloader[1] |= board_id & 0xff;
+        bootloader[2] |= (board_id >> 8) & 0xff;
+        bootloader[5] = loader_start + KERNEL_ARGS_ADDR;
+        bootloader[6] = entry;
+        for (n = 0; n < sizeof(bootloader) / 4; n++)
+            stl_raw(phys_ram_base + (n * 4), bootloader[n]);
+        set_kernel_args(ram_size, initrd_size, kernel_cmdline, loader_start);
     }
-    bootloader[1] |= board_id & 0xff;
-    bootloader[2] |= (board_id >> 8) & 0xff;
-    bootloader[5] = loader_start + KERNEL_ARGS_ADDR;
-    bootloader[6] = loader_start + KERNEL_LOAD_ADDR;
-    for (n = 0; n < sizeof(bootloader) / 4; n++)
-        stl_raw(phys_ram_base + (n * 4), bootloader[n]);
-    set_kernel_args(ram_size, initrd_size, kernel_cmdline);
 }
-

Modified: trunk/src/host/qemu-neo1973/hw/arm_gic.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/arm_gic.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/arm_gic.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -60,10 +60,8 @@
 
 typedef struct gic_state
 {
-    arm_pic_handler handler;
     uint32_t base;
-    void *parent;
-    int parent_irq;
+    qemu_irq parent_irq;
     int enabled;
     int cpu_enabled;
 
@@ -88,7 +86,7 @@
 
     s->current_pending = 1023;
     if (!s->enabled || !s->cpu_enabled) {
-        pic_set_irq_new(s->parent, s->parent_irq, 0);
+        qemu_irq_lower(s->parent_irq);
         return;
     }
     best_prio = 0x100;
@@ -102,12 +100,12 @@
         }
     }
     if (best_prio > s->priority_mask) {
-        pic_set_irq_new(s->parent, s->parent_irq, 0);
+        qemu_irq_lower(s->parent_irq);
     } else {
         s->current_pending = best_irq;
         if (best_prio < s->running_priority) {
             DPRINTF("Raised pending IRQ %d\n", best_irq);
-            pic_set_irq_new(s->parent, s->parent_irq, 1);
+            qemu_irq_raise(s->parent_irq);
         }
     }
 }
@@ -150,7 +148,7 @@
         DPRINTF("ACK no pending IRQ\n");
         return 1023;
     }
-    pic_set_irq_new(s->parent, s->parent_irq, 0);
+    qemu_irq_lower(s->parent_irq);
     s->last_active[new_irq] = s->running_irq;
     /* For level triggered interrupts we clear the pending bit while
        the interrupt is active.  */
@@ -520,16 +518,16 @@
     s->cpu_enabled = 0;
 }
 
-void *arm_gic_init(uint32_t base, void *parent, int parent_irq)
+qemu_irq *arm_gic_init(uint32_t base, qemu_irq parent_irq)
 {
     gic_state *s;
+    qemu_irq *qi;
     int iomemtype;
 
     s = (gic_state *)qemu_mallocz(sizeof(gic_state));
     if (!s)
         return NULL;
-    s->handler = gic_set_irq;
-    s->parent = parent;
+    qi = qemu_allocate_irqs(gic_set_irq, s, GIC_NIRQ);
     s->parent_irq = parent_irq;
     if (base != 0xffffffff) {
         iomemtype = cpu_register_io_memory(0, gic_cpu_readfn,
@@ -543,5 +541,5 @@
         s->base = 0;
     }
     gic_reset(s);
-    return s;
+    return qi;
 }

Modified: trunk/src/host/qemu-neo1973/hw/arm_pic.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/arm_pic.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/arm_pic.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -11,11 +11,6 @@
 #include "arm_pic.h"
 
 /* Stub functions for hardware that doesn't exist.  */
-void pic_set_irq(int irq, int level)
-{
-    cpu_abort(cpu_single_env, "pic_set_irq");
-}
-
 void pic_info(void)
 {
 }
@@ -25,49 +20,29 @@
 }
 
 
-void pic_set_irq_new(void *opaque, int irq, int level)
-{
-    arm_pic_handler *p = (arm_pic_handler *)opaque;
-    /* Call the real handler.  */
-    (*p)(opaque, irq, level);
-}
-
-/* Model the IRQ/FIQ CPU interrupt lines as a two input interrupt controller.
-   Input 0 is IRQ and input 1 is FIQ.  */
-typedef struct
-{
-    arm_pic_handler handler;
-    CPUState *cpu_env;
-} arm_pic_cpu_state;
-
+/* Input 0 is IRQ and input 1 is FIQ.  */
 static void arm_pic_cpu_handler(void *opaque, int irq, int level)
 {
-    arm_pic_cpu_state *s = (arm_pic_cpu_state *)opaque;
+    CPUState *env = (CPUState *)opaque;
     switch (irq) {
     case ARM_PIC_CPU_IRQ:
         if (level)
-            cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
         else
-            cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
+            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
         break;
     case ARM_PIC_CPU_FIQ:
         if (level)
-            cpu_interrupt(s->cpu_env, CPU_INTERRUPT_FIQ);
+            cpu_interrupt(env, CPU_INTERRUPT_FIQ);
         else
-            cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_FIQ);
+            cpu_reset_interrupt(env, CPU_INTERRUPT_FIQ);
         break;
     default:
-        cpu_abort(s->cpu_env, "arm_pic_cpu_handler: Bad interrput line %d\n",
-                  irq);
+        cpu_abort(env, "arm_pic_cpu_handler: Bad interrput line %d\n", irq);
     }
 }
 
-void *arm_pic_init_cpu(CPUState *env)
+qemu_irq *arm_pic_init_cpu(CPUState *env)
 {
-    arm_pic_cpu_state *s;
-    
-    s = (arm_pic_cpu_state *)malloc(sizeof(arm_pic_cpu_state));
-    s->handler = arm_pic_cpu_handler;
-    s->cpu_env = env;
-    return s;
+    return qemu_allocate_irqs(arm_pic_cpu_handler, env, 2);
 }

Modified: trunk/src/host/qemu-neo1973/hw/arm_pic.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/arm_pic.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/arm_pic.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -14,14 +14,10 @@
 #ifndef ARM_INTERRUPT_H
 #define ARM_INTERRUPT_H 1
 
-/* The first element of an individual PIC state structures should
-   be a pointer to the handler routine.  */
-typedef void (*arm_pic_handler)(void *opaque, int irq, int level);
-
 /* The CPU is also modeled as an interrupt controller.  */
 #define ARM_PIC_CPU_IRQ 0
 #define ARM_PIC_CPU_FIQ 1
-void *arm_pic_init_cpu(CPUState *env);
+qemu_irq *arm_pic_init_cpu(CPUState *env);
 
 #endif /* !ARM_INTERRUPT_H */
 

Modified: trunk/src/host/qemu-neo1973/hw/arm_sysctl.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/arm_sysctl.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/arm_sysctl.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -149,7 +149,7 @@
         if (s->lockval == LOCK_VALUE) {
             s->resetlevel = val;
             if (val & 0x100)
-                cpu_abort(cpu_single_env, "Board reset\n");
+                qemu_system_reset_request ();
         }
         break;
     case 0x44: /* PCICTL */

Modified: trunk/src/host/qemu-neo1973/hw/arm_timer.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/arm_timer.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/arm_timer.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -32,8 +32,7 @@
     int raw_freq;
     int freq;
     int int_level;
-    void *pic;
-    int irq;
+    qemu_irq irq;
 } arm_timer_state;
 
 /* Calculate the new expiry time of the given timer.  */
@@ -85,9 +84,9 @@
     }
     /* Update interrupts.  */
     if (s->int_level && (s->control & TIMER_CTRL_IE)) {
-        pic_set_irq_new(s->pic, s->irq, 1);
+        qemu_irq_raise(s->irq);
     } else {
-        pic_set_irq_new(s->pic, s->irq, 0);
+        qemu_irq_lower(s->irq);
     }
 
     next = now;
@@ -215,12 +214,11 @@
     arm_timer_update((arm_timer_state *)opaque, now);
 }
 
-static void *arm_timer_init(uint32_t freq, void *pic, int irq)
+static void *arm_timer_init(uint32_t freq, qemu_irq irq)
 {
     arm_timer_state *s;
 
     s = (arm_timer_state *)qemu_mallocz(sizeof(arm_timer_state));
-    s->pic = pic;
     s->irq = irq;
     s->raw_freq = s->freq = 1000000;
     s->control = TIMER_CTRL_IE;
@@ -233,26 +231,23 @@
 
 /* ARM PrimeCell SP804 dual timer module.
    Docs for this device don't seem to be publicly available.  This
-   implementation is based on gueswork, the linux kernel sources and the
+   implementation is based on guesswork, the linux kernel sources and the
    Integrator/CP timer modules.  */
 
 typedef struct {
-    /* Include a pseudo-PIC device to merge the two interrupt sources.  */
-    arm_pic_handler handler;
     void *timer[2];
     int level[2];
     uint32_t base;
-    /* The output PIC device.  */
-    void *pic;
-    int irq;
+    qemu_irq irq;
 } sp804_state;
 
+/* Merge the IRQs from the two component devices.  */
 static void sp804_set_irq(void *opaque, int irq, int level)
 {
     sp804_state *s = (sp804_state *)opaque;
 
     s->level[irq] = level;
-    pic_set_irq_new(s->pic, s->irq, s->level[0] || s->level[1]);
+    qemu_set_irq(s->irq, s->level[0] || s->level[1]);
 }
 
 static uint32_t sp804_read(void *opaque, target_phys_addr_t offset)
@@ -293,20 +288,20 @@
    sp804_write
 };
 
-void sp804_init(uint32_t base, void *pic, int irq)
+void sp804_init(uint32_t base, qemu_irq irq)
 {
     int iomemtype;
     sp804_state *s;
+    qemu_irq *qi;
 
     s = (sp804_state *)qemu_mallocz(sizeof(sp804_state));
-    s->handler = sp804_set_irq;
+    qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
     s->base = base;
-    s->pic = pic;
     s->irq = irq;
     /* ??? The timers are actually configurable between 32kHz and 1MHz, but
        we don't implement that.  */
-    s->timer[0] = arm_timer_init(1000000, s, 0);
-    s->timer[1] = arm_timer_init(1000000, s, 1);
+    s->timer[0] = arm_timer_init(1000000, qi[0]);
+    s->timer[1] = arm_timer_init(1000000, qi[1]);
     iomemtype = cpu_register_io_memory(0, sp804_readfn,
                                        sp804_writefn, s);
     cpu_register_physical_memory(base, 0x00000fff, iomemtype);
@@ -362,7 +357,7 @@
    icp_pit_write
 };
 
-void icp_pit_init(uint32_t base, void *pic, int irq)
+void icp_pit_init(uint32_t base, qemu_irq *pic, int irq)
 {
     int iomemtype;
     icp_pit_state *s;
@@ -370,10 +365,10 @@
     s = (icp_pit_state *)qemu_mallocz(sizeof(icp_pit_state));
     s->base = base;
     /* Timer 0 runs at the system clock speed (40MHz).  */
-    s->timer[0] = arm_timer_init(40000000, pic, irq);
+    s->timer[0] = arm_timer_init(40000000, pic[irq]);
     /* The other two timers run at 1MHz.  */
-    s->timer[1] = arm_timer_init(1000000, pic, irq + 1);
-    s->timer[2] = arm_timer_init(1000000, pic, irq + 2);
+    s->timer[1] = arm_timer_init(1000000, pic[irq + 1]);
+    s->timer[2] = arm_timer_init(1000000, pic[irq + 2]);
 
     iomemtype = cpu_register_io_memory(0, icp_pit_readfn,
                                        icp_pit_writefn, s);

Modified: trunk/src/host/qemu-neo1973/hw/cirrus_vga.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/cirrus_vga.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/cirrus_vga.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -3193,6 +3193,9 @@
     vga_common_init((VGAState *)s, 
                     ds, vga_ram_base, vga_ram_offset, vga_ram_size);
     cirrus_init_common(s, device_id, 1);
+
+    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
+
     s->pci_dev = (PCIDevice *)d;
 
     /* setup memory space */

Modified: trunk/src/host/qemu-neo1973/hw/cs4231.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/cs4231.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/cs4231.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -47,9 +47,6 @@
 #ifdef DEBUG_CS
 #define DPRINTF(fmt, args...)                           \
     do { printf("CS: " fmt , ##args); } while (0)
-#define pic_set_irq_new(intctl, irq, level)                             \
-    do { printf("CS: set_irq(%d): %d\n", (irq), (level));               \
-        pic_set_irq_new((intctl), (irq),(level));} while (0)
 #else
 #define DPRINTF(fmt, args...)
 #endif

Modified: trunk/src/host/qemu-neo1973/hw/cuda.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/cuda.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/cuda.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -124,9 +124,7 @@
     int data_in_index;
     int data_out_index;
 
-    SetIRQFunc *set_irq;
-    int irq;
-    void *irq_opaque;
+    qemu_irq irq;
     uint8_t autopoll;
     uint8_t data_in[128];
     uint8_t data_out[16];
@@ -145,9 +143,9 @@
 static void cuda_update_irq(CUDAState *s)
 {
     if (s->ifr & s->ier & (SR_INT | T1_INT)) {
-        s->set_irq(s->irq_opaque, s->irq, 1);
+        qemu_irq_raise(s->irq);
     } else {
-        s->set_irq(s->irq_opaque, s->irq, 0);
+        qemu_irq_lower(s->irq);
     }
 }
 
@@ -630,13 +628,11 @@
     &cuda_readl,
 };
 
-int cuda_init(SetIRQFunc *set_irq, void *irq_opaque, int irq)
+int cuda_init(qemu_irq irq)
 {
     CUDAState *s = &cuda_state;
     int cuda_mem_index;
 
-    s->set_irq = set_irq;
-    s->irq_opaque = irq_opaque;
     s->irq = irq;
 
     s->timers[0].index = 0;

Added: trunk/src/host/qemu-neo1973/hw/ds1225y.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ds1225y.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/ds1225y.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,121 @@
+/*
+ * QEMU NVRAM emulation for DS1225Y chip
+ * 
+ * Copyright (c) 2007 Hervé Poussineau
+ * 
+ * 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"
+
+typedef enum
+{
+    none = 0,
+    readmode,
+    writemode,
+} nvram_open_mode;
+
+struct ds1225y_t
+{
+    target_ulong mem_base;
+    uint32_t capacity;
+    const char *filename;
+    QEMUFile *file;
+    nvram_open_mode open_mode;
+};
+
+static int ds1225y_set_to_mode(ds1225y_t *NVRAM, nvram_open_mode mode, const char *filemode)
+{
+    if (NVRAM->open_mode != mode)
+    {
+        if (NVRAM->file)
+            qemu_fclose(NVRAM->file);
+        NVRAM->file = qemu_fopen(NVRAM->filename, filemode);
+        NVRAM->open_mode = mode;
+    }
+    return (NVRAM->file != NULL);
+}
+
+static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
+{
+    ds1225y_t *NVRAM = opaque;
+    int64_t pos;
+
+    pos = addr - NVRAM->mem_base;
+    if (addr >= NVRAM->capacity)
+        addr -= NVRAM->capacity;
+
+    if (!ds1225y_set_to_mode(NVRAM, readmode, "rb"))
+        return 0;
+    qemu_fseek(NVRAM->file, pos, SEEK_SET);
+    return (uint32_t)qemu_get_byte(NVRAM->file);
+}
+
+static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    ds1225y_t *NVRAM = opaque;
+    int64_t pos;
+
+    pos = addr - NVRAM->mem_base;
+    if (ds1225y_set_to_mode(NVRAM, writemode, "wb"))
+    {
+        qemu_fseek(NVRAM->file, pos, SEEK_SET);
+        qemu_put_byte(NVRAM->file, (int)value);
+    }
+}
+
+static CPUReadMemoryFunc *nvram_read[] = {
+    &nvram_readb,
+    NULL,
+    NULL,
+};
+
+static CPUWriteMemoryFunc *nvram_write[] = {
+    &nvram_writeb,
+    NULL,
+    NULL,
+};
+
+static CPUWriteMemoryFunc *nvram_none[] = {
+    NULL,
+    NULL,
+    NULL,
+};
+
+/* Initialisation routine */
+ds1225y_t *ds1225y_init(target_ulong mem_base, const char *filename)
+{
+    ds1225y_t *s;
+    int mem_index1, mem_index2;
+
+    s = qemu_mallocz(sizeof(ds1225y_t));
+    if (!s)
+        return NULL;
+    s->mem_base = mem_base;
+    s->capacity = 0x2000; /* Fixed for ds1225y chip: 8K */
+    s->filename = filename;
+
+    /* Read/write memory */
+    mem_index1 = cpu_register_io_memory(0, nvram_read, nvram_write, s);
+    cpu_register_physical_memory(mem_base, s->capacity, mem_index1);
+    /* Read-only memory */
+    mem_index2 = cpu_register_io_memory(0, nvram_read, nvram_none, s);
+    cpu_register_physical_memory(mem_base + s->capacity, s->capacity, mem_index2);
+    return s;
+}

Added: trunk/src/host/qemu-neo1973/hw/eepro100.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/eepro100.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/eepro100.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,1714 @@
+/*
+ * QEMU i8255x (PRO100) emulation
+ *
+ * Copyright (c) 2006-2007 Stefan Weil
+ *
+ * Portions of the code are copies from grub / etherboot eepro100.c
+ * and linux e100.c.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Tested features (i82559):
+ *      PXE boot (i386) no valid link
+ *      Linux networking (i386) ok
+ *
+ * Untested:
+ *      non-i386 platforms
+ *      Windows networking
+ *
+ * References:
+ *
+ * Intel 8255x 10/100 Mbps Ethernet Controller Family
+ * Open Source Software Developer Manual
+ */
+
+#if defined(TARGET_I386)
+# warning "PXE boot still not working!"
+#endif
+
+#include <assert.h>
+#include <stddef.h>             /* offsetof */
+#include "vl.h"
+#include "eeprom93xx.h"
+
+/* Common declarations for all PCI devices. */
+
+#define PCI_VENDOR_ID           0x00    /* 16 bits */
+#define PCI_DEVICE_ID           0x02    /* 16 bits */
+#define PCI_COMMAND             0x04    /* 16 bits */
+#define PCI_STATUS              0x06    /* 16 bits */
+
+#define PCI_REVISION_ID         0x08    /* 8 bits  */
+#define PCI_CLASS_CODE          0x0b    /* 8 bits */
+#define PCI_SUBCLASS_CODE       0x0a    /* 8 bits */
+#define PCI_HEADER_TYPE         0x0e    /* 8 bits */
+
+#define PCI_BASE_ADDRESS_0      0x10    /* 32 bits */
+#define PCI_BASE_ADDRESS_1      0x14    /* 32 bits */
+#define PCI_BASE_ADDRESS_2      0x18    /* 32 bits */
+#define PCI_BASE_ADDRESS_3      0x1c    /* 32 bits */
+#define PCI_BASE_ADDRESS_4      0x20    /* 32 bits */
+#define PCI_BASE_ADDRESS_5      0x24    /* 32 bits */
+
+#define PCI_CONFIG_8(offset, value) \
+    (pci_conf[offset] = (value))
+#define PCI_CONFIG_16(offset, value) \
+    (*(uint16_t *)&pci_conf[offset] = cpu_to_le16(value))
+#define PCI_CONFIG_32(offset, value) \
+    (*(uint32_t *)&pci_conf[offset] = cpu_to_le32(value))
+
+#define KiB 1024
+
+/* debug EEPRO100 card */
+//~ #define DEBUG_EEPRO100
+
+#ifdef DEBUG_EEPRO100
+#define logout(fmt, args...) fprintf(stderr, "EE100\t%-24s" fmt, __func__, ##args)
+#else
+#define logout(fmt, args...) ((void)0)
+#endif
+
+/* Set flags to 0 to disable debug output. */
+#define MDI     0
+
+#define TRACE(flag, command) ((flag) ? (command) : (void)0)
+
+#define missing(text)       assert(!"feature is missing in this emulation: " text)
+
+#define MAX_ETH_FRAME_SIZE 1514
+
+/* This driver supports several different devices which are declared here. */
+#define i82551          0x82551
+#define i82557B         0x82557b
+#define i82557C         0x82557c
+#define i82558B         0x82558b
+#define i82559C         0x82559c
+#define i82559ER        0x82559e
+#define i82562          0x82562
+
+#define EEPROM_SIZE     64
+
+#define PCI_MEM_SIZE            (4 * KiB)
+#define PCI_IO_SIZE             64
+#define PCI_FLASH_SIZE          (128 * KiB)
+
+#define BIT(n) (1 << (n))
+#define BITS(n, m) (((0xffffffffU << (31 - n)) >> (31 - n + m)) << m)
+
+/* The SCB accepts the following controls for the Tx and Rx units: */
+#define  CU_NOP         0x0000  /* No operation. */
+#define  CU_START       0x0010  /* CU start. */
+#define  CU_RESUME      0x0020  /* CU resume. */
+#define  CU_STATSADDR   0x0040  /* Load dump counters address. */
+#define  CU_SHOWSTATS   0x0050  /* Dump statistical counters. */
+#define  CU_CMD_BASE    0x0060  /* Load CU base address. */
+#define  CU_DUMPSTATS   0x0070  /* Dump and reset statistical counters. */
+#define  CU_SRESUME     0x00a0  /* CU static resume. */
+
+#define  RU_NOP         0x0000
+#define  RX_START       0x0001
+#define  RX_RESUME      0x0002
+#define  RX_ABORT       0x0004
+#define  RX_ADDR_LOAD   0x0006
+#define  RX_RESUMENR    0x0007
+#define INT_MASK        0x0100
+#define DRVR_INT        0x0200  /* Driver generated interrupt. */
+
+typedef unsigned char bool;
+
+/* Offsets to the various registers.
+   All accesses need not be longword aligned. */
+enum speedo_offsets {
+    SCBStatus = 0,
+    SCBAck = 1,
+    SCBCmd = 2,                 /* Rx/Command Unit command and status. */
+    SCBIntmask = 3,
+    SCBPointer = 4,             /* General purpose pointer. */
+    SCBPort = 8,                /* Misc. commands and operands.  */
+    SCBflash = 12, SCBeeprom = 14,      /* EEPROM and flash memory control. */
+    SCBCtrlMDI = 16,            /* MDI interface control. */
+    SCBEarlyRx = 20,            /* Early receive byte count. */
+};
+
+/* A speedo3 transmit buffer descriptor with two buffers... */
+typedef struct {
+    uint16_t status;
+    uint16_t command;
+    uint32_t link;              /* void * */
+    uint32_t tx_desc_addr;      /* transmit buffer decsriptor array address. */
+    uint16_t tcb_bytes;         /* transmit command block byte count (in lower 14 bits */
+    uint8_t tx_threshold;       /* transmit threshold */
+    uint8_t tbd_count;          /* TBD number */
+    //~ /* This constitutes two "TBD" entries: hdr and data */
+    //~ uint32_t tx_buf_addr0;  /* void *, header of frame to be transmitted.  */
+    //~ int32_t  tx_buf_size0;  /* Length of Tx hdr. */
+    //~ uint32_t tx_buf_addr1;  /* void *, data to be transmitted.  */
+    //~ int32_t  tx_buf_size1;  /* Length of Tx data. */
+} eepro100_tx_t;
+
+/* Receive frame descriptor. */
+typedef struct {
+    int16_t status;
+    uint16_t command;
+    uint32_t link;              /* struct RxFD * */
+    uint32_t rx_buf_addr;       /* void * */
+    uint16_t count;
+    uint16_t size;
+    char packet[MAX_ETH_FRAME_SIZE + 4];
+} eepro100_rx_t;
+
+typedef struct {
+    uint32_t tx_good_frames, tx_max_collisions, tx_late_collisions,
+        tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions,
+        tx_multiple_collisions, tx_total_collisions;
+    uint32_t rx_good_frames, rx_crc_errors, rx_alignment_errors,
+        rx_resource_errors, rx_overrun_errors, rx_cdt_errors,
+        rx_short_frame_errors;
+    uint32_t fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported;
+    uint16_t xmt_tco_frames, rcv_tco_frames;
+    uint32_t complete;
+} eepro100_stats_t;
+
+typedef enum {
+    cu_idle = 0,
+    cu_suspended = 1,
+    cu_active = 2,
+    cu_lpq_active = 2,
+    cu_hqp_active = 3
+} cu_state_t;
+
+typedef enum {
+    ru_idle = 0,
+    ru_suspended = 1,
+    ru_no_resources = 2,
+    ru_ready = 4
+} ru_state_t;
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+#define X(a,b)	b,a
+#else
+#define X(a,b)	a,b
+#endif
+
+typedef struct {
+#if 1
+    uint8_t cmd;
+    uint32_t start;
+    uint32_t stop;
+    uint8_t boundary;
+    uint8_t tsr;
+    uint8_t tpsr;
+    uint16_t tcnt;
+    uint16_t rcnt;
+    uint32_t rsar;
+    uint8_t rsr;
+    uint8_t rxcr;
+    uint8_t isr;
+    uint8_t dcfg;
+    uint8_t imr;
+    uint8_t phys[6];            /* mac address */
+    uint8_t curpag;
+    uint8_t mult[8];            /* multicast mask array */
+    int mmio_index;
+    PCIDevice *pci_dev;
+    VLANClientState *vc;
+#endif
+    uint8_t scb_stat;           /* SCB stat/ack byte */
+    uint8_t int_stat;           /* PCI interrupt status */
+    uint32_t region[3];         /* PCI region addresses */
+    uint8_t macaddr[6];
+    uint32_t statcounter[19];
+    uint16_t mdimem[32];
+    eeprom_t *eeprom;
+    uint32_t device;            /* device variant */
+    uint32_t pointer;
+    /* (cu_base + cu_offset) address the next command block in the command block list. */
+    uint32_t cu_base;           /* CU base address */
+    uint32_t cu_offset;         /* CU address offset */
+    /* (ru_base + ru_offset) address the RFD in the Receive Frame Area. */
+    uint32_t ru_base;           /* RU base address */
+    uint32_t ru_offset;         /* RU address offset */
+    uint32_t statsaddr;         /* pointer to eepro100_stats_t */
+    eepro100_stats_t statistics;        /* statistical counters */
+#if 0
+    uint16_t status;
+#endif
+
+    /* Configuration bytes. */
+    uint8_t configuration[22];
+
+    /* Data in mem is always in the byte order of the controller (le). */
+    uint8_t mem[PCI_MEM_SIZE];
+} EEPRO100State;
+
+/* Default values for MDI (PHY) registers */
+static const uint16_t eepro100_mdi_default[] = {
+    /* MDI Registers 0 - 6, 7 */
+    0x3000, 0x780d, 0x02a8, 0x0154, 0x05e1, 0x0000, 0x0000, 0x0000,
+    /* MDI Registers 8 - 15 */
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* MDI Registers 16 - 31 */
+    0x0003, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+/* Readonly mask for MDI (PHY) registers */
+static const uint16_t eepro100_mdi_mask[] = {
+    0x0000, 0xffff, 0xffff, 0xffff, 0xc01f, 0xffff, 0xffff, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0fff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+    0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+#define POLYNOMIAL 0x04c11db6
+
+/* From FreeBSD */
+/* XXX: optimize */
+static int compute_mcast_idx(const uint8_t * ep)
+{
+    uint32_t crc;
+    int carry, i, j;
+    uint8_t b;
+
+    crc = 0xffffffff;
+    for (i = 0; i < 6; i++) {
+        b = *ep++;
+        for (j = 0; j < 8; j++) {
+            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
+            crc <<= 1;
+            b >>= 1;
+            if (carry)
+                crc = ((crc ^ POLYNOMIAL) | carry);
+        }
+    }
+    return (crc >> 26);
+}
+
+#if defined(DEBUG_EEPRO100)
+static const char *nic_dump(const uint8_t * buf, unsigned size)
+{
+    static char dump[3 * 16 + 1];
+    char *p = &dump[0];
+    if (size > 16)
+        size = 16;
+    while (size-- > 0) {
+        p += sprintf(p, " %02x", *buf++);
+    }
+    return dump;
+}
+#endif                          /* DEBUG_EEPRO100 */
+
+enum scb_stat_ack {
+    stat_ack_not_ours = 0x00,
+    stat_ack_sw_gen = 0x04,
+    stat_ack_rnr = 0x10,
+    stat_ack_cu_idle = 0x20,
+    stat_ack_frame_rx = 0x40,
+    stat_ack_cu_cmd_done = 0x80,
+    stat_ack_not_present = 0xFF,
+    stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx),
+    stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done),
+};
+
+static void disable_interrupt(EEPRO100State * s)
+{
+    if (s->int_stat) {
+        logout("interrupt disabled\n");
+        qemu_irq_lower(s->pci_dev->irq[0]);
+        s->int_stat = 0;
+    }
+}
+
+static void enable_interrupt(EEPRO100State * s)
+{
+    if (!s->int_stat) {
+        logout("interrupt enabled\n");
+        qemu_irq_raise(s->pci_dev->irq[0]);
+        s->int_stat = 1;
+    }
+}
+
+static void eepro100_acknowledge(EEPRO100State * s)
+{
+    s->scb_stat &= ~s->mem[SCBAck];
+    s->mem[SCBAck] = s->scb_stat;
+    if (s->scb_stat == 0) {
+        disable_interrupt(s);
+    }
+}
+
+static void eepro100_interrupt(EEPRO100State * s, uint8_t stat)
+{
+    uint8_t mask = ~s->mem[SCBIntmask];
+    s->mem[SCBAck] |= stat;
+    stat = s->scb_stat = s->mem[SCBAck];
+    stat &= (mask | 0x0f);
+    //~ stat &= (~s->mem[SCBIntmask] | 0x0xf);
+    if (stat && (mask & 0x01)) {
+        /* SCB mask and SCB Bit M do not disable interrupt. */
+        enable_interrupt(s);
+    } else if (s->int_stat) {
+        disable_interrupt(s);
+    }
+}
+
+static void eepro100_cx_interrupt(EEPRO100State * s)
+{
+    /* CU completed action command. */
+    /* Transmit not ok (82557 only, not in emulation). */
+    eepro100_interrupt(s, 0x80);
+}
+
+static void eepro100_cna_interrupt(EEPRO100State * s)
+{
+    /* CU left the active state. */
+    eepro100_interrupt(s, 0x20);
+}
+
+static void eepro100_fr_interrupt(EEPRO100State * s)
+{
+    /* RU received a complete frame. */
+    eepro100_interrupt(s, 0x40);
+}
+
+#if 0
+static void eepro100_rnr_interrupt(EEPRO100State * s)
+{
+    /* RU is not ready. */
+    eepro100_interrupt(s, 0x10);
+}
+#endif
+
+static void eepro100_mdi_interrupt(EEPRO100State * s)
+{
+    /* MDI completed read or write cycle. */
+    eepro100_interrupt(s, 0x08);
+}
+
+static void eepro100_swi_interrupt(EEPRO100State * s)
+{
+    /* Software has requested an interrupt. */
+    eepro100_interrupt(s, 0x04);
+}
+
+#if 0
+static void eepro100_fcp_interrupt(EEPRO100State * s)
+{
+    /* Flow control pause interrupt (82558 and later). */
+    eepro100_interrupt(s, 0x01);
+}
+#endif
+
+static void pci_reset(EEPRO100State * s)
+{
+    uint32_t device = s->device;
+    uint8_t *pci_conf = s->pci_dev->config;
+
+    logout("%p\n", s);
+
+    /* PCI Vendor ID */
+    PCI_CONFIG_16(PCI_VENDOR_ID, 0x8086);
+    /* PCI Device ID */
+    PCI_CONFIG_16(PCI_DEVICE_ID, 0x1209);
+    /* PCI Command */
+    PCI_CONFIG_16(PCI_COMMAND, 0x0000);
+    /* PCI Status */
+    PCI_CONFIG_16(PCI_STATUS, 0x2800);
+    /* PCI Revision ID */
+    PCI_CONFIG_8(PCI_REVISION_ID, 0x08);
+    /* PCI Class Code */
+    PCI_CONFIG_8(0x09, 0x00);
+    PCI_CONFIG_8(PCI_SUBCLASS_CODE, 0x00);      // ethernet network controller
+    PCI_CONFIG_8(PCI_CLASS_CODE, 0x02); // network controller
+    /* PCI Cache Line Size */
+    /* check cache line size!!! */
+    //~ PCI_CONFIG_8(0x0c, 0x00);
+    /* PCI Latency Timer */
+    PCI_CONFIG_8(0x0d, 0x20);   // latency timer = 32 clocks
+    /* PCI Header Type */
+    /* BIST (built-in self test) */
+#if defined(TARGET_I386)
+// !!! workaround for buggy bios
+//~ #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0
+#endif
+#if 0
+    /* PCI Base Address Registers */
+    /* CSR Memory Mapped Base Address */
+    PCI_CONFIG_32(PCI_BASE_ADDRESS_0,
+                  PCI_ADDRESS_SPACE_MEM | PCI_ADDRESS_SPACE_MEM_PREFETCH);
+    /* CSR I/O Mapped Base Address */
+    PCI_CONFIG_32(PCI_BASE_ADDRESS_1, PCI_ADDRESS_SPACE_IO);
+#if 0
+    /* Flash Memory Mapped Base Address */
+    PCI_CONFIG_32(PCI_BASE_ADDRESS_2, 0xfffe0000 | PCI_ADDRESS_SPACE_MEM);
+#endif
+#endif
+    /* Expansion ROM Base Address (depends on boot disable!!!) */
+    PCI_CONFIG_32(0x30, 0x00000000);
+    /* Capability Pointer */
+    PCI_CONFIG_8(0x34, 0xdc);
+    /* Interrupt Pin */
+    PCI_CONFIG_8(0x3d, 1);      // interrupt pin 0
+    /* Minimum Grant */
+    PCI_CONFIG_8(0x3e, 0x08);
+    /* Maximum Latency */
+    PCI_CONFIG_8(0x3f, 0x18);
+    /* Power Management Capabilities / Next Item Pointer / Capability ID */
+    PCI_CONFIG_32(0xdc, 0x7e210001);
+
+    switch (device) {
+    case i82551:
+        //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1209);
+        PCI_CONFIG_8(PCI_REVISION_ID, 0x0f);
+        break;
+    case i82557B:
+        PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229);
+        PCI_CONFIG_8(PCI_REVISION_ID, 0x02);
+        break;
+    case i82557C:
+        PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229);
+        PCI_CONFIG_8(PCI_REVISION_ID, 0x03);
+        break;
+    case i82558B:
+        PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229);
+        PCI_CONFIG_16(PCI_STATUS, 0x2810);
+        PCI_CONFIG_8(PCI_REVISION_ID, 0x05);
+        break;
+    case i82559C:
+        PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229);
+        PCI_CONFIG_16(PCI_STATUS, 0x2810);
+        //~ PCI_CONFIG_8(PCI_REVISION_ID, 0x08);
+        break;
+    case i82559ER:
+        //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1209);
+        PCI_CONFIG_16(PCI_STATUS, 0x2810);
+        PCI_CONFIG_8(PCI_REVISION_ID, 0x09);
+        break;
+    //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1029);
+    //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1030);       /* 82559 InBusiness 10/100 */
+    default:
+        logout("Device %X is undefined!\n", device);
+    }
+
+    if (device == i82557C || device == i82558B || device == i82559C) {
+        logout("Get device id and revision from EEPROM!!!\n");
+    }
+}
+
+static void nic_selective_reset(EEPRO100State * s)
+{
+    size_t i;
+    uint16_t *eeprom_contents = eeprom93xx_data(s->eeprom);
+    //~ eeprom93xx_reset(s->eeprom);
+    memcpy(eeprom_contents, s->macaddr, 6);
+    eeprom_contents[0xa] = 0x4000;
+    uint16_t sum = 0;
+    for (i = 0; i < EEPROM_SIZE - 1; i++) {
+        sum += eeprom_contents[i];
+    }
+    eeprom_contents[EEPROM_SIZE - 1] = 0xbaba - sum;
+
+    memset(s->mem, 0, sizeof(s->mem));
+    uint32_t val = BIT(21);
+    memcpy(&s->mem[SCBCtrlMDI], &val, sizeof(val));
+
+    assert(sizeof(s->mdimem) == sizeof(eepro100_mdi_default));
+    memcpy(&s->mdimem[0], &eepro100_mdi_default[0], sizeof(s->mdimem));
+}
+
+static void nic_reset(void *opaque)
+{
+    EEPRO100State *s = (EEPRO100State *) opaque;
+    logout("%p\n", s);
+    static int first;
+    if (!first) {
+        first = 1;
+    }
+    nic_selective_reset(s);
+}
+
+#if defined(DEBUG_EEPRO100)
+static const char *reg[PCI_IO_SIZE / 4] = {
+    "Command/Status",
+    "General Pointer",
+    "Port",
+    "EEPROM/Flash Control",
+    "MDI Control",
+    "Receive DMA Byte Count",
+    "Flow control register",
+    "General Status/Control"
+};
+
+static char *regname(uint32_t addr)
+{
+    static char buf[16];
+    if (addr < PCI_IO_SIZE) {
+        const char *r = reg[addr / 4];
+        if (r != 0) {
+            sprintf(buf, "%s+%u", r, addr % 4);
+        } else {
+            sprintf(buf, "0x%02x", addr);
+        }
+    } else {
+        sprintf(buf, "??? 0x%08x", addr);
+    }
+    return buf;
+}
+#endif                          /* DEBUG_EEPRO100 */
+
+#if 0
+static uint16_t eepro100_read_status(EEPRO100State * s)
+{
+    uint16_t val = s->status;
+    logout("val=0x%04x\n", val);
+    return val;
+}
+
+static void eepro100_write_status(EEPRO100State * s, uint16_t val)
+{
+    logout("val=0x%04x\n", val);
+    s->status = val;
+}
+#endif
+
+/*****************************************************************************
+ *
+ * Command emulation.
+ *
+ ****************************************************************************/
+
+#if 0
+static uint16_t eepro100_read_command(EEPRO100State * s)
+{
+    uint16_t val = 0xffff;
+    //~ logout("val=0x%04x\n", val);
+    return val;
+}
+#endif
+
+/* Commands that can be put in a command list entry. */
+enum commands {
+    CmdNOp = 0,
+    CmdIASetup = 1,
+    CmdConfigure = 2,
+    CmdMulticastList = 3,
+    CmdTx = 4,
+    CmdTDR = 5,                 /* load microcode */
+    CmdDump = 6,
+    CmdDiagnose = 7,
+
+    /* And some extra flags: */
+    CmdSuspend = 0x4000,        /* Suspend after completion. */
+    CmdIntr = 0x2000,           /* Interrupt after completion. */
+    CmdTxFlex = 0x0008,         /* Use "Flexible mode" for CmdTx command. */
+};
+
+static cu_state_t get_cu_state(EEPRO100State * s)
+{
+    return ((s->mem[SCBStatus] >> 6) & 0x03);
+}
+
+static void set_cu_state(EEPRO100State * s, cu_state_t state)
+{
+    s->mem[SCBStatus] = (s->mem[SCBStatus] & 0x3f) + (state << 6);
+}
+
+static ru_state_t get_ru_state(EEPRO100State * s)
+{
+    return ((s->mem[SCBStatus] >> 2) & 0x0f);
+}
+
+static void set_ru_state(EEPRO100State * s, ru_state_t state)
+{
+    s->mem[SCBStatus] = (s->mem[SCBStatus] & 0xc3) + (state << 2);
+}
+
+static void dump_statistics(EEPRO100State * s)
+{
+    /* Dump statistical data. Most data is never changed by the emulation
+     * and always 0, so we first just copy the whole block and then those
+     * values which really matter.
+     * Number of data should check configuration!!!
+     */
+    cpu_physical_memory_write(s->statsaddr, (uint8_t *) & s->statistics, 64);
+    stl_phys(s->statsaddr + 0, s->statistics.tx_good_frames);
+    stl_phys(s->statsaddr + 36, s->statistics.rx_good_frames);
+    stl_phys(s->statsaddr + 48, s->statistics.rx_resource_errors);
+    stl_phys(s->statsaddr + 60, s->statistics.rx_short_frame_errors);
+    //~ stw_phys(s->statsaddr + 76, s->statistics.xmt_tco_frames);
+    //~ stw_phys(s->statsaddr + 78, s->statistics.rcv_tco_frames);
+    //~ missing("CU dump statistical counters");
+}
+
+static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
+{
+    eepro100_tx_t tx;
+    uint32_t cb_address;
+    switch (val) {
+    case CU_NOP:
+        /* No operation. */
+        break;
+    case CU_START:
+        if (get_cu_state(s) != cu_idle) {
+            /* Intel documentation says that CU must be idle for the CU
+             * start command. Intel driver for Linux also starts the CU
+             * from suspended state. */
+            logout("CU state is %u, should be %u\n", get_cu_state(s), cu_idle);
+            //~ assert(!"wrong CU state");
+        }
+        set_cu_state(s, cu_active);
+        s->cu_offset = s->pointer;
+      next_command:
+        cb_address = s->cu_base + s->cu_offset;
+        cpu_physical_memory_read(cb_address, (uint8_t *) & tx, sizeof(tx));
+        uint16_t status = le16_to_cpu(tx.status);
+        uint16_t command = le16_to_cpu(tx.command);
+        logout
+            ("val=0x%02x (cu start), status=0x%04x, command=0x%04x, link=0x%08x\n",
+             val, status, command, tx.link);
+        bool bit_el = ((command & 0x8000) != 0);
+        bool bit_s = ((command & 0x4000) != 0);
+        bool bit_i = ((command & 0x2000) != 0);
+        bool bit_nc = ((command & 0x0010) != 0);
+        //~ bool bit_sf = ((command & 0x0008) != 0);
+        uint16_t cmd = command & 0x0007;
+        s->cu_offset = le32_to_cpu(tx.link);
+        switch (cmd) {
+        case CmdNOp:
+            /* Do nothing. */
+            break;
+        case CmdIASetup:
+            cpu_physical_memory_read(cb_address + 8, &s->macaddr[0], 6);
+            logout("macaddr: %s\n", nic_dump(&s->macaddr[0], 6));
+            break;
+        case CmdConfigure:
+            cpu_physical_memory_read(cb_address + 8, &s->configuration[0],
+                                     sizeof(s->configuration));
+            logout("configuration: %s\n", nic_dump(&s->configuration[0], 16));
+            break;
+        case CmdMulticastList:
+            //~ missing("multicast list");
+            break;
+        case CmdTx:
+            (void)0;
+            uint32_t tbd_array = le32_to_cpu(tx.tx_desc_addr);
+            uint16_t tcb_bytes = (le16_to_cpu(tx.tcb_bytes) & 0x3fff);
+            logout
+                ("transmit, TBD array address 0x%08x, TCB byte count 0x%04x, TBD count %u\n",
+                 tbd_array, tcb_bytes, tx.tbd_count);
+            assert(!bit_nc);
+            //~ assert(!bit_sf);
+            assert(tcb_bytes <= 2600);
+            /* Next assertion fails for local configuration. */
+            //~ assert((tcb_bytes > 0) || (tbd_array != 0xffffffff));
+            if (!((tcb_bytes > 0) || (tbd_array != 0xffffffff))) {
+                logout
+                    ("illegal values of TBD array address and TCB byte count!\n");
+            }
+            uint8_t buf[MAX_ETH_FRAME_SIZE + 4];
+            uint16_t size = 0;
+            uint32_t tbd_address = cb_address + 0x10;
+            assert(tcb_bytes <= sizeof(buf));
+            while (size < tcb_bytes) {
+                uint32_t tx_buffer_address = ldl_phys(tbd_address);
+                uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
+                //~ uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
+                tbd_address += 8;
+                logout
+                    ("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n",
+                     tx_buffer_address, tx_buffer_size);
+                cpu_physical_memory_read(tx_buffer_address, &buf[size],
+                                         tx_buffer_size);
+                size += tx_buffer_size;
+            }
+            if (tbd_array == 0xffffffff) {
+                /* Simplified mode. Was already handled by code above. */
+            } else {
+                /* Flexible mode. */
+                uint8_t tbd_count = 0;
+                if (!(s->configuration[6] & BIT(4))) {
+                    /* Extended TCB. */
+                    assert(tcb_bytes == 0);
+                    for (; tbd_count < 2; tbd_count++) {
+                        uint32_t tx_buffer_address = ldl_phys(tbd_address);
+                        uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
+                        uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
+                        tbd_address += 8;
+                        logout
+                            ("TBD (extended mode): buffer address 0x%08x, size 0x%04x\n",
+                             tx_buffer_address, tx_buffer_size);
+                        cpu_physical_memory_read(tx_buffer_address, &buf[size],
+                                                 tx_buffer_size);
+                        size += tx_buffer_size;
+                        if (tx_buffer_el & 1) {
+                            break;
+                        }
+                    }
+                }
+                tbd_address = tbd_array;
+                for (; tbd_count < tx.tbd_count; tbd_count++) {
+                    uint32_t tx_buffer_address = ldl_phys(tbd_address);
+                    uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
+                    uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
+                    tbd_address += 8;
+                    logout
+                        ("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n",
+                         tx_buffer_address, tx_buffer_size);
+                    cpu_physical_memory_read(tx_buffer_address, &buf[size],
+                                             tx_buffer_size);
+                    size += tx_buffer_size;
+                    if (tx_buffer_el & 1) {
+                        break;
+                    }
+                }
+            }
+            qemu_send_packet(s->vc, buf, size);
+            s->statistics.tx_good_frames++;
+            /* Transmit with bad status would raise an CX/TNO interrupt.
+             * (82557 only). Emulation never has bad status. */
+            //~ eepro100_cx_interrupt(s);
+            break;
+        case CmdTDR:
+            logout("load microcode\n");
+            /* Starting with offset 8, the command contains
+             * 64 dwords microcode which we just ignore here. */
+            break;
+        default:
+            missing("undefined command");
+        }
+        /* Write new status (success). */
+        stw_phys(cb_address, status | 0x8000 | 0x2000);
+        if (bit_i) {
+            /* CU completed action. */
+            eepro100_cx_interrupt(s);
+        }
+        if (bit_el) {
+            /* CU becomes idle. */
+            set_cu_state(s, cu_idle);
+            eepro100_cna_interrupt(s);
+        } else if (bit_s) {
+            /* CU becomes suspended. */
+            set_cu_state(s, cu_suspended);
+            eepro100_cna_interrupt(s);
+        } else {
+            /* More entries in list. */
+            logout("CU list with at least one more entry\n");
+            goto next_command;
+        }
+        logout("CU list empty\n");
+        /* List is empty. Now CU is idle or suspended. */
+        break;
+    case CU_RESUME:
+        if (get_cu_state(s) != cu_suspended) {
+            logout("bad CU resume from CU state %u\n", get_cu_state(s));
+            /* Workaround for bad Linux eepro100 driver which resumes
+             * from idle state. */
+            //~ missing("cu resume");
+            set_cu_state(s, cu_suspended);
+        }
+        if (get_cu_state(s) == cu_suspended) {
+            logout("CU resuming\n");
+            set_cu_state(s, cu_active);
+            goto next_command;
+        }
+        break;
+    case CU_STATSADDR:
+        /* Load dump counters address. */
+        s->statsaddr = s->pointer;
+        logout("val=0x%02x (status address)\n", val);
+        break;
+    case CU_SHOWSTATS:
+        /* Dump statistical counters. */
+        dump_statistics(s);
+        break;
+    case CU_CMD_BASE:
+        /* Load CU base. */
+        logout("val=0x%02x (CU base address)\n", val);
+        s->cu_base = s->pointer;
+        break;
+    case CU_DUMPSTATS:
+        /* Dump and reset statistical counters. */
+        dump_statistics(s);
+        memset(&s->statistics, 0, sizeof(s->statistics));
+        break;
+    case CU_SRESUME:
+        /* CU static resume. */
+        missing("CU static resume");
+        break;
+    default:
+        missing("Undefined CU command");
+    }
+}
+
+static void eepro100_ru_command(EEPRO100State * s, uint8_t val)
+{
+    switch (val) {
+    case RU_NOP:
+        /* No operation. */
+        break;
+    case RX_START:
+        /* RU start. */
+        if (get_ru_state(s) != ru_idle) {
+            logout("RU state is %u, should be %u\n", get_ru_state(s), ru_idle);
+            //~ assert(!"wrong RU state");
+        }
+        set_ru_state(s, ru_ready);
+        s->ru_offset = s->pointer;
+        logout("val=0x%02x (rx start)\n", val);
+        break;
+    case RX_RESUME:
+        /* Restart RU. */
+        if (get_ru_state(s) != ru_suspended) {
+            logout("RU state is %u, should be %u\n", get_ru_state(s),
+                   ru_suspended);
+            //~ assert(!"wrong RU state");
+        }
+        set_ru_state(s, ru_ready);
+        break;
+    case RX_ADDR_LOAD:
+        /* Load RU base. */
+        logout("val=0x%02x (RU base address)\n", val);
+        s->ru_base = s->pointer;
+        break;
+    default:
+        logout("val=0x%02x (undefined RU command)\n", val);
+        missing("Undefined SU command");
+    }
+}
+
+static void eepro100_write_command(EEPRO100State * s, uint8_t val)
+{
+    eepro100_ru_command(s, val & 0x0f);
+    eepro100_cu_command(s, val & 0xf0);
+    if ((val) == 0) {
+        logout("val=0x%02x\n", val);
+    }
+    /* Clear command byte after command was accepted. */
+    s->mem[SCBCmd] = 0;
+}
+
+/*****************************************************************************
+ *
+ * EEPROM emulation.
+ *
+ ****************************************************************************/
+
+#define EEPROM_CS       0x02
+#define EEPROM_SK       0x01
+#define EEPROM_DI       0x04
+#define EEPROM_DO       0x08
+
+static uint16_t eepro100_read_eeprom(EEPRO100State * s)
+{
+    uint16_t val;
+    memcpy(&val, &s->mem[SCBeeprom], sizeof(val));
+    if (eeprom93xx_read(s->eeprom)) {
+        val |= EEPROM_DO;
+    } else {
+        val &= ~EEPROM_DO;
+    }
+    return val;
+}
+
+static void eepro100_write_eeprom(eeprom_t * eeprom, uint8_t val)
+{
+    logout("write val=0x%02x\n", val);
+
+    /* mask unwriteable bits */
+    //~ val = SET_MASKED(val, 0x31, eeprom->value);
+
+    int eecs = ((val & EEPROM_CS) != 0);
+    int eesk = ((val & EEPROM_SK) != 0);
+    int eedi = ((val & EEPROM_DI) != 0);
+    eeprom93xx_write(eeprom, eecs, eesk, eedi);
+}
+
+static void eepro100_write_pointer(EEPRO100State * s, uint32_t val)
+{
+    s->pointer = le32_to_cpu(val);
+    logout("val=0x%08x\n", val);
+}
+
+/*****************************************************************************
+ *
+ * MDI emulation.
+ *
+ ****************************************************************************/
+
+#if defined(DEBUG_EEPRO100)
+static const char *mdi_op_name[] = {
+    "opcode 0",
+    "write",
+    "read",
+    "opcode 3"
+};
+
+static const char *mdi_reg_name[] = {
+    "Control",
+    "Status",
+    "PHY Identification (Word 1)",
+    "PHY Identification (Word 2)",
+    "Auto-Negotiation Advertisement",
+    "Auto-Negotiation Link Partner Ability",
+    "Auto-Negotiation Expansion"
+};
+#endif                          /* DEBUG_EEPRO100 */
+
+static uint32_t eepro100_read_mdi(EEPRO100State * s)
+{
+    uint32_t val;
+    memcpy(&val, &s->mem[0x10], sizeof(val));
+
+#ifdef DEBUG_EEPRO100
+    uint8_t raiseint = (val & BIT(29)) >> 29;
+    uint8_t opcode = (val & BITS(27, 26)) >> 26;
+    uint8_t phy = (val & BITS(25, 21)) >> 21;
+    uint8_t reg = (val & BITS(20, 16)) >> 16;
+    uint16_t data = (val & BITS(15, 0));
+#endif
+    /* Emulation takes no time to finish MDI transaction. */
+    val |= BIT(28);
+    TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n",
+                      val, raiseint, mdi_op_name[opcode], phy,
+                      mdi_reg_name[reg], data));
+    return val;
+}
+
+//~ #define BITS(val, upper, lower) (val & ???)
+static void eepro100_write_mdi(EEPRO100State * s, uint32_t val)
+{
+    uint8_t raiseint = (val & BIT(29)) >> 29;
+    uint8_t opcode = (val & BITS(27, 26)) >> 26;
+    uint8_t phy = (val & BITS(25, 21)) >> 21;
+    uint8_t reg = (val & BITS(20, 16)) >> 16;
+    uint16_t data = (val & BITS(15, 0));
+    if (phy != 1) {
+        /* Unsupported PHY address. */
+        //~ logout("phy must be 1 but is %u\n", phy);
+        data = 0;
+    } else if (opcode != 1 && opcode != 2) {
+        /* Unsupported opcode. */
+        logout("opcode must be 1 or 2 but is %u\n", opcode);
+        data = 0;
+    } else if (reg > 6) {
+        /* Unsupported register. */
+        logout("register must be 0...6 but is %u\n", reg);
+        data = 0;
+    } else {
+        TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n",
+                          val, raiseint, mdi_op_name[opcode], phy,
+                          mdi_reg_name[reg], data));
+        if (opcode == 1) {
+            /* MDI write */
+            switch (reg) {
+            case 0:            /* Control Register */
+                if (data & 0x8000) {
+                    /* Reset status and control registers to default. */
+                    s->mdimem[0] = eepro100_mdi_default[0];
+                    s->mdimem[1] = eepro100_mdi_default[1];
+                    data = s->mdimem[reg];
+                } else {
+                    /* Restart Auto Configuration = Normal Operation */
+                    data &= ~0x0200;
+                }
+                break;
+            case 1:            /* Status Register */
+                missing("not writable");
+                data = s->mdimem[reg];
+                break;
+            case 2:            /* PHY Identification Register (Word 1) */
+            case 3:            /* PHY Identification Register (Word 2) */
+                missing("not implemented");
+                break;
+            case 4:            /* Auto-Negotiation Advertisement Register */
+            case 5:            /* Auto-Negotiation Link Partner Ability Register */
+                break;
+            case 6:            /* Auto-Negotiation Expansion Register */
+            default:
+                missing("not implemented");
+            }
+            s->mdimem[reg] = data;
+        } else if (opcode == 2) {
+            /* MDI read */
+            switch (reg) {
+            case 0:            /* Control Register */
+                if (data & 0x8000) {
+                    /* Reset status and control registers to default. */
+                    s->mdimem[0] = eepro100_mdi_default[0];
+                    s->mdimem[1] = eepro100_mdi_default[1];
+                }
+                break;
+            case 1:            /* Status Register */
+                s->mdimem[reg] |= 0x0020;
+                break;
+            case 2:            /* PHY Identification Register (Word 1) */
+            case 3:            /* PHY Identification Register (Word 2) */
+            case 4:            /* Auto-Negotiation Advertisement Register */
+                break;
+            case 5:            /* Auto-Negotiation Link Partner Ability Register */
+                s->mdimem[reg] = 0x41fe;
+                break;
+            case 6:            /* Auto-Negotiation Expansion Register */
+                s->mdimem[reg] = 0x0001;
+                break;
+            }
+            data = s->mdimem[reg];
+        }
+        /* Emulation takes no time to finish MDI transaction.
+         * Set MDI bit in SCB status register. */
+        s->mem[SCBAck] |= 0x08;
+        val |= BIT(28);
+        if (raiseint) {
+            eepro100_mdi_interrupt(s);
+        }
+    }
+    val = (val & 0xffff0000) + data;
+    memcpy(&s->mem[0x10], &val, sizeof(val));
+}
+
+/*****************************************************************************
+ *
+ * Port emulation.
+ *
+ ****************************************************************************/
+
+#define PORT_SOFTWARE_RESET     0
+#define PORT_SELFTEST           1
+#define PORT_SELECTIVE_RESET    2
+#define PORT_DUMP               3
+#define PORT_SELECTION_MASK     3
+
+typedef struct {
+    uint32_t st_sign;           /* Self Test Signature */
+    uint32_t st_result;         /* Self Test Results */
+} eepro100_selftest_t;
+
+static uint32_t eepro100_read_port(EEPRO100State * s)
+{
+    return 0;
+}
+
+static void eepro100_write_port(EEPRO100State * s, uint32_t val)
+{
+    val = le32_to_cpu(val);
+    uint32_t address = (val & ~PORT_SELECTION_MASK);
+    uint8_t selection = (val & PORT_SELECTION_MASK);
+    switch (selection) {
+    case PORT_SOFTWARE_RESET:
+        nic_reset(s);
+        break;
+    case PORT_SELFTEST:
+        logout("selftest address=0x%08x\n", address);
+        eepro100_selftest_t data;
+        cpu_physical_memory_read(address, (uint8_t *) & data, sizeof(data));
+        data.st_sign = 0xffffffff;
+        data.st_result = 0;
+        cpu_physical_memory_write(address, (uint8_t *) & data, sizeof(data));
+        break;
+    case PORT_SELECTIVE_RESET:
+        logout("selective reset, selftest address=0x%08x\n", address);
+        nic_selective_reset(s);
+        break;
+    default:
+        logout("val=0x%08x\n", val);
+        missing("unknown port selection");
+    }
+}
+
+/*****************************************************************************
+ *
+ * General hardware emulation.
+ *
+ ****************************************************************************/
+
+static uint8_t eepro100_read1(EEPRO100State * s, uint32_t addr)
+{
+    uint8_t val;
+    if (addr <= sizeof(s->mem) - sizeof(val)) {
+        memcpy(&val, &s->mem[addr], sizeof(val));
+    }
+
+    switch (addr) {
+    case SCBStatus:
+        //~ val = eepro100_read_status(s);
+        logout("addr=%s val=0x%02x\n", regname(addr), val);
+        break;
+    case SCBAck:
+        //~ val = eepro100_read_status(s);
+        logout("addr=%s val=0x%02x\n", regname(addr), val);
+        break;
+    case SCBCmd:
+        logout("addr=%s val=0x%02x\n", regname(addr), val);
+        //~ val = eepro100_read_command(s);
+        break;
+    case SCBIntmask:
+        logout("addr=%s val=0x%02x\n", regname(addr), val);
+        break;
+    case SCBPort + 3:
+        logout("addr=%s val=0x%02x\n", regname(addr), val);
+        break;
+    case SCBeeprom:
+        val = eepro100_read_eeprom(s);
+        break;
+    case 0x1b:                 /* PMDR (power management driver register) */
+        val = 0;
+        logout("addr=%s val=0x%02x\n", regname(addr), val);
+        break;
+    case 0x1d:                 /* general status register */
+        /* 100 Mbps full duplex, valid link */
+        val = 0x07;
+        logout("addr=General Status val=%02x\n", val);
+        break;
+    default:
+        logout("addr=%s val=0x%02x\n", regname(addr), val);
+        missing("unknown byte read");
+    }
+    return val;
+}
+
+static uint16_t eepro100_read2(EEPRO100State * s, uint32_t addr)
+{
+    uint16_t val;
+    if (addr <= sizeof(s->mem) - sizeof(val)) {
+        memcpy(&val, &s->mem[addr], sizeof(val));
+    }
+
+    logout("addr=%s val=0x%04x\n", regname(addr), val);
+
+    switch (addr) {
+    case SCBStatus:
+        //~ val = eepro100_read_status(s);
+        break;
+    case SCBeeprom:
+        val = eepro100_read_eeprom(s);
+        break;
+    default:
+        logout("addr=%s val=0x%04x\n", regname(addr), val);
+        missing("unknown word read");
+    }
+    return val;
+}
+
+static uint32_t eepro100_read4(EEPRO100State * s, uint32_t addr)
+{
+    uint32_t val;
+    if (addr <= sizeof(s->mem) - sizeof(val)) {
+        memcpy(&val, &s->mem[addr], sizeof(val));
+    }
+
+    switch (addr) {
+    case SCBStatus:
+        //~ val = eepro100_read_status(s);
+        logout("addr=%s val=0x%08x\n", regname(addr), val);
+        break;
+    case SCBPointer:
+        //~ val = eepro100_read_pointer(s);
+        logout("addr=%s val=0x%08x\n", regname(addr), val);
+        break;
+    case SCBPort:
+        val = eepro100_read_port(s);
+        logout("addr=%s val=0x%08x\n", regname(addr), val);
+        break;
+    case SCBCtrlMDI:
+        val = eepro100_read_mdi(s);
+        break;
+    default:
+        logout("addr=%s val=0x%08x\n", regname(addr), val);
+        missing("unknown longword read");
+    }
+    return val;
+}
+
+static void eepro100_write1(EEPRO100State * s, uint32_t addr, uint8_t val)
+{
+    if (addr <= sizeof(s->mem) - sizeof(val)) {
+        memcpy(&s->mem[addr], &val, sizeof(val));
+    }
+
+    logout("addr=%s val=0x%02x\n", regname(addr), val);
+
+    switch (addr) {
+    case SCBStatus:
+        //~ eepro100_write_status(s, val);
+        break;
+    case SCBAck:
+        eepro100_acknowledge(s);
+        break;
+    case SCBCmd:
+        eepro100_write_command(s, val);
+        break;
+    case SCBIntmask:
+        if (val & BIT(1)) {
+            eepro100_swi_interrupt(s);
+        }
+        eepro100_interrupt(s, 0);
+        break;
+    case SCBPort + 3:
+        logout("addr=%s val=0x%02x\n", regname(addr), val);
+        break;
+    case SCBeeprom:
+        eepro100_write_eeprom(s->eeprom, val);
+        break;
+    default:
+        logout("addr=%s val=0x%02x\n", regname(addr), val);
+        missing("unknown byte write");
+    }
+}
+
+static void eepro100_write2(EEPRO100State * s, uint32_t addr, uint16_t val)
+{
+    if (addr <= sizeof(s->mem) - sizeof(val)) {
+        memcpy(&s->mem[addr], &val, sizeof(val));
+    }
+
+    logout("addr=%s val=0x%04x\n", regname(addr), val);
+
+    switch (addr) {
+    case SCBStatus:
+        //~ eepro100_write_status(s, val);
+        eepro100_acknowledge(s);
+        break;
+    case SCBCmd:
+        eepro100_write_command(s, val);
+        eepro100_write1(s, SCBIntmask, val >> 8);
+        break;
+    case SCBeeprom:
+        eepro100_write_eeprom(s->eeprom, val);
+        break;
+    default:
+        logout("addr=%s val=0x%04x\n", regname(addr), val);
+        missing("unknown word write");
+    }
+}
+
+static void eepro100_write4(EEPRO100State * s, uint32_t addr, uint32_t val)
+{
+    if (addr <= sizeof(s->mem) - sizeof(val)) {
+        memcpy(&s->mem[addr], &val, sizeof(val));
+    }
+
+    switch (addr) {
+    case SCBPointer:
+        eepro100_write_pointer(s, val);
+        break;
+    case SCBPort:
+        logout("addr=%s val=0x%08x\n", regname(addr), val);
+        eepro100_write_port(s, val);
+        break;
+    case SCBCtrlMDI:
+        eepro100_write_mdi(s, val);
+        break;
+    default:
+        logout("addr=%s val=0x%08x\n", regname(addr), val);
+        missing("unknown longword write");
+    }
+}
+
+static uint32_t ioport_read1(void *opaque, uint32_t addr)
+{
+    EEPRO100State *s = opaque;
+    //~ logout("addr=%s\n", regname(addr));
+    return eepro100_read1(s, addr - s->region[1]);
+}
+
+static uint32_t ioport_read2(void *opaque, uint32_t addr)
+{
+    EEPRO100State *s = opaque;
+    return eepro100_read2(s, addr - s->region[1]);
+}
+
+static uint32_t ioport_read4(void *opaque, uint32_t addr)
+{
+    EEPRO100State *s = opaque;
+    return eepro100_read4(s, addr - s->region[1]);
+}
+
+static void ioport_write1(void *opaque, uint32_t addr, uint32_t val)
+{
+    EEPRO100State *s = opaque;
+    //~ logout("addr=%s val=0x%02x\n", regname(addr), val);
+    eepro100_write1(s, addr - s->region[1], val);
+}
+
+static void ioport_write2(void *opaque, uint32_t addr, uint32_t val)
+{
+    EEPRO100State *s = opaque;
+    eepro100_write2(s, addr - s->region[1], val);
+}
+
+static void ioport_write4(void *opaque, uint32_t addr, uint32_t val)
+{
+    EEPRO100State *s = opaque;
+    eepro100_write4(s, addr - s->region[1], val);
+}
+
+/***********************************************************/
+/* PCI EEPRO100 definitions */
+
+typedef struct PCIEEPRO100State {
+    PCIDevice dev;
+    EEPRO100State eepro100;
+} PCIEEPRO100State;
+
+static void pci_map(PCIDevice * pci_dev, int region_num,
+                    uint32_t addr, uint32_t size, int type)
+{
+    PCIEEPRO100State *d = (PCIEEPRO100State *) pci_dev;
+    EEPRO100State *s = &d->eepro100;
+
+    logout("region %d, addr=0x%08x, size=0x%08x, type=%d\n",
+           region_num, addr, size, type);
+
+    assert(region_num == 1);
+    register_ioport_write(addr, size, 1, ioport_write1, s);
+    register_ioport_read(addr, size, 1, ioport_read1, s);
+    register_ioport_write(addr, size, 2, ioport_write2, s);
+    register_ioport_read(addr, size, 2, ioport_read2, s);
+    register_ioport_write(addr, size, 4, ioport_write4, s);
+    register_ioport_read(addr, size, 4, ioport_read4, s);
+
+    s->region[region_num] = addr;
+}
+
+static void pci_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    EEPRO100State *s = opaque;
+    addr -= s->region[0];
+    //~ logout("addr=%s val=0x%02x\n", regname(addr), val);
+    eepro100_write1(s, addr, val);
+}
+
+static void pci_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    EEPRO100State *s = opaque;
+    addr -= s->region[0];
+    //~ logout("addr=%s val=0x%02x\n", regname(addr), val);
+    eepro100_write2(s, addr, val);
+}
+
+static void pci_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    EEPRO100State *s = opaque;
+    addr -= s->region[0];
+    //~ logout("addr=%s val=0x%02x\n", regname(addr), val);
+    eepro100_write4(s, addr, val);
+}
+
+static uint32_t pci_mmio_readb(void *opaque, target_phys_addr_t addr)
+{
+    EEPRO100State *s = opaque;
+    addr -= s->region[0];
+    //~ logout("addr=%s\n", regname(addr));
+    return eepro100_read1(s, addr);
+}
+
+static uint32_t pci_mmio_readw(void *opaque, target_phys_addr_t addr)
+{
+    EEPRO100State *s = opaque;
+    addr -= s->region[0];
+    //~ logout("addr=%s\n", regname(addr));
+    return eepro100_read2(s, addr);
+}
+
+static uint32_t pci_mmio_readl(void *opaque, target_phys_addr_t addr)
+{
+    EEPRO100State *s = opaque;
+    addr -= s->region[0];
+    //~ logout("addr=%s\n", regname(addr));
+    return eepro100_read4(s, addr);
+}
+
+static CPUWriteMemoryFunc *pci_mmio_write[] = {
+    pci_mmio_writeb,
+    pci_mmio_writew,
+    pci_mmio_writel
+};
+
+static CPUReadMemoryFunc *pci_mmio_read[] = {
+    pci_mmio_readb,
+    pci_mmio_readw,
+    pci_mmio_readl
+};
+
+static void pci_mmio_map(PCIDevice * pci_dev, int region_num,
+                         uint32_t addr, uint32_t size, int type)
+{
+    PCIEEPRO100State *d = (PCIEEPRO100State *) pci_dev;
+
+    logout("region %d, addr=0x%08x, size=0x%08x, type=%d\n",
+           region_num, addr, size, type);
+
+    if (region_num == 0) {
+        /* Map control / status registers. */
+        cpu_register_physical_memory(addr, size, d->eepro100.mmio_index);
+        d->eepro100.region[region_num] = addr;
+    }
+}
+
+static int nic_can_receive(void *opaque)
+{
+    EEPRO100State *s = opaque;
+    logout("%p\n", s);
+    return get_ru_state(s) == ru_ready;
+    //~ return !eepro100_buffer_full(s);
+}
+
+#define MIN_BUF_SIZE 60
+
+static void nic_receive(void *opaque, const uint8_t * buf, int size)
+{
+    /* TODO:
+     * - Magic packets should set bit 30 in power management driver register.
+     * - Interesting packets should set bit 29 in power management driver register.
+     */
+    EEPRO100State *s = opaque;
+    uint16_t rfd_status = 0xa000;
+    static const uint8_t broadcast_macaddr[6] =
+        { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+    /* TODO: check multiple IA bit. */
+    assert(!(s->configuration[20] & BIT(6)));
+
+    if (s->configuration[8] & 0x80) {
+        /* CSMA is disabled. */
+        logout("%p received while CSMA is disabled\n", s);
+        return;
+    } else if (size < 64 && (s->configuration[7] & 1)) {
+        /* Short frame and configuration byte 7/0 (discard short receive) set:
+         * Short frame is discarded */
+        logout("%p received short frame (%d byte)\n", s, size);
+        s->statistics.rx_short_frame_errors++;
+        //~ return;
+    } else if ((size > MAX_ETH_FRAME_SIZE + 4) && !(s->configuration[18] & 8)) {
+        /* Long frame and configuration byte 18/3 (long receive ok) not set:
+         * Long frames are discarded. */
+        logout("%p received long frame (%d byte), ignored\n", s, size);
+        return;
+    } else if (memcmp(buf, s->macaddr, 6) == 0) {       // !!!
+        /* Frame matches individual address. */
+        /* TODO: check configuration byte 15/4 (ignore U/L). */
+        logout("%p received frame for me, len=%d\n", s, size);
+    } else if (memcmp(buf, broadcast_macaddr, 6) == 0) {
+        /* Broadcast frame. */
+        logout("%p received broadcast, len=%d\n", s, size);
+        rfd_status |= 0x0002;
+    } else if (buf[0] & 0x01) { // !!!
+        /* Multicast frame. */
+        logout("%p received multicast, len=%d\n", s, size);
+        /* TODO: check multicast all bit. */
+        assert(!(s->configuration[21] & BIT(3)));
+        int mcast_idx = compute_mcast_idx(buf);
+        if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))) {
+            return;
+        }
+        rfd_status |= 0x0002;
+    } else if (s->configuration[15] & 1) {
+        /* Promiscuous: receive all. */
+        logout("%p received frame in promiscuous mode, len=%d\n", s, size);
+        rfd_status |= 0x0004;
+    } else {
+        logout("%p received frame, ignored, len=%d,%s\n", s, size,
+               nic_dump(buf, size));
+        return;
+    }
+
+    if (get_ru_state(s) != ru_ready) {
+        /* No ressources available. */
+        logout("no ressources, state=%u\n", get_ru_state(s));
+        s->statistics.rx_resource_errors++;
+        //~ assert(!"no ressources");
+        return;
+    }
+    //~ !!!
+//~ $3 = {status = 0x0, command = 0xc000, link = 0x2d220, rx_buf_addr = 0x207dc, count = 0x0, size = 0x5f8, packet = {0x0 <repeats 1518 times>}}
+    eepro100_rx_t rx;
+    cpu_physical_memory_read(s->ru_base + s->ru_offset, (uint8_t *) & rx,
+                             offsetof(eepro100_rx_t, packet));
+    uint16_t rfd_command = le16_to_cpu(rx.command);
+    uint16_t rfd_size = le16_to_cpu(rx.size);
+    assert(size <= rfd_size);
+    if (size < 64) {
+        rfd_status |= 0x0080;
+    }
+    logout("command 0x%04x, link 0x%08x, addr 0x%08x, size %u\n", rfd_command,
+           rx.link, rx.rx_buf_addr, rfd_size);
+    stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, status),
+             rfd_status);
+    stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, count), size);
+    /* Early receive interrupt not supported. */
+    //~ eepro100_er_interrupt(s);
+    /* Receive CRC Transfer not supported. */
+    assert(!(s->configuration[18] & 4));
+    /* TODO: check stripping enable bit. */
+    //~ assert(!(s->configuration[17] & 1));
+    cpu_physical_memory_write(s->ru_base + s->ru_offset +
+                              offsetof(eepro100_rx_t, packet), buf, size);
+    s->statistics.rx_good_frames++;
+    eepro100_fr_interrupt(s);
+    s->ru_offset = le32_to_cpu(rx.link);
+    if (rfd_command & 0x8000) {
+        /* EL bit is set, so this was the last frame. */
+        assert(0);
+    }
+    if (rfd_command & 0x4000) {
+        /* S bit is set. */
+        set_ru_state(s, ru_suspended);
+    }
+}
+
+static int nic_load(QEMUFile * f, void *opaque, int version_id)
+{
+    EEPRO100State *s = (EEPRO100State *) opaque;
+    int ret;
+
+    missing("NIC load");
+
+    if (version_id > 3)
+        return -EINVAL;
+
+    if (s->pci_dev && version_id >= 3) {
+        ret = pci_device_load(s->pci_dev, f);
+        if (ret < 0)
+            return ret;
+    }
+
+    if (version_id >= 2) {
+        qemu_get_8s(f, &s->rxcr);
+    } else {
+        s->rxcr = 0x0c;
+    }
+
+    qemu_get_8s(f, &s->cmd);
+    qemu_get_be32s(f, &s->start);
+    qemu_get_be32s(f, &s->stop);
+    qemu_get_8s(f, &s->boundary);
+    qemu_get_8s(f, &s->tsr);
+    qemu_get_8s(f, &s->tpsr);
+    qemu_get_be16s(f, &s->tcnt);
+    qemu_get_be16s(f, &s->rcnt);
+    qemu_get_be32s(f, &s->rsar);
+    qemu_get_8s(f, &s->rsr);
+    qemu_get_8s(f, &s->isr);
+    qemu_get_8s(f, &s->dcfg);
+    qemu_get_8s(f, &s->imr);
+    qemu_get_buffer(f, s->phys, 6);
+    qemu_get_8s(f, &s->curpag);
+    qemu_get_buffer(f, s->mult, 8);
+    qemu_get_buffer(f, s->mem, sizeof(s->mem));
+
+    return 0;
+}
+
+static void nic_save(QEMUFile * f, void *opaque)
+{
+    EEPRO100State *s = (EEPRO100State *) opaque;
+
+    missing("NIC save");
+
+    if (s->pci_dev)
+        pci_device_save(s->pci_dev, f);
+
+    qemu_put_8s(f, &s->rxcr);
+
+    qemu_put_8s(f, &s->cmd);
+    qemu_put_be32s(f, &s->start);
+    qemu_put_be32s(f, &s->stop);
+    qemu_put_8s(f, &s->boundary);
+    qemu_put_8s(f, &s->tsr);
+    qemu_put_8s(f, &s->tpsr);
+    qemu_put_be16s(f, &s->tcnt);
+    qemu_put_be16s(f, &s->rcnt);
+    qemu_put_be32s(f, &s->rsar);
+    qemu_put_8s(f, &s->rsr);
+    qemu_put_8s(f, &s->isr);
+    qemu_put_8s(f, &s->dcfg);
+    qemu_put_8s(f, &s->imr);
+    qemu_put_buffer(f, s->phys, 6);
+    qemu_put_8s(f, &s->curpag);
+    qemu_put_buffer(f, s->mult, 8);
+    qemu_put_buffer(f, s->mem, sizeof(s->mem));
+}
+
+static void nic_init(PCIBus * bus, NICInfo * nd,
+                     const char *name, uint32_t device)
+{
+    PCIEEPRO100State *d;
+    EEPRO100State *s;
+
+    logout("\n");
+
+    d = (PCIEEPRO100State *) pci_register_device(bus, name,
+                                                 sizeof(PCIEEPRO100State), -1,
+                                                 NULL, NULL);
+
+    s = &d->eepro100;
+    s->device = device;
+    s->pci_dev = &d->dev;
+
+    pci_reset(s);
+
+    /* Add 64 * 2 EEPROM. i82557 and i82558 support a 64 word EEPROM,
+     * i82559 and later support 64 or 256 word EEPROM. */
+    s->eeprom = eeprom93xx_new(EEPROM_SIZE);
+
+    /* Handler for memory-mapped I/O */
+    d->eepro100.mmio_index =
+        cpu_register_io_memory(0, pci_mmio_read, pci_mmio_write, s);
+
+    pci_register_io_region(&d->dev, 0, PCI_MEM_SIZE,
+                           PCI_ADDRESS_SPACE_MEM |
+                           PCI_ADDRESS_SPACE_MEM_PREFETCH, pci_mmio_map);
+    pci_register_io_region(&d->dev, 1, PCI_IO_SIZE, PCI_ADDRESS_SPACE_IO,
+                           pci_map);
+    pci_register_io_region(&d->dev, 2, PCI_FLASH_SIZE, PCI_ADDRESS_SPACE_MEM,
+                           pci_mmio_map);
+
+    memcpy(s->macaddr, nd->macaddr, 6);
+    logout("macaddr: %s\n", nic_dump(&s->macaddr[0], 6));
+    assert(s->region[1] == 0);
+
+    nic_reset(s);
+
+    s->vc = qemu_new_vlan_client(nd->vlan, nic_receive, nic_can_receive, s);
+
+    snprintf(s->vc->info_str, sizeof(s->vc->info_str),
+             "eepro100 pci macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
+             s->macaddr[0],
+             s->macaddr[1],
+             s->macaddr[2], s->macaddr[3], s->macaddr[4], s->macaddr[5]);
+
+    qemu_register_reset(nic_reset, s);
+
+    /* XXX: instance number ? */
+    register_savevm(name, 0, 3, nic_save, nic_load, s);
+}
+
+void pci_i82551_init(PCIBus * bus, NICInfo * nd, int devfn)
+{
+    nic_init(bus, nd, "i82551", i82551);
+    //~ uint8_t *pci_conf = d->dev.config;
+}
+
+void pci_i82557b_init(PCIBus * bus, NICInfo * nd, int devfn)
+{
+    nic_init(bus, nd, "i82557b", i82557B);
+}
+
+void pci_i82559er_init(PCIBus * bus, NICInfo * nd, int devfn)
+{
+    nic_init(bus, nd, "i82559er", i82559ER);
+}
+
+/* eof */

Added: trunk/src/host/qemu-neo1973/hw/eeprom93xx.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/eeprom93xx.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/eeprom93xx.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,312 @@
+/*
+ * QEMU EEPROM 93xx emulation
+ *
+ * Copyright (c) 2006-2007 Stefan Weil
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/* Emulation for serial EEPROMs:
+ * NMC93C06 256-Bit (16 x 16)
+ * NMC93C46 1024-Bit (64 x 16)
+ * NMC93C56 2028 Bit (128 x 16)
+ * NMC93C66 4096 Bit (256 x 16)
+ * Compatible devices include FM93C46 and others.
+ *
+ * Other drivers use these interface functions:
+ * eeprom93xx_new   - add a new EEPROM (with 16, 64 or 256 words)
+ * eeprom93xx_free  - destroy EEPROM
+ * eeprom93xx_read  - read data from the EEPROM
+ * eeprom93xx_write - write data to the EEPROM
+ * eeprom93xx_data  - get EEPROM data array for external manipulation
+ *
+ * Todo list:
+ * - No emulation of EEPROM timings.
+ */
+
+#include <assert.h>
+#include "eeprom93xx.h"
+
+/* Debug EEPROM emulation. */
+//~ #define DEBUG_EEPROM
+
+#ifdef DEBUG_EEPROM
+#define logout(fmt, args...) fprintf(stderr, "EEPROM\t%-24s" fmt, __func__, ##args)
+#else
+#define logout(fmt, args...) ((void)0)
+#endif
+
+static int eeprom_instance = 0;
+static const int eeprom_version = 20061112;
+
+#if 0
+typedef enum {
+  eeprom_read  = 0x80,   /* read register xx */
+  eeprom_write = 0x40,   /* write register xx */
+  eeprom_erase = 0xc0,   /* erase register xx */
+  eeprom_ewen  = 0x30,   /* erase / write enable */
+  eeprom_ewds  = 0x00,   /* erase / write disable */
+  eeprom_eral  = 0x20,   /* erase all registers */
+  eeprom_wral  = 0x10,   /* write all registers */
+  eeprom_amask = 0x0f,
+  eeprom_imask = 0xf0
+} eeprom_instruction_t;
+#endif
+
+#ifdef DEBUG_EEPROM
+static const char *opstring[] = {
+  "extended", "write", "read", "erase"
+};
+#endif
+
+struct _eeprom_t {
+    uint8_t  tick;
+    uint8_t  address;
+    uint8_t  command;
+    uint8_t  writeable;
+
+    uint8_t eecs;
+    uint8_t eesk;
+    uint8_t eedo;
+
+    uint8_t  addrbits;
+    uint8_t  size;
+    uint16_t data;
+    uint16_t contents[0];
+};
+
+/* Code for saving and restoring of EEPROM state. */
+
+static void eeprom_save(QEMUFile *f, void *opaque)
+{
+    /* Save EEPROM data. */
+    unsigned address;
+    eeprom_t *eeprom = (eeprom_t *)opaque;
+    qemu_put_buffer(f, (uint8_t *)eeprom, sizeof(*eeprom) - 2);
+    qemu_put_be16(f, eeprom->data);
+    for (address = 0; address < eeprom->size; address++) {
+        qemu_put_be16(f, eeprom->contents[address]);
+    }
+}
+
+static int eeprom_load(QEMUFile *f, void *opaque, int version_id)
+{
+    /* Load EEPROM data from saved data if version and EEPROM size
+       of data and current EEPROM are identical. */
+    eeprom_t *eeprom = (eeprom_t *)opaque;
+    int result = -EINVAL;
+    if (version_id == eeprom_version) {
+        unsigned address;
+        uint8_t size = eeprom->size;
+        qemu_get_buffer(f, (uint8_t *)eeprom, sizeof(*eeprom) - 2);
+        if (eeprom->size == size) {
+            eeprom->data = qemu_get_be16(f);
+            for (address = 0; address < eeprom->size; address++) {
+                eeprom->contents[address] = qemu_get_be16(f);
+            }
+            result = 0;
+        }
+    }
+    return result;
+}
+
+void eeprom93xx_write(eeprom_t *eeprom, int eecs, int eesk, int eedi)
+{
+    uint8_t tick = eeprom->tick;
+    uint8_t eedo = eeprom->eedo;
+    uint16_t address = eeprom->address;
+    uint8_t command = eeprom->command;
+
+    logout("CS=%u SK=%u DI=%u DO=%u, tick = %u\n",
+           eecs, eesk, eedi, eedo, tick);
+
+    if (! eeprom->eecs && eecs) {
+        /* Start chip select cycle. */
+        logout("Cycle start, waiting for 1st start bit (0)\n");
+        tick = 0;
+        command = 0x0;
+        address = 0x0;
+    } else if (eeprom->eecs && ! eecs) {
+        /* End chip select cycle. This triggers write / erase. */
+        if (eeprom->writeable) {
+            uint8_t subcommand = address >> (eeprom->addrbits - 2);
+            if (command == 0 && subcommand == 2) {
+                /* Erase all. */
+                for (address = 0; address < eeprom->size; address++) {
+                    eeprom->contents[address] = 0xffff;
+                }
+            } else if (command == 3) {
+                /* Erase word. */
+                eeprom->contents[address] = 0xffff;
+            } else if (tick >= 2 + 2 + eeprom->addrbits + 16) {
+                if (command == 1) {
+                    /* Write word. */
+                    eeprom->contents[address] &= eeprom->data;
+                } else if (command == 0 && subcommand == 1) {
+                    /* Write all. */
+                    for (address = 0; address < eeprom->size; address++) {
+                        eeprom->contents[address] &= eeprom->data;
+                    }
+                }
+            }
+        }
+        /* Output DO is tristate, read results in 1. */
+        eedo = 1;
+    } else if (eecs && ! eeprom->eesk && eesk) {
+        /* Raising edge of clock shifts data in. */
+        if (tick == 0) {
+            /* Wait for 1st start bit. */
+            if (eedi == 0) {
+                logout("Got correct 1st start bit, waiting for 2nd start bit (1)\n");
+                tick++;
+            } else {
+                logout("wrong 1st start bit (is 1, should be 0)\n");
+                tick = 2;
+                //~ assert(!"wrong start bit");
+            }
+        } else if (tick == 1) {
+            /* Wait for 2nd start bit. */
+            if (eedi != 0) {
+                logout("Got correct 2nd start bit, getting command + address\n");
+                tick++;
+            } else {
+                logout("1st start bit is longer than needed\n");
+            }
+        } else if (tick < 2 + 2) {
+            /* Got 2 start bits, transfer 2 opcode bits. */
+            tick++;
+            command <<= 1;
+            if (eedi) {
+                command += 1;
+            }
+        } else if (tick < 2 + 2 + eeprom->addrbits) {
+            /* Got 2 start bits and 2 opcode bits, transfer all address bits. */
+            tick++;
+            address = ((address << 1) | eedi);
+            if (tick == 2 + 2 + eeprom->addrbits) {
+                logout("%s command, address = 0x%02x (value 0x%04x)\n",
+                       opstring[command], address, eeprom->contents[address]);
+                if (command == 2) {
+                    eedo = 0;
+                }
+                address = address % eeprom->size;
+                if (command == 0) {
+                    /* Command code in upper 2 bits of address. */
+                    switch (address >> (eeprom->addrbits - 2)) {
+                        case 0:
+                            logout("write disable command\n");
+                            eeprom->writeable = 0;
+                            break;
+                        case 1:
+                            logout("write all command\n");
+                            break;
+                        case 2:
+                            logout("erase all command\n");
+                            break;
+                        case 3:
+                            logout("write enable command\n");
+                            eeprom->writeable = 1;
+                            break;
+                    }
+                } else {
+                    /* Read, write or erase word. */
+                    eeprom->data = eeprom->contents[address];
+                }
+            }
+        } else if (tick < 2 + 2 + eeprom->addrbits + 16) {
+            /* Transfer 16 data bits. */
+            tick++;
+            if (command == 2) {
+                /* Read word. */
+                eedo = ((eeprom->data & 0x8000) != 0);
+            }
+            eeprom->data <<= 1;
+            eeprom->data += eedi;
+        } else {
+            logout("additional unneeded tick, not processed\n");
+        }
+    }
+    /* Save status of EEPROM. */
+    eeprom->tick = tick;
+    eeprom->eecs = eecs;
+    eeprom->eesk = eesk;
+    eeprom->eedo = eedo;
+    eeprom->address = address;
+    eeprom->command = command;
+}
+
+uint16_t eeprom93xx_read(eeprom_t *eeprom)
+{
+    /* Return status of pin DO (0 or 1). */
+    logout("CS=%u DO=%u\n", eeprom->eecs, eeprom->eedo);
+    return (eeprom->eedo);
+}
+
+#if 0
+void eeprom93xx_reset(eeprom_t *eeprom)
+{
+    /* prepare eeprom */
+    logout("eeprom = 0x%p\n", eeprom);
+    eeprom->tick = 0;
+    eeprom->command = 0;
+}
+#endif
+
+eeprom_t *eeprom93xx_new(uint16_t nwords)
+{
+    /* Add a new EEPROM (with 16, 64 or 256 words). */
+    eeprom_t *eeprom;
+    uint8_t addrbits;
+
+    switch (nwords) {
+        case 16:
+        case 64:
+            addrbits = 6;
+            break;
+        case 128:
+        case 256:
+            addrbits = 8;
+            break;
+        default:
+            assert(!"Unsupported EEPROM size, fallback to 64 words!");
+            nwords = 64;
+            addrbits = 6;
+    }
+
+    eeprom = (eeprom_t *)qemu_mallocz(sizeof(*eeprom) + nwords * 2);
+    eeprom->size = nwords;
+    eeprom->addrbits = addrbits;
+    /* Output DO is tristate, read results in 1. */
+    eeprom->eedo = 1;
+    logout("eeprom = 0x%p, nwords = %u\n", eeprom, nwords);
+    register_savevm("eeprom", eeprom_instance, eeprom_version,
+                    eeprom_save, eeprom_load, eeprom);
+    return eeprom;
+}
+
+void eeprom93xx_free(eeprom_t *eeprom)
+{
+    /* Destroy EEPROM. */
+    logout("eeprom = 0x%p\n", eeprom);
+    qemu_free(eeprom);
+}
+
+uint16_t *eeprom93xx_data(eeprom_t *eeprom)
+{
+    /* Get EEPROM data array. */
+    return &eeprom->contents[0];
+}
+
+/* eof */

Added: trunk/src/host/qemu-neo1973/hw/eeprom93xx.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/eeprom93xx.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/eeprom93xx.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,43 @@
+/*
+ * QEMU EEPROM 93xx emulation
+ *
+ * Copyright (c) 2006-2007 Stefan Weil
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef EEPROM93XX_H
+#define EEPROM93XX_H
+
+#include "vl.h"
+
+typedef struct _eeprom_t eeprom_t;
+
+/* Create a new EEPROM with (nwords * 2) bytes. */
+eeprom_t *eeprom93xx_new(uint16_t nwords);
+
+/* Destroy an existing EEPROM. */
+void eeprom93xx_free(eeprom_t *eeprom);
+
+/* Read from the EEPROM. */
+uint16_t eeprom93xx_read(eeprom_t *eeprom);
+
+/* Write to the EEPROM. */
+void eeprom93xx_write(eeprom_t *eeprom, int eecs, int eesk, int eedi);
+
+/* Get EEPROM data array. */
+uint16_t *eeprom93xx_data(eeprom_t *eeprom);
+
+#endif /* EEPROM93XX_H */

Modified: trunk/src/host/qemu-neo1973/hw/es1370.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/es1370.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/es1370.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -324,7 +324,7 @@
     else {
         s->status = new_status & ~STAT_INTR;
     }
-    pci_set_irq (s->pci_dev, 0, !!level);
+    qemu_set_irq(s->pci_dev->irq[0], !!level);
 }
 
 static void es1370_reset (ES1370State *s)
@@ -350,7 +350,7 @@
             s->dac_voice[i] = NULL;
         }
     }
-    pci_set_irq (s->pci_dev, 0, 0);
+    qemu_irq_lower(s->pci_dev->irq[0]);
 }
 
 static void es1370_maybe_lower_irq (ES1370State *s, uint32_t sctl)

Modified: trunk/src/host/qemu-neo1973/hw/esp.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/esp.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/esp.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -507,15 +507,21 @@
     qemu_put_be32s(f, &s->ti_rptr);
     qemu_put_be32s(f, &s->ti_wptr);
     qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
+    qemu_put_be32s(f, &s->sense);
     qemu_put_be32s(f, &s->dma);
+    qemu_put_buffer(f, s->cmdbuf, TI_BUFSZ);
+    qemu_put_be32s(f, &s->cmdlen);
+    qemu_put_be32s(f, &s->do_cmd);
+    qemu_put_be32s(f, &s->dma_left);
+    // There should be no transfers in progress, so dma_counter is not saved
 }
 
 static int esp_load(QEMUFile *f, void *opaque, int version_id)
 {
     ESPState *s = opaque;
     
-    if (version_id != 2)
-        return -EINVAL; // Cannot emulate 1
+    if (version_id != 3)
+        return -EINVAL; // Cannot emulate 2
 
     qemu_get_buffer(f, s->rregs, ESP_MAXREG);
     qemu_get_buffer(f, s->wregs, ESP_MAXREG);
@@ -523,7 +529,12 @@
     qemu_get_be32s(f, &s->ti_rptr);
     qemu_get_be32s(f, &s->ti_wptr);
     qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
+    qemu_get_be32s(f, &s->sense);
     qemu_get_be32s(f, &s->dma);
+    qemu_get_buffer(f, s->cmdbuf, TI_BUFSZ);
+    qemu_get_be32s(f, &s->cmdlen);
+    qemu_get_be32s(f, &s->do_cmd);
+    qemu_get_be32s(f, &s->dma_left);
 
     return 0;
 }
@@ -568,7 +579,7 @@
 
     esp_reset(s);
 
-    register_savevm("esp", espaddr, 2, esp_save, esp_load, s);
+    register_savevm("esp", espaddr, 3, esp_save, esp_load, s);
     qemu_register_reset(esp_reset, s);
 
     return s;

Modified: trunk/src/host/qemu-neo1973/hw/fdc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/fdc.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/fdc.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /*
  * QEMU Floppy disk emulator (Intel 82078)
  * 
- * Copyright (c) 2003 Jocelyn Mayer
+ * Copyright (c) 2003, 2007 Jocelyn Mayer
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -368,7 +368,7 @@
     /* Controller's identification */
     uint8_t version;
     /* HW */
-    int irq_lvl;
+    qemu_irq irq;
     int dma_chann;
     uint32_t io_base;
     /* Controller state */
@@ -485,7 +485,100 @@
     fdctrl_write_mem,
 };
 
-fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped, 
+static void fd_save (QEMUFile *f, fdrive_t *fd)
+{
+    uint8_t tmp;
+
+    tmp = fd->drflags;
+    qemu_put_8s(f, &tmp);
+    qemu_put_8s(f, &fd->head);
+    qemu_put_8s(f, &fd->track);
+    qemu_put_8s(f, &fd->sect);
+    qemu_put_8s(f, &fd->dir);
+    qemu_put_8s(f, &fd->rw);
+}
+
+static void fdc_save (QEMUFile *f, void *opaque)
+{
+    fdctrl_t *s = opaque;
+
+    qemu_put_8s(f, &s->state);
+    qemu_put_8s(f, &s->dma_en);
+    qemu_put_8s(f, &s->cur_drv);
+    qemu_put_8s(f, &s->bootsel);
+    qemu_put_buffer(f, s->fifo, FD_SECTOR_LEN);
+    qemu_put_be32s(f, &s->data_pos);
+    qemu_put_be32s(f, &s->data_len);
+    qemu_put_8s(f, &s->data_state);
+    qemu_put_8s(f, &s->data_dir);
+    qemu_put_8s(f, &s->int_status);
+    qemu_put_8s(f, &s->eot);
+    qemu_put_8s(f, &s->timer0);
+    qemu_put_8s(f, &s->timer1);
+    qemu_put_8s(f, &s->precomp_trk);
+    qemu_put_8s(f, &s->config);
+    qemu_put_8s(f, &s->lock);
+    qemu_put_8s(f, &s->pwrd);
+    fd_save(f, &s->drives[0]);
+    fd_save(f, &s->drives[1]);
+}
+
+static int fd_load (QEMUFile *f, fdrive_t *fd)
+{
+    uint8_t tmp;
+
+    qemu_get_8s(f, &tmp);
+    fd->drflags = tmp;
+    qemu_get_8s(f, &fd->head);
+    qemu_get_8s(f, &fd->track);
+    qemu_get_8s(f, &fd->sect);
+    qemu_get_8s(f, &fd->dir);
+    qemu_get_8s(f, &fd->rw);
+
+    return 0;
+}
+
+static int fdc_load (QEMUFile *f, void *opaque, int version_id)
+{
+    fdctrl_t *s = opaque;
+    int ret;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    qemu_get_8s(f, &s->state);
+    qemu_get_8s(f, &s->dma_en);
+    qemu_get_8s(f, &s->cur_drv);
+    qemu_get_8s(f, &s->bootsel);
+    qemu_get_buffer(f, s->fifo, FD_SECTOR_LEN);
+    qemu_get_be32s(f, &s->data_pos);
+    qemu_get_be32s(f, &s->data_len);
+    qemu_get_8s(f, &s->data_state);
+    qemu_get_8s(f, &s->data_dir);
+    qemu_get_8s(f, &s->int_status);
+    qemu_get_8s(f, &s->eot);
+    qemu_get_8s(f, &s->timer0);
+    qemu_get_8s(f, &s->timer1);
+    qemu_get_8s(f, &s->precomp_trk);
+    qemu_get_8s(f, &s->config);
+    qemu_get_8s(f, &s->lock);
+    qemu_get_8s(f, &s->pwrd);
+
+    ret = fd_load(f, &s->drives[0]);
+    if (ret == 0)
+        ret = fd_load(f, &s->drives[1]);
+
+    return ret;
+}
+
+static void fdctrl_external_reset(void *opaque)
+{
+    fdctrl_t *s = opaque;
+
+    fdctrl_reset(s, 0);
+}
+
+fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped, 
                        uint32_t io_base,
                        BlockDriverState **fds)
 {
@@ -501,7 +594,7 @@
                                           fdctrl_result_timer, fdctrl);
 
     fdctrl->version = 0x90; /* Intel 82078 controller */
-    fdctrl->irq_lvl = irq_lvl;
+    fdctrl->irq = irq;
     fdctrl->dma_chann = dma_chann;
     fdctrl->io_base = io_base;
     fdctrl->config = 0x60; /* Implicit seek, polling & FIFO enabled */
@@ -525,6 +618,8 @@
         register_ioport_write(io_base + 0x01, 5, 1, &fdctrl_write, fdctrl);
         register_ioport_write(io_base + 0x07, 1, 1, &fdctrl_write, fdctrl);
     }
+    register_savevm("fdc", io_base, 1, fdc_save, fdc_load, fdctrl);
+    qemu_register_reset(fdctrl_external_reset, fdctrl);
     for (i = 0; i < 2; i++) {
         fd_revalidate(&fdctrl->drives[i]);
     }
@@ -542,7 +637,7 @@
 static void fdctrl_reset_irq (fdctrl_t *fdctrl)
 {
     FLOPPY_DPRINTF("Reset interrupt\n");
-    pic_set_irq(fdctrl->irq_lvl, 0);
+    qemu_set_irq(fdctrl->irq, 0);
     fdctrl->state &= ~FD_CTRL_INTR;
 }
 
@@ -557,7 +652,7 @@
     }
 #endif
     if (~(fdctrl->state & FD_CTRL_INTR)) {
-        pic_set_irq(fdctrl->irq_lvl, 1);
+        qemu_set_irq(fdctrl->irq, 1);
         fdctrl->state |= FD_CTRL_INTR;
     }
     FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", status);

Modified: trunk/src/host/qemu-neo1973/hw/grackle_pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/grackle_pci.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/grackle_pci.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -80,12 +80,12 @@
     return (irq_num + (pci_dev->devfn >> 3)) & 3;
 }
 
-static void pci_grackle_set_irq(void *pic, int irq_num, int level)
+static void pci_grackle_set_irq(qemu_irq *pic, int irq_num, int level)
 {
-    heathrow_pic_set_irq(pic, irq_num + 8, level);
+    qemu_set_irq(pic[irq_num + 8], level);
 }
 
-PCIBus *pci_grackle_init(uint32_t base, void *pic)
+PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
 {
     GrackleState *s;
     PCIDevice *d;

Added: trunk/src/host/qemu-neo1973/hw/gt64xxx.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/gt64xxx.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/gt64xxx.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,673 @@
+/*
+ * QEMU GT64120 PCI host
+ *
+ * Copyright (c) 2006,2007 Aurelien Jarno
+ * 
+ * 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"
+typedef target_phys_addr_t pci_addr_t;
+#include "pci_host.h"
+
+#define GT_REGS			(0x1000 >> 2)
+
+/* CPU Configuration */
+#define GT_CPU    		(0x000 >> 2)
+#define GT_MULTI    		(0x120 >> 2)
+
+/* CPU Address Decode */
+#define GT_SCS10LD    		(0x008 >> 2)
+#define GT_SCS10HD    		(0x010 >> 2)
+#define GT_SCS32LD    		(0x018 >> 2)
+#define GT_SCS32HD    		(0x020 >> 2)
+#define GT_CS20LD    		(0x028 >> 2)
+#define GT_CS20HD    		(0x030 >> 2)
+#define GT_CS3BOOTLD    	(0x038 >> 2)
+#define GT_CS3BOOTHD    	(0x040 >> 2)
+#define GT_PCI0IOLD    		(0x048 >> 2)
+#define GT_PCI0IOHD    		(0x050 >> 2)
+#define GT_PCI0M0LD    		(0x058 >> 2)
+#define GT_PCI0M0HD    		(0x060 >> 2)
+#define GT_ISD    		(0x068 >> 2)
+
+#define GT_PCI0M1LD    		(0x080 >> 2)
+#define GT_PCI0M1HD    		(0x088 >> 2)
+#define GT_PCI1IOLD    		(0x090 >> 2)
+#define GT_PCI1IOHD    		(0x098 >> 2)
+#define GT_PCI1M0LD    		(0x0a0 >> 2)
+#define GT_PCI1M0HD    		(0x0a8 >> 2)
+#define GT_PCI1M1LD    		(0x0b0 >> 2)
+#define GT_PCI1M1HD    		(0x0b8 >> 2)
+#define GT_PCI1M1LD    		(0x0b0 >> 2)
+#define GT_PCI1M1HD    		(0x0b8 >> 2)
+
+#define GT_SCS10AR    		(0x0d0 >> 2)
+#define GT_SCS32AR    		(0x0d8 >> 2)
+#define GT_CS20R    		(0x0e0 >> 2)
+#define GT_CS3BOOTR    		(0x0e8 >> 2)
+
+#define GT_PCI0IOREMAP    	(0x0f0 >> 2)
+#define GT_PCI0M0REMAP    	(0x0f8 >> 2)
+#define GT_PCI0M1REMAP    	(0x100 >> 2)
+#define GT_PCI1IOREMAP    	(0x108 >> 2)
+#define GT_PCI1M0REMAP    	(0x110 >> 2)
+#define GT_PCI1M1REMAP    	(0x118 >> 2)
+
+/* CPU Error Report */
+#define GT_CPUERR_ADDRLO    	(0x070 >> 2)
+#define GT_CPUERR_ADDRHI    	(0x078 >> 2)
+#define GT_CPUERR_DATALO    	(0x128 >> 2)		/* GT-64120A only  */
+#define GT_CPUERR_DATAHI    	(0x130 >> 2)		/* GT-64120A only  */
+#define GT_CPUERR_PARITY    	(0x138 >> 2)		/* GT-64120A only  */
+
+/* CPU Sync Barrier */
+#define GT_PCI0SYNC    		(0x0c0 >> 2)
+#define GT_PCI1SYNC    		(0x0c8 >> 2)
+
+/* SDRAM and Device Address Decode */
+#define GT_SCS0LD    		(0x400 >> 2)
+#define GT_SCS0HD    		(0x404 >> 2)
+#define GT_SCS1LD    		(0x408 >> 2)
+#define GT_SCS1HD    		(0x40c >> 2)
+#define GT_SCS2LD    		(0x410 >> 2)
+#define GT_SCS2HD    		(0x414 >> 2)
+#define GT_SCS3LD    		(0x418 >> 2)
+#define GT_SCS3HD    		(0x41c >> 2)
+#define GT_CS0LD    		(0x420 >> 2)
+#define GT_CS0HD    		(0x424 >> 2)
+#define GT_CS1LD    		(0x428 >> 2)
+#define GT_CS1HD    		(0x42c >> 2)
+#define GT_CS2LD    		(0x430 >> 2)
+#define GT_CS2HD    		(0x434 >> 2)
+#define GT_CS3LD    		(0x438 >> 2)
+#define GT_CS3HD    		(0x43c >> 2)
+#define GT_BOOTLD    		(0x440 >> 2)
+#define GT_BOOTHD    		(0x444 >> 2)
+#define GT_ADERR    		(0x470 >> 2)
+
+/* SDRAM Configuration */
+#define GT_SDRAM_CFG    	(0x448 >> 2)
+#define GT_SDRAM_OPMODE    	(0x474 >> 2)
+#define GT_SDRAM_BM    		(0x478 >> 2)
+#define GT_SDRAM_ADDRDECODE    	(0x47c >> 2)
+
+/* SDRAM Parameters */
+#define GT_SDRAM_B0    		(0x44c >> 2)
+#define GT_SDRAM_B1    		(0x450 >> 2)
+#define GT_SDRAM_B2    		(0x454 >> 2)
+#define GT_SDRAM_B3    		(0x458 >> 2)
+
+/* Device Parameters */
+#define GT_DEV_B0    		(0x45c >> 2)
+#define GT_DEV_B1    		(0x460 >> 2)
+#define GT_DEV_B2    		(0x464 >> 2)
+#define GT_DEV_B3    		(0x468 >> 2)
+#define GT_DEV_BOOT    		(0x46c >> 2)
+
+/* ECC */
+#define GT_ECC_ERRDATALO	(0x480 >> 2)		/* GT-64120A only  */
+#define GT_ECC_ERRDATAHI	(0x484 >> 2)		/* GT-64120A only  */
+#define GT_ECC_MEM		(0x488 >> 2)		/* GT-64120A only  */
+#define GT_ECC_CALC		(0x48c >> 2)		/* GT-64120A only  */
+#define GT_ECC_ERRADDR		(0x490 >> 2)		/* GT-64120A only  */
+
+/* DMA Record */
+#define GT_DMA0_CNT    		(0x800 >> 2)
+#define GT_DMA1_CNT    		(0x804 >> 2)
+#define GT_DMA2_CNT    		(0x808 >> 2)
+#define GT_DMA3_CNT    		(0x80c >> 2)
+#define GT_DMA0_SA    		(0x810 >> 2)
+#define GT_DMA1_SA    		(0x814 >> 2)
+#define GT_DMA2_SA    		(0x818 >> 2)
+#define GT_DMA3_SA    		(0x81c >> 2)
+#define GT_DMA0_DA    		(0x820 >> 2)
+#define GT_DMA1_DA    		(0x824 >> 2)
+#define GT_DMA2_DA    		(0x828 >> 2)
+#define GT_DMA3_DA    		(0x82c >> 2)
+#define GT_DMA0_NEXT    	(0x830 >> 2)
+#define GT_DMA1_NEXT    	(0x834 >> 2)
+#define GT_DMA2_NEXT    	(0x838 >> 2)
+#define GT_DMA3_NEXT    	(0x83c >> 2)
+#define GT_DMA0_CUR    		(0x870 >> 2)
+#define GT_DMA1_CUR    		(0x874 >> 2)
+#define GT_DMA2_CUR    		(0x878 >> 2)
+#define GT_DMA3_CUR    		(0x87c >> 2)
+
+/* DMA Channel Control */
+#define GT_DMA0_CTRL    	(0x840 >> 2)
+#define GT_DMA1_CTRL    	(0x844 >> 2)
+#define GT_DMA2_CTRL    	(0x848 >> 2)
+#define GT_DMA3_CTRL    	(0x84c >> 2)
+
+/* DMA Arbiter */
+#define GT_DMA_ARB    		(0x860 >> 2)
+
+/* Timer/Counter */
+#define GT_TC0    		(0x850 >> 2)
+#define GT_TC1    		(0x854 >> 2)
+#define GT_TC2    		(0x858 >> 2)
+#define GT_TC3    		(0x85c >> 2)
+#define GT_TC_CONTROL    	(0x864 >> 2)
+
+/* PCI Internal */
+#define GT_PCI0_CMD    		(0xc00 >> 2)
+#define GT_PCI0_TOR    		(0xc04 >> 2)
+#define GT_PCI0_BS_SCS10    	(0xc08 >> 2)
+#define GT_PCI0_BS_SCS32    	(0xc0c >> 2)
+#define GT_PCI0_BS_CS20    	(0xc10 >> 2)
+#define GT_PCI0_BS_CS3BT    	(0xc14 >> 2)
+#define GT_PCI1_IACK    	(0xc30 >> 2)
+#define GT_PCI0_IACK    	(0xc34 >> 2)
+#define GT_PCI0_BARE    	(0xc3c >> 2)
+#define GT_PCI0_PREFMBR    	(0xc40 >> 2)
+#define GT_PCI0_SCS10_BAR    	(0xc48 >> 2)
+#define GT_PCI0_SCS32_BAR    	(0xc4c >> 2)
+#define GT_PCI0_CS20_BAR    	(0xc50 >> 2)
+#define GT_PCI0_CS3BT_BAR    	(0xc54 >> 2)
+#define GT_PCI0_SSCS10_BAR    	(0xc58 >> 2)
+#define GT_PCI0_SSCS32_BAR    	(0xc5c >> 2)
+#define GT_PCI0_SCS3BT_BAR    	(0xc64 >> 2)
+#define GT_PCI1_CMD    		(0xc80 >> 2)
+#define GT_PCI1_TOR    		(0xc84 >> 2)
+#define GT_PCI1_BS_SCS10    	(0xc88 >> 2)
+#define GT_PCI1_BS_SCS32    	(0xc8c >> 2)
+#define GT_PCI1_BS_CS20    	(0xc90 >> 2)
+#define GT_PCI1_BS_CS3BT    	(0xc94 >> 2)
+#define GT_PCI1_BARE    	(0xcbc >> 2)
+#define GT_PCI1_PREFMBR    	(0xcc0 >> 2)
+#define GT_PCI1_SCS10_BAR    	(0xcc8 >> 2)
+#define GT_PCI1_SCS32_BAR    	(0xccc >> 2)
+#define GT_PCI1_CS20_BAR    	(0xcd0 >> 2)
+#define GT_PCI1_CS3BT_BAR    	(0xcd4 >> 2)
+#define GT_PCI1_SSCS10_BAR    	(0xcd8 >> 2)
+#define GT_PCI1_SSCS32_BAR    	(0xcdc >> 2)
+#define GT_PCI1_SCS3BT_BAR    	(0xce4 >> 2)
+#define GT_PCI1_CFGADDR    	(0xcf0 >> 2)
+#define GT_PCI1_CFGDATA    	(0xcf4 >> 2)
+#define GT_PCI0_CFGADDR    	(0xcf8 >> 2)
+#define GT_PCI0_CFGDATA    	(0xcfc >> 2)
+
+/* Interrupts */
+#define GT_INTRCAUSE    	(0xc18 >> 2)
+#define GT_INTRMASK    		(0xc1c >> 2)
+#define GT_PCI0_ICMASK    	(0xc24 >> 2)
+#define GT_PCI0_SERR0MASK    	(0xc28 >> 2)
+#define GT_CPU_INTSEL    	(0xc70 >> 2)
+#define GT_PCI0_INTSEL    	(0xc74 >> 2)
+#define GT_HINTRCAUSE    	(0xc98 >> 2)
+#define GT_HINTRMASK    	(0xc9c >> 2)
+#define GT_PCI0_HICMASK    	(0xca4 >> 2)
+#define GT_PCI1_SERR1MASK    	(0xca8 >> 2)
+
+
+typedef PCIHostState GT64120PCIState;
+
+typedef struct GT64120State {
+    GT64120PCIState *pci;
+    uint32_t regs[GT_REGS];
+    target_phys_addr_t PCI0IO_start;
+    target_phys_addr_t PCI0IO_length;
+} GT64120State;
+
+static void gt64120_pci_mapping(GT64120State *s)
+{
+    /* Update IO mapping */
+    if ((s->regs[GT_PCI0IOLD] & 0x7f) <= s->regs[GT_PCI0IOHD])
+    {
+      /* Unmap old IO address */	    
+      if (s->PCI0IO_length)
+      {
+        cpu_register_physical_memory(s->PCI0IO_start, s->PCI0IO_length, IO_MEM_UNASSIGNED);	     
+      }
+      /* Map new IO address */
+      s->PCI0IO_start = s->regs[GT_PCI0IOLD] << 21;
+      s->PCI0IO_length = ((s->regs[GT_PCI0IOHD] + 1) - (s->regs[GT_PCI0IOLD] & 0x7f)) << 21;
+      isa_mem_base = s->PCI0IO_start;
+      isa_mmio_init(s->PCI0IO_start, s->PCI0IO_length);
+    }
+}
+
+static void gt64120_writel (void *opaque, target_phys_addr_t addr,
+                            uint32_t val)
+{
+    GT64120State *s = opaque;
+    uint32_t saddr;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+
+    saddr = (addr & 0xfff) >> 2;
+    switch (saddr) {
+
+    /* CPU Configuration */
+    case GT_CPU:
+        s->regs[GT_CPU] = val;
+        break;
+    case GT_MULTI:
+	/* Read-only register as only one GT64xxx is present on the CPU bus */
+        break;
+
+    /* CPU Address Decode */
+    case GT_PCI0IOLD:
+        s->regs[GT_PCI0IOLD]    = val & 0x00007fff;
+        s->regs[GT_PCI0IOREMAP] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI0M0LD:
+        s->regs[GT_PCI0M0LD]    = val & 0x00007fff;
+        s->regs[GT_PCI0M0REMAP] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI0M1LD:
+        s->regs[GT_PCI0M1LD]    = val & 0x00007fff;
+        s->regs[GT_PCI0M1REMAP] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI1IOLD:
+        s->regs[GT_PCI1IOLD]    = val & 0x00007fff;
+        s->regs[GT_PCI1IOREMAP] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI1M0LD:
+        s->regs[GT_PCI1M0LD]    = val & 0x00007fff;
+        s->regs[GT_PCI1M0REMAP] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI1M1LD:
+        s->regs[GT_PCI1M1LD]    = val & 0x00007fff;
+        s->regs[GT_PCI1M1REMAP] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI0IOHD:
+    case GT_PCI0M0HD:
+    case GT_PCI0M1HD:
+    case GT_PCI1IOHD:
+    case GT_PCI1M0HD:
+    case GT_PCI1M1HD:
+        s->regs[saddr] = val & 0x0000007f;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI0IOREMAP:
+    case GT_PCI0M0REMAP:
+    case GT_PCI0M1REMAP:
+    case GT_PCI1IOREMAP:
+    case GT_PCI1M0REMAP:
+    case GT_PCI1M1REMAP:
+        s->regs[saddr] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+
+    /* CPU Error Report */
+    case GT_CPUERR_ADDRLO:
+    case GT_CPUERR_ADDRHI:
+    case GT_CPUERR_DATALO:
+    case GT_CPUERR_DATAHI:
+    case GT_CPUERR_PARITY:
+	/* Read-only registers, do nothing */
+        break;
+
+    /* CPU Sync Barrier */
+    case GT_PCI0SYNC:
+    case GT_PCI1SYNC:
+	/* Read-only registers, do nothing */
+        break;
+
+    /* ECC */
+    case GT_ECC_ERRDATALO:
+    case GT_ECC_ERRDATAHI:
+    case GT_ECC_MEM:
+    case GT_ECC_CALC:
+    case GT_ECC_ERRADDR:
+        /* Read-only registers, do nothing */
+        break;
+
+    /* PCI Internal */
+    case GT_PCI0_CMD:
+    case GT_PCI1_CMD:
+        s->regs[saddr] = val & 0x0401fc0f;
+        break;
+    case GT_PCI0_CFGADDR:
+        s->pci->config_reg = val & 0x80fffffc;
+        break;
+    case GT_PCI0_CFGDATA:
+        pci_host_data_writel(s->pci, 0, val);
+        break;
+
+    /* SDRAM Parameters */
+    case GT_SDRAM_B0:
+    case GT_SDRAM_B1:
+    case GT_SDRAM_B2:
+    case GT_SDRAM_B3:
+        /* We don't simulate electrical parameters of the SDRAM.
+           Accept, but ignore the values. */
+        s->regs[saddr] = val;
+        break;
+
+    default:
+#if 0
+        printf ("gt64120_writel: Bad register offset 0x%x\n", (int)addr);
+#endif
+        break;
+    }
+}
+
+static uint32_t gt64120_readl (void *opaque,
+                               target_phys_addr_t addr)
+{
+    GT64120State *s = opaque;
+    uint32_t val;
+    uint32_t saddr;
+
+    val = 0;
+    saddr = (addr & 0xfff) >> 2;
+
+    switch (saddr) {
+
+    /* CPU Configuration */
+    case GT_MULTI:
+        /* Only one GT64xxx is present on the CPU bus, return
+           the initial value */
+        val = s->regs[saddr];
+        break;
+
+    /* CPU Error Report */
+    case GT_CPUERR_ADDRLO:
+    case GT_CPUERR_ADDRHI:
+    case GT_CPUERR_DATALO:
+    case GT_CPUERR_DATAHI:
+    case GT_CPUERR_PARITY:
+        /* Emulated memory has no error, always return the initial
+           values */ 
+        val = s->regs[saddr];
+        break;
+
+    /* CPU Sync Barrier */
+    case GT_PCI0SYNC:
+    case GT_PCI1SYNC:
+        /* Reading those register should empty all FIFO on the PCI
+           bus, which are not emulated. The return value should be
+           a random value that should be ignored. */
+        val = 0xc000ffee; 
+        break;
+
+    /* ECC */
+    case GT_ECC_ERRDATALO:
+    case GT_ECC_ERRDATAHI:
+    case GT_ECC_MEM:
+    case GT_ECC_CALC:
+    case GT_ECC_ERRADDR:
+        /* Emulated memory has no error, always return the initial
+           values */ 
+        val = s->regs[saddr];
+        break;
+
+    case GT_CPU:
+    case GT_PCI0IOLD:
+    case GT_PCI0M0LD:
+    case GT_PCI0M1LD:
+    case GT_PCI1IOLD:
+    case GT_PCI1M0LD:
+    case GT_PCI1M1LD:
+    case GT_PCI0IOHD:
+    case GT_PCI0M0HD:
+    case GT_PCI0M1HD:
+    case GT_PCI1IOHD:
+    case GT_PCI1M0HD:
+    case GT_PCI1M1HD:
+    case GT_PCI0_CMD:
+    case GT_PCI1_CMD:
+    case GT_PCI0IOREMAP:
+    case GT_PCI0M0REMAP:
+    case GT_PCI0M1REMAP:
+    case GT_PCI1IOREMAP:
+    case GT_PCI1M0REMAP:
+    case GT_PCI1M1REMAP:
+        val = s->regs[saddr];
+        break;
+    case GT_PCI0_IACK:
+        /* Read the IRQ number */ 
+        val = pic_read_irq(isa_pic);
+        break;
+
+    /* SDRAM Parameters */
+    case GT_SDRAM_B0:
+    case GT_SDRAM_B1:
+    case GT_SDRAM_B2:
+    case GT_SDRAM_B3:
+        /* We don't simulate electrical parameters of the SDRAM.
+           Just return the last written value. */
+        val = s->regs[saddr];
+        break;
+
+    /* PCI Internal */
+    case GT_PCI0_CFGADDR:
+        val = s->pci->config_reg;
+        break;
+    case GT_PCI0_CFGDATA:
+        val = pci_host_data_readl(s->pci, 0);
+        break;
+
+    default:
+        val = s->regs[saddr];
+#if 0
+        printf ("gt64120_readl: Bad register offset 0x%x\n", (int)addr);
+#endif
+        break;
+    }
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    return bswap32(val);
+#else
+    return val;
+#endif
+}
+
+static CPUWriteMemoryFunc *gt64120_write[] = {
+    &gt64120_writel,
+    &gt64120_writel,
+    &gt64120_writel,
+};
+
+static CPUReadMemoryFunc *gt64120_read[] = {
+    &gt64120_readl,
+    &gt64120_readl,
+    &gt64120_readl,
+};
+
+static int pci_gt64120_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    int slot;
+
+    slot = (pci_dev->devfn >> 3);
+
+    switch (slot) {
+      /* PIIX4 USB */
+      case 10:
+        return 3;
+      /* AMD 79C973 Ethernet */
+      case 11:
+        return 0;
+      /* Crystal 4281 Sound */
+      case 12:
+        return 0;
+      /* PCI slot 1 to 4 */
+      case 18 ... 21:
+        return ((slot - 18) + irq_num) & 0x03;
+      /* Unknown device, don't do any translation */
+      default:
+        return irq_num;
+    }
+}
+
+extern PCIDevice *piix4_dev;
+static int pci_irq_levels[4];
+
+static void pci_gt64120_set_irq(qemu_irq *pic, int irq_num, int level)
+{
+    int i, pic_irq, pic_level;
+
+    pci_irq_levels[irq_num] = level;
+
+    /* now we change the pic irq level according to the piix irq mappings */
+    /* XXX: optimize */
+    pic_irq = piix4_dev->config[0x60 + irq_num];
+    if (pic_irq < 16) {
+        /* The pic level is the logical OR of all the PCI irqs mapped
+           to it */
+        pic_level = 0;
+        for (i = 0; i < 4; i++) {
+            if (pic_irq == piix4_dev->config[0x60 + i])
+                pic_level |= pci_irq_levels[i];
+        }
+        qemu_set_irq(pic[pic_irq], pic_level);
+    }
+}
+
+
+void gt64120_reset(void *opaque)
+{
+    GT64120State *s = opaque;
+
+    /* CPU Configuration */
+#ifdef TARGET_WORDS_BIGENDIAN
+    s->regs[GT_CPU]           = 0x00000000;
+#else
+    s->regs[GT_CPU]           = 0x00001000;
+#endif
+    s->regs[GT_MULTI]         = 0x00000000;
+
+    /* CPU Address decode FIXME: not complete*/
+    s->regs[GT_PCI0IOLD]      = 0x00000080;
+    s->regs[GT_PCI0IOHD]      = 0x0000000f;
+    s->regs[GT_PCI0M0LD]      = 0x00000090;
+    s->regs[GT_PCI0M0HD]      = 0x0000001f;
+    s->regs[GT_PCI0M1LD]      = 0x00000790;
+    s->regs[GT_PCI0M1HD]      = 0x0000001f;
+    s->regs[GT_PCI1IOLD]      = 0x00000100;
+    s->regs[GT_PCI1IOHD]      = 0x0000000f;
+    s->regs[GT_PCI1M0LD]      = 0x00000110;
+    s->regs[GT_PCI1M0HD]      = 0x0000001f;
+    s->regs[GT_PCI1M1LD]      = 0x00000120;
+    s->regs[GT_PCI1M1HD]      = 0x0000002f;
+    s->regs[GT_PCI0IOREMAP]   = 0x00000080;
+    s->regs[GT_PCI0M0REMAP]   = 0x00000090;
+    s->regs[GT_PCI0M1REMAP]   = 0x00000790;
+    s->regs[GT_PCI1IOREMAP]   = 0x00000100;
+    s->regs[GT_PCI1M0REMAP]   = 0x00000110;
+    s->regs[GT_PCI1M1REMAP]   = 0x00000120;
+
+    /* CPU Error Report */
+    s->regs[GT_CPUERR_ADDRLO] = 0x00000000;
+    s->regs[GT_CPUERR_ADDRHI] = 0x00000000;
+    s->regs[GT_CPUERR_DATALO] = 0xffffffff;
+    s->regs[GT_CPUERR_DATAHI] = 0xffffffff;
+    s->regs[GT_CPUERR_PARITY] = 0x000000ff;
+
+    /* ECC */
+    s->regs[GT_ECC_ERRDATALO] = 0x00000000;
+    s->regs[GT_ECC_ERRDATAHI] = 0x00000000;
+    s->regs[GT_ECC_MEM]       = 0x00000000;
+    s->regs[GT_ECC_CALC]      = 0x00000000;
+    s->regs[GT_ECC_ERRADDR]   = 0x00000000;
+
+    /* SDRAM Parameters */
+    s->regs[GT_SDRAM_B0]      = 0x00000005;    
+    s->regs[GT_SDRAM_B1]      = 0x00000005;    
+    s->regs[GT_SDRAM_B2]      = 0x00000005;    
+    s->regs[GT_SDRAM_B3]      = 0x00000005;    
+
+    /* PCI Internal FIXME: not complete*/
+#ifdef TARGET_WORDS_BIGENDIAN
+    s->regs[GT_PCI0_CMD]      = 0x00000000;
+    s->regs[GT_PCI1_CMD]      = 0x00000000;
+#else
+    s->regs[GT_PCI0_CMD]      = 0x00010001;
+    s->regs[GT_PCI1_CMD]      = 0x00010001;
+#endif
+    s->regs[GT_PCI0_IACK]     = 0x00000000;
+    s->regs[GT_PCI1_IACK]     = 0x00000000;
+
+    gt64120_pci_mapping(s);
+}
+
+static uint32_t gt64120_read_config(PCIDevice *d, uint32_t address, int len)
+{
+    uint32_t val = pci_default_read_config(d, address, len);
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    return val;
+}
+
+static void gt64120_write_config(PCIDevice *d, uint32_t address, uint32_t val,
+                                 int len)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    pci_default_write_config(d, address, val, len);
+}
+
+PCIBus *pci_gt64120_init(qemu_irq *pic)
+{
+    GT64120State *s;
+    PCIDevice *d;
+    int gt64120;
+
+    s = qemu_mallocz(sizeof(GT64120State));
+    s->pci = qemu_mallocz(sizeof(GT64120PCIState));
+    gt64120_reset(s);
+
+    s->pci->bus = pci_register_bus(pci_gt64120_set_irq, pci_gt64120_map_irq,
+                                   pic, 144, 4);
+
+    gt64120 = cpu_register_io_memory(0, gt64120_read,
+                                     gt64120_write, s);
+    cpu_register_physical_memory(0x1be00000LL, 0x1000, gt64120);
+
+    d = pci_register_device(s->pci->bus, "GT64120 PCI Bus", sizeof(PCIDevice),
+                            0, gt64120_read_config, gt64120_write_config);
+
+    d->config[0x00] = 0xab; // vendor_id
+    d->config[0x01] = 0x11;
+    d->config[0x02] = 0x20; // device_id
+    d->config[0x03] = 0x46;
+    d->config[0x04] = 0x06;
+    d->config[0x05] = 0x00;
+    d->config[0x06] = 0x80;
+    d->config[0x07] = 0xa2;
+    d->config[0x08] = 0x10;
+    d->config[0x09] = 0x00;
+    d->config[0x0A] = 0x80;
+    d->config[0x0B] = 0x05;
+    d->config[0x0C] = 0x08;
+    d->config[0x0D] = 0x40;
+    d->config[0x0E] = 0x00;
+    d->config[0x0F] = 0x00;
+    d->config[0x17] = 0x08;
+    d->config[0x1B] = 0x1c;
+    d->config[0x1F] = 0x1f;
+    d->config[0x23] = 0x14;
+    d->config[0x27] = 0x14;
+    d->config[0x3D] = 0x01;
+
+    return s->pci->bus;
+}

Modified: trunk/src/host/qemu-neo1973/hw/heathrow_pic.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/heathrow_pic.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/heathrow_pic.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -32,9 +32,9 @@
     uint32_t level_triggered;
 } HeathrowPIC;
 
-struct HeathrowPICS {
+typedef struct HeathrowPICS {
     HeathrowPIC pics[2];
-};
+} HeathrowPICS;
 
 static inline int check_irq(HeathrowPIC *pic)
 {
@@ -130,7 +130,7 @@
 };
 
 
-void heathrow_pic_set_irq(void *opaque, int num, int level)
+static void heathrow_pic_set_irq(void *opaque, int num, int level)
 {
     HeathrowPICS *s = opaque;
     HeathrowPIC *pic;
@@ -156,7 +156,7 @@
     heathrow_pic_update(s);
 }
 
-HeathrowPICS *heathrow_pic_init(int *pmem_index)
+qemu_irq *heathrow_pic_init(int *pmem_index)
 {
     HeathrowPICS *s;
     
@@ -164,5 +164,5 @@
     s->pics[0].level_triggered = 0;
     s->pics[1].level_triggered = 0x1ff00000;
     *pmem_index = cpu_register_io_memory(0, pic_read, pic_write, s);
-    return s;
+    return qemu_allocate_irqs(heathrow_pic_set_irq, s, 64);
 }

Added: trunk/src/host/qemu-neo1973/hw/i2c.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/i2c.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/i2c.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,117 @@
+/* 
+ * QEMU I2C bus interface.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licenced under the LGPL.
+ */
+
+#include "vl.h"
+
+struct i2c_bus
+{
+    i2c_slave *current_dev;
+    i2c_slave *dev;
+};
+
+/* Create a new I2C bus.  */
+i2c_bus *i2c_init_bus(void)
+{
+    i2c_bus *bus;
+
+    bus = (i2c_bus *)qemu_mallocz(sizeof(i2c_bus));
+    return bus;
+}
+
+/* Create a new slave device.  */
+i2c_slave *i2c_slave_init(i2c_bus *bus, int address, int size)
+{
+    i2c_slave *dev;
+
+    if (size < sizeof(i2c_slave))
+        cpu_abort(cpu_single_env, "I2C struct too small");
+
+    dev = (i2c_slave *)qemu_mallocz(size);
+    dev->address = address;
+    dev->next = bus->dev;
+    bus->dev = dev;
+
+    return dev;
+}
+
+void i2c_set_slave_address(i2c_slave *dev, int address)
+{
+    dev->address = address;
+}
+
+/* Return nonzero if bus is busy.  */
+int i2c_bus_busy(i2c_bus *bus)
+{
+    return bus->current_dev != NULL;
+}
+
+/* Returns nonzero if the bus is already busy, or is the address is not
+   valid.  */
+/* TODO: Make this handle multiple masters.  */
+int i2c_start_transfer(i2c_bus *bus, int address, int recv)
+{
+    i2c_slave *dev;
+
+    for (dev = bus->dev; dev; dev = dev->next) {
+        if (dev->address == address)
+            break;
+    }
+
+    if (!dev)
+        return 1;
+
+    /* If the bus is already busy, assume this is a repeated
+       start condition.  */
+    bus->current_dev = dev;
+    dev->event(dev, recv ? I2C_START_RECV : I2C_START_SEND);
+    return 0;
+}
+
+void i2c_end_transfer(i2c_bus *bus)
+{
+    i2c_slave *dev = bus->current_dev;
+
+    if (!dev)
+        return;
+
+    dev->event(dev, I2C_FINISH);
+
+    bus->current_dev = NULL;
+}
+
+int i2c_send(i2c_bus *bus, uint8_t data)
+{
+    i2c_slave *dev = bus->current_dev;
+
+    if (!dev)
+        return -1;
+
+    return dev->send(dev, data);
+}
+
+int i2c_recv(i2c_bus *bus)
+{
+    i2c_slave *dev = bus->current_dev;
+
+    if (!dev)
+        return -1;
+
+    return dev->recv(dev);
+}
+
+void i2c_nack(i2c_bus *bus)
+{
+    i2c_slave *dev = bus->current_dev;
+
+    if (!dev)
+        return;
+
+    dev->event(dev, I2C_NACK);
+}
+

Modified: trunk/src/host/qemu-neo1973/hw/i2c.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/i2c.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/i2c.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,187 +1,80 @@
-/*
- * Simplified I2C(tm) bus / SMBus(tm).
- *
- * Copyright (c) 2006 Openedhand Ltd.
- * Written by Andrzej Zaborowski <balrog at zabor.org>
- *
- * This file is licensed under GNU GPL.
- */
+#ifndef QEMU_I2C_H
+#define QEMU_I2C_H
 
-#define I2C_MAX_MSG	4096
+/* The QEMU I2C implementation only supports simple transfers that complete
+   immediately.  It does not support slave devices that need to be able to
+   defer their response (eg. CPU slave interfaces where the data is supplied
+   by the device driver in response to an interrupt).  */
 
-struct i2c_slave_s {
-    uint8_t address;
-    int (*tx)(void *opaque, uint8_t *data, int len);
-    void (*start)(void *opaque, int dir);
-    void (*stop)(void *opaque);
-    void *opaque;
+enum i2c_event {
+    I2C_START_RECV,
+    I2C_START_SEND,
+    I2C_FINISH,
+    I2C_NACK /* Masker NACKed a recieve byte.  */
 };
 
-struct i2c_bus_s {
-    struct i2c_slave_s *slave[0x80];
-    uint8_t current;
-    int dir;
-};
+typedef struct i2c_slave i2c_slave;
 
-/* I2C master - drives the clock signal on a bus.  There can be multiple
- * masters on one bus.  */
-struct i2c_master_s {
-    struct i2c_bus_s *bus;
-    uint8_t message[I2C_MAX_MSG];
-    int message_len;
-    int ack;
+/* Master to slave.  */
+typedef int (*i2c_send_cb)(i2c_slave *s, uint8_t data);
+/* Slave to master.  */
+typedef int (*i2c_recv_cb)(i2c_slave *s);
+/* Notify the slave of a bus state change.  */
+typedef void (*i2c_event_cb)(i2c_slave *s, enum i2c_event event);
 
-    uint8_t data;
-};
-
-static inline int i2c_bus_start(struct i2c_bus_s *bus, uint8_t byte)
+struct i2c_slave
 {
-    struct i2c_slave_s *slave;
+    /* Callbacks to be set by the device.  */
+    i2c_event_cb event;
+    i2c_recv_cb recv;
+    i2c_send_cb send;
 
-    bus->current = byte >> 1;
-    bus->dir = byte & 1;
-    slave = bus->slave[bus->current];
+    /* Remaining fields for internal use by the I2C code.  */
+    int address;
+    void *next;
+};
 
-    return !slave;
-}
+typedef struct i2c_bus i2c_bus;
 
-static inline int i2c_start_submit(struct i2c_bus_s *bus)
-{
-    struct i2c_slave_s *slave = bus->slave[bus->current];
-    if (!slave)
-        return 1;
+i2c_bus *i2c_init_bus(void);
+i2c_slave *i2c_slave_init(i2c_bus *bus, int address, int size);
+void i2c_set_slave_address(i2c_slave *dev, int address);
+int i2c_bus_busy(i2c_bus *bus);
+int i2c_start_transfer(i2c_bus *bus, int address, int recv);
+void i2c_end_transfer(i2c_bus *bus);
+void i2c_nack(i2c_bus *bus);
+int i2c_send(i2c_bus *bus, uint8_t data);
+int i2c_recv(i2c_bus *bus);
 
-    if (slave->start)
-        slave->start(slave->opaque, bus->dir);
-    return 0;
-}
-
-static inline int i2c_stop_submit(struct i2c_bus_s *bus)
-{
-    struct i2c_slave_s *slave = bus->slave[bus->current];
-    if (!slave)
-        return 1;
-
-    if (slave->stop)
-        slave->stop(slave->opaque);
-    return 0;
-}
-
-static inline int i2c_msg_submit(struct i2c_bus_s *bus,
-                uint8_t message[], int len)
-{
-    struct i2c_slave_s *slave = bus->slave[bus->current];
-    if (!slave)
-        return 1;
-
-    return slave->tx ? slave->tx(slave->opaque, message, len) : 1;
-}
-
-static inline void i2c_master_submit(struct i2c_master_s *master,
-                int start, int stop)
-{
-    int ret = 0;
-
-    if (!master->bus) {
-        master->ack = 0;
-        return;
-    }
-
-    if (start) {
-        if (master->message_len)
-            if (!master->bus->dir) {	/* Master --> Slave */
-                i2c_start_submit(master->bus);
-                ret = i2c_msg_submit(master->bus,
-                                master->message, master->message_len);
-                master->message_len = 0;
-            }
-
-        ret = i2c_bus_start(master->bus, master->data);
-        master->message_len = 0;
-
-        if (master->bus->dir) {		/* Master <-- Slave */
-            i2c_start_submit(master->bus);
-            master->message_len = 1;
-            if (stop)
-                i2c_msg_submit(master->bus, master->message, 0);
-        }
-    } else if (stop < 2) {
-        if (!master->bus->dir) {	/* Master --> Slave */
-            if (master->message_len < I2C_MAX_MSG)
-                master->message[master->message_len ++] = master->data;
-        } else {			/* Master <-- Slave */
-            ret = i2c_msg_submit(master->bus,
-                            master->message, master->message_len);
-            master->data = master->message[0];
-        }
-    }
-
-    if (stop) {
-        if (!master->bus->dir) {	/* Master --> Slave */
-            i2c_start_submit(master->bus);
-            ret = i2c_msg_submit(master->bus,
-                            master->message, master->message_len);
-            master->message_len = 0;
-        }
-
-        i2c_stop_submit(master->bus);
-    }
-
-    master->ack = !ret;
-}
-
-/* Call with zero `addr' to detach.  */
-static inline void i2c_slave_attach(struct i2c_bus_s *bus, uint8_t addr,
-                struct i2c_slave_s *dev)
-{
-    if (addr >= 0x80)
-        cpu_abort(cpu_single_env, "bad I2C address");
-
-    if (dev->address)
-        bus->slave[dev->address] = 0;
-
-    dev->address = addr;
-
-    if (dev->address)
-        bus->slave[dev->address] = dev;
-}
-
-static inline void i2c_master_attach(struct i2c_bus_s *bus,
-                struct i2c_master_s *dev)
-{
-    dev->bus = bus;
-}
-
 /* max7310.c */
-struct i2c_slave_s *max7310_init(void);
-void max7310_reset(struct i2c_slave_s *i2c);
-void max7310_gpio_set(struct i2c_slave_s *i2c, int line, int level);
-void max7310_gpio_handler_set(struct i2c_slave_s *i2c, int line,
+i2c_slave *max7310_init(i2c_bus *bus);
+void max7310_reset(i2c_slave *i2c);
+void max7310_gpio_set(i2c_slave *i2c, int line, int level);
+void max7310_gpio_handler_set(i2c_slave *i2c, int line,
                 gpio_handler_t handler, void *opaque);
 
 /* wm8750.c */
-struct i2c_slave_s *wm8750_init(AudioState *audio);
-void wm8750_reset(struct i2c_slave_s *i2c);
-void wm8750_data_req_set(struct i2c_slave_s *i2c,
+i2c_slave *wm8750_init(i2c_bus *bus, AudioState *audio);
+void wm8750_reset(i2c_slave *i2c);
+void wm8750_data_req_set(i2c_slave *i2c,
                 void (*data_req)(void *, int, int), void *opaque);
 void wm8750_dac_dat(void *opaque, uint32_t sample);
 uint32_t wm8750_adc_dat(void *opaque);
 
 /* wm8753.c */
-struct i2c_slave_s *wm8753_init(AudioState *audio);
-void wm8753_reset(struct i2c_slave_s *i2c);
-void wm8753_data_req_set(struct i2c_slave_s *i2c,
+i2c_slave *wm8753_init(i2c_bus *bus, AudioState *audio);
+void wm8753_reset(i2c_slave *i2c);
+void wm8753_data_req_set(i2c_slave *i2c,
                 void (*data_req)(void *, int, int), void *opaque);
 void wm8753_dac_dat(void *opaque, uint32_t sample);
 uint32_t wm8753_adc_dat(void *opaque);
-void wm8753_gpio_set(struct i2c_slave_s *i2c, int line, int level);
-void wm8753_gpio_handler_set(struct i2c_slave_s *i2c, int line,
-                gpio_handler_t handler, void *opaque);
+qemu_irq *wm8753_gpio_in_get(i2c_slave *i2c);
+void wm8753_gpio_out_set(i2c_slave *i2c, int line, qemu_irq handler);
 
 /* pcf5060x.c */
-struct i2c_slave_s *pcf5060x_init(void *pic, int irq, int tsc);
-void pcf_reset(struct i2c_slave_s *i2c);
-void pcf_gpo_handler_set(struct i2c_slave_s *i2c, int line,
-                gpio_handler_t handler, void *opaque);
-void pcf_onkey_set(struct i2c_slave_s *i2c, int level);
-void pcf_exton_set(struct i2c_slave_s *i2c, int level);
+i2c_slave *pcf5060x_init(i2c_bus *bus, qemu_irq irq, int tsc);
+void pcf_reset(i2c_slave *i2c);
+void pcf_gpo_handler_set(i2c_slave *i2c, int line, qemu_irq handler);
+void pcf_onkey_set(i2c_slave *i2c, int level);
+void pcf_exton_set(i2c_slave *i2c, int level);
+#endif

Modified: trunk/src/host/qemu-neo1973/hw/i8254.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/i8254.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/i8254.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -47,7 +47,7 @@
     /* irq handling */
     int64_t next_transition_time;
     QEMUTimer *irq_timer;
-    int irq;
+    qemu_irq irq;
 } PITChannelState;
 
 struct PITState {
@@ -366,7 +366,7 @@
         return;
     expire_time = pit_get_next_transition_time(s, current_time);
     irq_level = pit_get_out1(s, current_time);
-    pic_set_irq(s->irq, irq_level);
+    qemu_set_irq(s->irq, irq_level);
 #ifdef DEBUG_PIT
     printf("irq_level=%d next_delay=%f\n",
            irq_level, 
@@ -460,7 +460,7 @@
     }
 }
 
-PITState *pit_init(int base, int irq)
+PITState *pit_init(int base, qemu_irq irq)
 {
     PITState *pit = &pit_state;
     PITChannelState *s;

Modified: trunk/src/host/qemu-neo1973/hw/i8259.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/i8259.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/i8259.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -44,6 +44,7 @@
     uint8_t rotate_on_auto_eoi;
     uint8_t special_fully_nested_mode;
     uint8_t init4; /* true if 4 byte init */
+    uint8_t single_mode; /* true if slave pic is not initialized */
     uint8_t elcr; /* PIIX edge/trigger selection*/
     uint8_t elcr_mask;
     PicState2 *pics_state;
@@ -53,7 +54,7 @@
     /* 0 is master pic, 1 is slave pic */
     /* XXX: better separation between the two pics */
     PicState pics[2];
-    IRQRequestFunc *irq_request;
+    qemu_irq parent_irq;
     void *irq_request_opaque;
     /* IOAPIC callback support */
     SetIRQFunc *alt_irq_func;
@@ -159,22 +160,29 @@
         }
         printf("pic: cpu_interrupt\n");
 #endif
-        s->irq_request(s->irq_request_opaque, 1);
+        qemu_irq_raise(s->parent_irq);
     }
+
+/* all targets should do this rather than acking the IRQ in the cpu */
+#if defined(TARGET_MIPS)
+    else {
+        qemu_irq_lower(s->parent_irq);
+    }
+#endif
 }
 
 #ifdef DEBUG_IRQ_LATENCY
 int64_t irq_time[16];
 #endif
 
-void pic_set_irq_new(void *opaque, int irq, int level)
+void i8259_set_irq(void *opaque, int irq, int level)
 {
     PicState2 *s = opaque;
 
 #if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
     if (level != irq_level[irq]) {
 #if defined(DEBUG_PIC)
-        printf("pic_set_irq: irq=%d level=%d\n", irq, level);
+        printf("i8259_set_irq: irq=%d level=%d\n", irq, level);
 #endif
         irq_level[irq] = level;
 #ifdef DEBUG_IRQ_COUNT
@@ -195,12 +203,6 @@
     pic_update_irq(s);
 }
 
-/* obsolete function */
-void pic_set_irq(int irq, int level)
-{
-    pic_set_irq_new(isa_pic, irq, level);
-}
-
 /* acknowledge interrupt 'irq' */
 static inline void pic_intack(PicState *s, int irq)
 {
@@ -271,6 +273,7 @@
     s->rotate_on_auto_eoi = 0;
     s->special_fully_nested_mode = 0;
     s->init4 = 0;
+    s->single_mode = 0;
     /* Note: ELCR is not reset */
 }
 
@@ -288,11 +291,10 @@
             /* init */
             pic_reset(s);
             /* deassert a pending interrupt */
-            s->pics_state->irq_request(s->pics_state->irq_request_opaque, 0);
+            qemu_irq_lower(s->pics_state->parent_irq);
             s->init_state = 1;
             s->init4 = val & 1;
-            if (val & 0x02)
-                hw_error("single mode not supported");
+            s->single_mode = val & 2;
             if (val & 0x08)
                 hw_error("level sensitive irq not supported");
         } else if (val & 0x08) {
@@ -349,7 +351,7 @@
             break;
         case 1:
             s->irq_base = val & 0xf8;
-            s->init_state = 2;
+            s->init_state = s->single_mode && s->init4 ? 3 : 2;
             break;
         case 2:
             if (s->init4) {
@@ -461,6 +463,7 @@
     qemu_put_8s(f, &s->rotate_on_auto_eoi);
     qemu_put_8s(f, &s->special_fully_nested_mode);
     qemu_put_8s(f, &s->init4);
+    qemu_put_8s(f, &s->single_mode);
     qemu_put_8s(f, &s->elcr);
 }
 
@@ -485,6 +488,7 @@
     qemu_get_8s(f, &s->rotate_on_auto_eoi);
     qemu_get_8s(f, &s->special_fully_nested_mode);
     qemu_get_8s(f, &s->init4);
+    qemu_get_8s(f, &s->single_mode);
     qemu_get_8s(f, &s->elcr);
     return 0;
 }
@@ -536,9 +540,10 @@
 #endif
 }
 
-PicState2 *pic_init(IRQRequestFunc *irq_request, void *irq_request_opaque)
+qemu_irq *i8259_init(qemu_irq parent_irq)
 {
     PicState2 *s;
+
     s = qemu_mallocz(sizeof(PicState2));
     if (!s)
         return NULL;
@@ -546,11 +551,11 @@
     pic_init1(0xa0, 0x4d1, &s->pics[1]);
     s->pics[0].elcr_mask = 0xf8;
     s->pics[1].elcr_mask = 0xde;
-    s->irq_request = irq_request;
-    s->irq_request_opaque = irq_request_opaque;
+    s->parent_irq = parent_irq;
     s->pics[0].pics_state = s;
     s->pics[1].pics_state = s;
-    return s;
+    isa_pic = s;
+    return qemu_allocate_irqs(i8259_set_irq, s, 16);
 }
 
 void pic_set_alt_irq_func(PicState2 *s, SetIRQFunc *alt_irq_func,

Modified: trunk/src/host/qemu-neo1973/hw/ide.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ide.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/ide.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -2,6 +2,7 @@
  * QEMU IDE disk and CD-ROM Emulator
  * 
  * Copyright (c) 2003 Fabrice Bellard
+ * Copyright (c) 2006 Openedhand Ltd.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -311,9 +312,7 @@
     int mult_sectors;
     int identify_set;
     uint16_t identify_data[256];
-    SetIRQFunc *set_irq;
-    void *irq_opaque;
-    int irq;
+    qemu_irq irq;
     PCIDevice *pci_dev;
     struct BMDMAState *bmdma;
     int drive_serial;
@@ -411,6 +410,7 @@
 } PCIIDEState;
 
 static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb);
+static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret);
 
 static void padstr(char *str, const char *src, int len)
 {
@@ -659,7 +659,7 @@
         if (bm) {
             bm->status |= BM_STATUS_INT;
         }
-        s->set_irq(s->irq_opaque, s->irq, 1);
+        qemu_irq_raise(s->irq);
     }
 }
 
@@ -878,7 +878,7 @@
     ret = bdrv_write(s->bs, sector_num, s->io_buffer, n);
     s->nsector -= n;
     if (s->nsector == 0) {
-        /* no more sector to write */
+        /* no more sectors to write */
         ide_transfer_stop(s);
     } else {
         n1 = s->nsector;
@@ -1148,11 +1148,17 @@
         size = max_size;
     s->lba = -1; /* no sector read */
     s->packet_transfer_size = size;
+    s->io_buffer_size = size;    /* dma: send the reply data as one chunk */
     s->elementary_transfer_size = 0;
     s->io_buffer_index = 0;
 
-    s->status = READY_STAT;
-    ide_atapi_cmd_reply_end(s);
+    if (s->atapi_dma) {
+    	s->status = READY_STAT | DRQ_STAT;
+	ide_dma_start(s, ide_atapi_cmd_read_dma_cb);
+    } else {
+    	s->status = READY_STAT;
+    	ide_atapi_cmd_reply_end(s);
+    }
 }
 
 /* start a CD-CDROM read command */
@@ -1184,14 +1190,23 @@
     }
 
     if (s->io_buffer_size > 0) {
-        if (s->cd_sector_size == 2352) {
-            n = 1;
-            cd_data_to_raw(s->io_buffer, s->lba);
-        } else {
-            n = s->io_buffer_size >> 11;
-        }
+	/*
+	 * For a cdrom read sector command (s->lba != -1),
+	 * adjust the lba for the next s->io_buffer_size chunk
+	 * and dma the current chunk.
+	 * For a command != read (s->lba == -1), just transfer
+	 * the reply data.
+	 */
+	if (s->lba != -1) {
+	    if (s->cd_sector_size == 2352) {
+		n = 1;
+		cd_data_to_raw(s->io_buffer, s->lba);
+	    } else {
+		n = s->io_buffer_size >> 11;
+	    }
+	    s->lba += n;
+	}
         s->packet_transfer_size -= s->io_buffer_size;
-        s->lba += n;
         if (dma_buf_rw(bm, 1) == 0)
             goto eot;
     }
@@ -1255,7 +1270,8 @@
                                int sector_size)
 {
 #ifdef DEBUG_IDE_ATAPI
-    printf("read: LBA=%d nb_sectors=%d\n", lba, nb_sectors);
+    printf("read %s: LBA=%d nb_sectors=%d\n", s->atapi_dma ? "dma" : "pio",
+	lba, nb_sectors);
 #endif
     if (s->atapi_dma) {
         ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size);
@@ -1759,12 +1775,12 @@
                 /* Disable Read and Write Multiple */
                 s->mult_sectors = 0;
                 s->status = READY_STAT;
-            } else if (s->nsector > MAX_MULT_SECTORS || 
-                s->nsector == 0 ||
-                (s->nsector & (s->nsector - 1)) != 0) {
+            } else if ((s->nsector & 0xff) != 0 &&
+                ((s->nsector & 0xff) > MAX_MULT_SECTORS ||
+                 (s->nsector & (s->nsector - 1)) != 0)) {
                 ide_abort_command(s);
             } else {
-                s->mult_sectors = s->nsector;
+                s->mult_sectors = s->nsector & 0xff;
                 s->status = READY_STAT;
             }
             ide_set_irq(s);
@@ -1864,6 +1880,8 @@
                 goto abort_cmd;
             /* XXX: valid for CDROM ? */
             switch(s->feature) {
+            case 0xcc: /* reverting to power-on defaults enable */
+            case 0x66: /* reverting to power-on defaults disable */
             case 0x02: /* write cache enable */
             case 0x82: /* write cache disable */
             case 0xaa: /* read look-ahead enable */
@@ -1874,8 +1892,6 @@
             case 0x67: /* NOP */
             case 0x96: /* NOP */
             case 0x9a: /* NOP */
-            case 0x66: /* disable power on reset at soft reset */
-            case 0xcc: /* enable power on reset at soft reset */
                 s->status = READY_STAT | SEEK_STAT;
                 ide_set_irq(s);
                 break;
@@ -1915,7 +1931,7 @@
             ide_set_irq(s);
             break;
 	case WIN_STANDBYNOW1:
-	case WIN_STANDBYNOW2:
+        case WIN_STANDBYNOW2:
         case WIN_IDLEIMMEDIATE:
         case CFA_IDLEIMMEDIATE:
         case WIN_SETIDLE1:
@@ -2107,7 +2123,7 @@
             ret = 0;
         else
             ret = s->status;
-        s->set_irq(s->irq_opaque, s->irq, 0);
+        qemu_irq_lower(s->irq);
         break;
     }
 #ifdef DEBUG_IDE
@@ -2306,7 +2322,7 @@
 
 static void ide_init2(IDEState *ide_state,
                       BlockDriverState *hd0, BlockDriverState *hd1,
-                      SetIRQFunc *set_irq, void *irq_opaque, int irq)
+                      qemu_irq irq)
 {
     IDEState *s;
     static int drive_serial = 1;
@@ -2377,8 +2393,6 @@
             }
         }
         s->drive_serial = drive_serial++;
-        s->set_irq = set_irq;
-        s->irq_opaque = irq_opaque;
         s->irq = irq;
         s->sector_write_timer = qemu_new_timer(vm_clock, 
                                                ide_sector_write_timer_cb, s);
@@ -2405,7 +2419,7 @@
 /***********************************************************/
 /* ISA IDE definitions */
 
-void isa_ide_init(int iobase, int iobase2, int irq,
+void isa_ide_init(int iobase, int iobase2, qemu_irq irq,
                   BlockDriverState *hd0, BlockDriverState *hd1)
 {
     IDEState *ide_state;
@@ -2414,7 +2428,7 @@
     if (!ide_state)
         return;
     
-    ide_init2(ide_state, hd0, hd1, pic_set_irq_new, isa_pic, irq);
+    ide_init2(ide_state, hd0, hd1, irq);
     ide_init_ioport(ide_state, iobase, iobase2);
 }
 
@@ -2454,7 +2468,6 @@
         return;
     bm->ide_if = s;
     bm->dma_cb = dma_cb;
-    bm->cur_addr = bm->addr;
     bm->cur_prd_last = 0;
     bm->cur_prd_addr = 0;
     bm->cur_prd_len = 0;
@@ -2587,6 +2600,7 @@
     printf("%s: 0x%08x\n", __func__, val);
 #endif
     bm->addr = val & ~3;
+    bm->cur_addr = bm->addr;
 }
 
 static void bmdma_map(PCIDevice *pci_dev, int region_num, 
@@ -2621,7 +2635,7 @@
                  !(d->dev.config[MRDMODE] & MRDMODE_BLK_CH0)) ||
         ((d->dev.config[MRDMODE] & MRDMODE_INTR_CH1) &&
          !(d->dev.config[MRDMODE] & MRDMODE_BLK_CH1));
-    pci_set_irq((PCIDevice *)d, 0, pci_level);
+    qemu_set_irq(d->dev.irq[0], pci_level);
 }
 
 /* the PCI irq level is the logical OR of the two channels */
@@ -2645,6 +2659,7 @@
     PCIIDEState *d;
     uint8_t *pci_conf;
     int i;
+    qemu_irq *irq;
 
     d = (PCIIDEState *)pci_register_device(bus, "CMD646 IDE", 
                                            sizeof(PCIIDEState),
@@ -2684,10 +2699,10 @@
     
     for(i = 0; i < 4; i++)
         d->ide_if[i].pci_dev = (PCIDevice *)d;
-    ide_init2(&d->ide_if[0], hd_table[0], hd_table[1],
-              cmd646_set_irq, d, 0);
-    ide_init2(&d->ide_if[2], hd_table[2], hd_table[3],
-              cmd646_set_irq, d, 1);
+
+    irq = qemu_allocate_irqs(cmd646_set_irq, d, 2);
+    ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], irq[0]);
+    ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], irq[1]);
 }
 
 static void pci_ide_save(QEMUFile* f, void *opaque)
@@ -2801,9 +2816,21 @@
     return 0;
 }
 
+static void piix3_reset(PCIIDEState *d)
+{
+    uint8_t *pci_conf = d->dev.config;
+
+    pci_conf[0x04] = 0x00;
+    pci_conf[0x05] = 0x00;
+    pci_conf[0x06] = 0x80; /* FBC */
+    pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
+    pci_conf[0x20] = 0x01; /* BMIBA: 20-23h */
+}
+
 /* hd_table must contain 4 block drivers */
 /* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
-void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn)
+void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
+                        qemu_irq *pic)
 {
     PCIIDEState *d;
     uint8_t *pci_conf;
@@ -2825,13 +2852,13 @@
     pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
     pci_conf[0x0e] = 0x00; // header_type
 
+    piix3_reset(d);
+
     pci_register_io_region((PCIDevice *)d, 4, 0x10, 
                            PCI_ADDRESS_SPACE_IO, bmdma_map);
 
-    ide_init2(&d->ide_if[0], hd_table[0], hd_table[1],
-              pic_set_irq_new, isa_pic, 14);
-    ide_init2(&d->ide_if[2], hd_table[2], hd_table[3],
-              pic_set_irq_new, isa_pic, 15);
+    ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], pic[14]);
+    ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], pic[15]);
     ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
     ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
 
@@ -2950,15 +2977,13 @@
 /* hd_table must contain 4 block drivers */
 /* PowerMac uses memory mapped registers, not I/O. Return the memory
    I/O index to access the ide. */
-int pmac_ide_init (BlockDriverState **hd_table,
-                   SetIRQFunc *set_irq, void *irq_opaque, int irq)
+int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq)
 {
     IDEState *ide_if;
     int pmac_ide_memory;
 
     ide_if = qemu_mallocz(sizeof(IDEState) * 2);
-    ide_init2(&ide_if[0], hd_table[0], hd_table[1],
-              set_irq, irq_opaque, irq);
+    ide_init2(&ide_if[0], hd_table[0], hd_table[1], irq);
     
     pmac_ide_memory = cpu_register_io_memory(0, pmac_ide_read,
                                              pmac_ide_write, &ide_if[0]);
@@ -2968,4 +2993,492 @@
 /***********************************************************/
 /* CF-ATA Microdrive */
 
-#include "md.c"
+#define METADATA_SIZE	0x20
+
+/* DSCM-1XXXX Microdrive hard disk with CF+ II / PCMCIA interface.  */
+struct md_s {
+    IDEState ide[2];
+    struct pcmcia_card_s card;
+    uint32_t attr_base;
+    uint32_t io_base;
+
+    /* Card state */
+    uint8_t opt;
+    uint8_t stat;
+    uint8_t pins;
+
+    uint8_t ctrl;
+    uint16_t io;
+    int cycle;
+};
+
+/* Register bitfields */
+enum md_opt {
+    OPT_MODE_MMAP	= 0,
+    OPT_MODE_IOMAP16	= 1,
+    OPT_MODE_IOMAP1	= 2,
+    OPT_MODE_IOMAP2	= 3,
+    OPT_MODE		= 0x3f,
+    OPT_LEVIREQ		= 0x40,
+    OPT_SRESET		= 0x80,
+};
+enum md_cstat {
+    STAT_INT		= 0x02,
+    STAT_PWRDWN		= 0x04,
+    STAT_XE		= 0x10,
+    STAT_IOIS8		= 0x20,
+    STAT_SIGCHG		= 0x40,
+    STAT_CHANGED	= 0x80,
+};
+enum md_pins {
+    PINS_MRDY		= 0x02,
+    PINS_CRDY		= 0x20,
+};
+enum md_ctrl {
+    CTRL_IEN		= 0x02,
+    CTRL_SRST		= 0x04,
+};
+
+static inline void md_interrupt_update(struct md_s *s)
+{
+    if (!s->card.slot)
+        return;
+
+    qemu_set_irq(s->card.slot->irq,
+                    !(s->stat & STAT_INT) &&	/* Inverted */
+                    !(s->ctrl & (CTRL_IEN | CTRL_SRST)) &&
+                    !(s->opt & OPT_SRESET));
+}
+
+static void md_set_irq(void *opaque, int irq, int level)
+{
+    struct md_s *s = (struct md_s *) opaque;
+    if (level)
+        s->stat |= STAT_INT;
+    else
+        s->stat &= ~STAT_INT;
+
+    md_interrupt_update(s);
+}
+
+static void md_reset(struct md_s *s)
+{
+    s->opt = OPT_MODE_MMAP;
+    s->stat = 0;
+    s->pins = 0;
+    s->cycle = 0;
+    s->ctrl = 0;
+    ide_reset(s->ide);
+}
+
+static uint8_t md_attr_read(void *opaque, uint32_t at)
+{
+    struct md_s *s = (struct md_s *) opaque;
+    if (at < s->attr_base) {
+        if (at < s->card.cis_len)
+            return s->card.cis[at];
+        else
+            return 0x00;
+    }
+
+    at -= s->attr_base;
+
+    switch (at) {
+    case 0x00:	/* Configuration Option Register */
+        return s->opt;
+    case 0x02:	/* Card Configuration Status Register */
+        if (s->ctrl & CTRL_IEN)
+            return s->stat & ~STAT_INT;
+        else
+            return s->stat;
+    case 0x04:	/* Pin Replacement Register */
+        return (s->pins & PINS_CRDY) | 0x0c;
+    case 0x06:	/* Socket and Copy Register */
+        return 0x00;
+#ifdef VERBOSE
+    default:
+        printf("%s: Bad attribute space register %02x\n", __FUNCTION__, at);
+#endif
+    }
+
+    return 0;
+}
+
+static void md_attr_write(void *opaque, uint32_t at, uint8_t value)
+{
+    struct md_s *s = (struct md_s *) opaque;
+    at -= s->attr_base;
+
+    switch (at) {
+    case 0x00:	/* Configuration Option Register */
+        s->opt = value & 0xcf;
+        if (value & OPT_SRESET)
+            md_reset(s);
+        md_interrupt_update(s);
+        break;
+    case 0x02:	/* Card Configuration Status Register */
+        if ((s->stat ^ value) & STAT_PWRDWN)
+            s->pins |= PINS_CRDY;
+        s->stat &= 0x82;
+        s->stat |= value & 0x74;
+        md_interrupt_update(s);
+        /* Word 170 in Identify Device must be equal to STAT_XE */
+        break;
+    case 0x04:	/* Pin Replacement Register */
+        s->pins &= PINS_CRDY;
+        s->pins |= value & PINS_MRDY;
+        break;
+    case 0x06:	/* Socket and Copy Register */
+        break;
+    default:
+        printf("%s: Bad attribute space register %02x\n", __FUNCTION__, at);
+    }
+}
+
+static uint16_t md_common_read(void *opaque, uint32_t at)
+{
+    struct md_s *s = (struct md_s *) opaque;
+    uint16_t ret;
+    at -= s->io_base;
+
+    switch (s->opt & OPT_MODE) {
+    case OPT_MODE_MMAP:
+        if ((at & ~0x3ff) == 0x400)
+            at = 0;
+        break;
+    case OPT_MODE_IOMAP16:
+        at &= 0xf;
+        break;
+    case OPT_MODE_IOMAP1:
+        if ((at & ~0xf) == 0x3f0)
+            at -= 0x3e8;
+        else if ((at & ~0xf) == 0x1f0)
+            at -= 0x1f0;
+        break;
+    case OPT_MODE_IOMAP2:
+        if ((at & ~0xf) == 0x370)
+            at -= 0x368;
+        else if ((at & ~0xf) == 0x170)
+            at -= 0x170;
+    }
+
+    switch (at) {
+    case 0x0:	/* Even RD Data */
+    case 0x8:
+        return ide_data_readw(s->ide, 0);
+
+        /* TODO: 8-bit accesses */
+        if (s->cycle)
+            ret = s->io >> 8;
+        else {
+            s->io = ide_data_readw(s->ide, 0);
+            ret = s->io & 0xff;
+        }
+        s->cycle = !s->cycle;
+        return ret;
+    case 0x9:	/* Odd RD Data */
+        return s->io >> 8;
+    case 0xd:	/* Error */
+        return ide_ioport_read(s->ide, 0x1);
+    case 0xe:	/* Alternate Status */
+        if (s->ide->cur_drive->bs)
+            return s->ide->cur_drive->status;
+        else
+            return 0;
+    case 0xf:	/* Device Address */
+        return 0xc2 | ((~s->ide->select << 2) & 0x3c);
+    default:
+        return ide_ioport_read(s->ide, at);
+    }
+
+    return 0;
+}
+
+static void md_common_write(void *opaque, uint32_t at, uint16_t value)
+{
+    struct md_s *s = (struct md_s *) opaque;
+    at -= s->io_base;
+
+    switch (s->opt & OPT_MODE) {
+    case OPT_MODE_MMAP:
+        if ((at & ~0x3ff) == 0x400)
+            at = 0;
+        break;
+    case OPT_MODE_IOMAP16:
+        at &= 0xf;
+        break;
+    case OPT_MODE_IOMAP1:
+        if ((at & ~0xf) == 0x3f0)
+            at -= 0x3e8;
+        else if ((at & ~0xf) == 0x1f0)
+            at -= 0x1f0;
+        break;
+    case OPT_MODE_IOMAP2:
+        if ((at & ~0xf) == 0x370)
+            at -= 0x368;
+        else if ((at & ~0xf) == 0x170)
+            at -= 0x170;
+    }
+
+    switch (at) {
+    case 0x0:	/* Even WR Data */
+    case 0x8:
+        ide_data_writew(s->ide, 0, value);
+        break;
+
+        /* TODO: 8-bit accesses */
+        if (s->cycle)
+            ide_data_writew(s->ide, 0, s->io | (value << 8));
+        else
+            s->io = value & 0xff;
+        s->cycle = !s->cycle;
+        break;
+    case 0x9:
+        s->io = value & 0xff;
+        s->cycle = !s->cycle;
+        break;
+    case 0xd:	/* Features */
+        ide_ioport_write(s->ide, 0x1, value);
+        break;
+    case 0xe:	/* Device Control */
+        s->ctrl = value;
+        if (value & CTRL_SRST)
+            md_reset(s);
+        md_interrupt_update(s);
+        break;
+    default:
+        if (s->stat & STAT_PWRDWN) {
+            s->pins |= PINS_CRDY;
+            s->stat &= ~STAT_PWRDWN;
+        }
+        ide_ioport_write(s->ide, at, value);
+    }
+}
+
+static const uint8_t dscm1xxxx_cis[0x14a] = {
+    [0x000] = CISTPL_DEVICE,	/* 5V Device Information */
+    [0x002] = 0x03,		/* Tuple length = 4 bytes */
+    [0x004] = 0xdb,		/* ID: DTYPE_FUNCSPEC, non WP, DSPEED_150NS */
+    [0x006] = 0x01,		/* Size = 2K bytes */
+    [0x008] = CISTPL_ENDMARK,
+
+    [0x00a] = CISTPL_DEVICE_OC,	/* Additional Device Information */
+    [0x00c] = 0x04,		/* Tuple length = 4 byest */
+    [0x00e] = 0x03,		/* Conditions: Ext = 0, Vcc 3.3V, MWAIT = 1 */
+    [0x010] = 0xdb,		/* ID: DTYPE_FUNCSPEC, non WP, DSPEED_150NS */
+    [0x012] = 0x01,		/* Size = 2K bytes */
+    [0x014] = CISTPL_ENDMARK,
+
+    [0x016] = CISTPL_JEDEC_C,	/* JEDEC ID */
+    [0x018] = 0x02,		/* Tuple length = 2 bytes */
+    [0x01a] = 0xdf,		/* PC Card ATA with no Vpp required */
+    [0x01c] = 0x01,
+
+    [0x01e] = CISTPL_MANFID,	/* Manufacture ID */
+    [0x020] = 0x04,		/* Tuple length = 4 bytes */
+    [0x022] = 0xa4,		/* TPLMID_MANF = 00a4 (IBM) */
+    [0x024] = 0x00,
+    [0x026] = 0x00,		/* PLMID_CARD = 0000 */
+    [0x028] = 0x00,
+
+    [0x02a] = CISTPL_VERS_1,	/* Level 1 Version */
+    [0x02c] = 0x12,		/* Tuple length = 23 bytes */
+    [0x02e] = 0x04,		/* Major Version = JEIDA 4.2 / PCMCIA 2.1 */
+    [0x030] = 0x01,		/* Minor Version = 1 */
+    [0x032] = 'I',
+    [0x034] = 'B',
+    [0x036] = 'M',
+    [0x038] = 0x00,
+    [0x03a] = 'm',
+    [0x03c] = 'i',
+    [0x03e] = 'c',
+    [0x040] = 'r',
+    [0x042] = 'o',
+    [0x044] = 'd',
+    [0x046] = 'r',
+    [0x048] = 'i',
+    [0x04a] = 'v',
+    [0x04c] = 'e',
+    [0x04e] = 0x00,
+    [0x050] = CISTPL_ENDMARK,
+
+    [0x052] = CISTPL_FUNCID,	/* Function ID */
+    [0x054] = 0x02,		/* Tuple length = 2 bytes */
+    [0x056] = 0x04,		/* TPLFID_FUNCTION = Fixed Disk */
+    [0x058] = 0x01,		/* TPLFID_SYSINIT: POST = 1, ROM = 0 */
+
+    [0x05a] = CISTPL_FUNCE,	/* Function Extension */
+    [0x05c] = 0x02,		/* Tuple length = 2 bytes */
+    [0x05e] = 0x01,		/* TPLFE_TYPE = Disk Device Interface */
+    [0x060] = 0x01,		/* TPLFE_DATA = PC Card ATA Interface */
+
+    [0x062] = CISTPL_FUNCE,	/* Function Extension */
+    [0x064] = 0x03,		/* Tuple length = 3 bytes */
+    [0x066] = 0x02,		/* TPLFE_TYPE = Basic PC Card ATA Interface */
+    [0x068] = 0x08,		/* TPLFE_DATA: Rotating, Unique, Single */
+    [0x06a] = 0x0f,		/* TPLFE_DATA: Sleep, Standby, Idle, Auto */
+
+    [0x06c] = CISTPL_CONFIG,	/* Configuration */
+    [0x06e] = 0x05,		/* Tuple length = 5 bytes */
+    [0x070] = 0x01,		/* TPCC_RASZ = 2 bytes, TPCC_RMSZ = 1 byte */
+    [0x072] = 0x07,		/* TPCC_LAST = 7 */
+    [0x074] = 0x00,		/* TPCC_RADR = 0200 */
+    [0x076] = 0x02,
+    [0x078] = 0x0f,		/* TPCC_RMSK = 200, 202, 204, 206 */
+
+    [0x07a] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
+    [0x07c] = 0x0b,		/* Tuple length = 11 bytes */
+    [0x07e] = 0xc0,		/* TPCE_INDX = Memory Mode, Default, Iface */
+    [0x080] = 0xc0,		/* TPCE_IF = Memory, no BVDs, no WP, READY */
+    [0x082] = 0xa1,		/* TPCE_FS = Vcc only, no I/O, Memory, Misc */
+    [0x084] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
+    [0x086] = 0x55,		/* NomV: 5.0 V */
+    [0x088] = 0x4d,		/* MinV: 4.5 V */
+    [0x08a] = 0x5d,		/* MaxV: 5.5 V */
+    [0x08c] = 0x4e,		/* Peakl: 450 mA */
+    [0x08e] = 0x08,		/* TPCE_MS = 1 window, 1 byte, Host address */
+    [0x090] = 0x00,		/* Window descriptor: Window length = 0 */
+    [0x092] = 0x20,		/* TPCE_MI: support power down mode, RW */
+
+    [0x094] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
+    [0x096] = 0x06,		/* Tuple length = 6 bytes */
+    [0x098] = 0x00,		/* TPCE_INDX = Memory Mode, no Default */
+    [0x09a] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
+    [0x09c] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
+    [0x09e] = 0xb5,		/* NomV: 3.3 V */
+    [0x0a0] = 0x1e,
+    [0x0a2] = 0x3e,		/* Peakl: 350 mA */
+
+    [0x0a4] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
+    [0x0a6] = 0x0d,		/* Tuple length = 13 bytes */
+    [0x0a8] = 0xc1,		/* TPCE_INDX = I/O and Memory Mode, Default */
+    [0x0aa] = 0x41,		/* TPCE_IF = I/O and Memory, no BVD, no WP */
+    [0x0ac] = 0x99,		/* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
+    [0x0ae] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
+    [0x0b0] = 0x55,		/* NomV: 5.0 V */
+    [0x0b2] = 0x4d,		/* MinV: 4.5 V */
+    [0x0b4] = 0x5d,		/* MaxV: 5.5 V */
+    [0x0b6] = 0x4e,		/* Peakl: 450 mA */
+    [0x0b8] = 0x64,		/* TPCE_IO = 16-byte boundary, 16/8 accesses */
+    [0x0ba] = 0xf0,		/* TPCE_IR =  MASK, Level, Pulse, Share */
+    [0x0bc] = 0xff,		/* IRQ0..IRQ7 supported */
+    [0x0be] = 0xff,		/* IRQ8..IRQ15 supported */
+    [0x0c0] = 0x20,		/* TPCE_MI = support power down mode */
+
+    [0x0c2] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
+    [0x0c4] = 0x06,		/* Tuple length = 6 bytes */
+    [0x0c6] = 0x01,		/* TPCE_INDX = I/O and Memory Mode */
+    [0x0c8] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
+    [0x0ca] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
+    [0x0cc] = 0xb5,		/* NomV: 3.3 V */
+    [0x0ce] = 0x1e,
+    [0x0d0] = 0x3e,		/* Peakl: 350 mA */
+
+    [0x0d2] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
+    [0x0d4] = 0x12,		/* Tuple length = 18 bytes */
+    [0x0d6] = 0xc2,		/* TPCE_INDX = I/O Primary Mode */
+    [0x0d8] = 0x41,		/* TPCE_IF = I/O and Memory, no BVD, no WP */
+    [0x0da] = 0x99,		/* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
+    [0x0dc] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
+    [0x0de] = 0x55,		/* NomV: 5.0 V */
+    [0x0e0] = 0x4d,		/* MinV: 4.5 V */
+    [0x0e2] = 0x5d,		/* MaxV: 5.5 V */
+    [0x0e4] = 0x4e,		/* Peakl: 450 mA */
+    [0x0e6] = 0xea,		/* TPCE_IO = 1K boundary, 16/8 access, Range */
+    [0x0e8] = 0x61,		/* Range: 2 fields, 2 bytes addr, 1 byte len */
+    [0x0ea] = 0xf0,		/* Field 1 address = 0x01f0 */
+    [0x0ec] = 0x01,
+    [0x0ee] = 0x07,		/* Address block length = 8 */
+    [0x0f0] = 0xf6,		/* Field 2 address = 0x03f6 */
+    [0x0f2] = 0x03,
+    [0x0f4] = 0x01,		/* Address block length = 2 */
+    [0x0f6] = 0xee,		/* TPCE_IR = IRQ E, Level, Pulse, Share */
+    [0x0f8] = 0x20,		/* TPCE_MI = support power down mode */
+
+    [0x0fa] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
+    [0x0fc] = 0x06,		/* Tuple length = 6 bytes */
+    [0x0fe] = 0x02,		/* TPCE_INDX = I/O Primary Mode, no Default */
+    [0x100] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
+    [0x102] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
+    [0x104] = 0xb5,		/* NomV: 3.3 V */
+    [0x106] = 0x1e,
+    [0x108] = 0x3e,		/* Peakl: 350 mA */
+
+    [0x10a] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
+    [0x10c] = 0x12,		/* Tuple length = 18 bytes */
+    [0x10e] = 0xc3,		/* TPCE_INDX = I/O Secondary Mode, Default */
+    [0x110] = 0x41,		/* TPCE_IF = I/O and Memory, no BVD, no WP */
+    [0x112] = 0x99,		/* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
+    [0x114] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
+    [0x116] = 0x55,		/* NomV: 5.0 V */
+    [0x118] = 0x4d,		/* MinV: 4.5 V */
+    [0x11a] = 0x5d,		/* MaxV: 5.5 V */
+    [0x11c] = 0x4e,		/* Peakl: 450 mA */
+    [0x11e] = 0xea,		/* TPCE_IO = 1K boundary, 16/8 access, Range */
+    [0x120] = 0x61,		/* Range: 2 fields, 2 byte addr, 1 byte len */
+    [0x122] = 0x70,		/* Field 1 address = 0x0170 */
+    [0x124] = 0x01,
+    [0x126] = 0x07,		/* Address block length = 8 */
+    [0x128] = 0x76,		/* Field 2 address = 0x0376 */
+    [0x12a] = 0x03,
+    [0x12c] = 0x01,		/* Address block length = 2 */
+    [0x12e] = 0xee,		/* TPCE_IR = IRQ E, Level, Pulse, Share */
+    [0x130] = 0x20,		/* TPCE_MI = support power down mode */
+
+    [0x132] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
+    [0x134] = 0x06,		/* Tuple length = 6 bytes */
+    [0x136] = 0x03,		/* TPCE_INDX = I/O Secondary Mode */
+    [0x138] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
+    [0x13a] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
+    [0x13c] = 0xb5,		/* NomV: 3.3 V */
+    [0x13e] = 0x1e,
+    [0x140] = 0x3e,		/* Peakl: 350 mA */
+
+    [0x142] = CISTPL_NO_LINK,	/* No Link */
+    [0x144] = 0x00,		/* Tuple length = 0 bytes */
+
+    [0x146] = CISTPL_END,	/* Tuple End */
+};
+
+static int dscm1xxxx_attach(void *opaque)
+{
+    struct md_s *md = (struct md_s *) opaque;
+    md->card.attr_read = md_attr_read;
+    md->card.attr_write = md_attr_write;
+    md->card.common_read = md_common_read;
+    md->card.common_write = md_common_write;
+    md->card.io_read = md_common_read;
+    md->card.io_write = md_common_write;
+
+    md->attr_base = md->card.cis[0x74] | (md->card.cis[0x76] << 8);
+    md->io_base = 0x0;
+
+    md_reset(md);
+    md_interrupt_update(md);
+
+    md->card.slot->card_string = "DSCM-1xxxx Hitachi Microdrive";
+    return 0;
+}
+
+static int dscm1xxxx_detach(void *opaque)
+{
+    struct md_s *md = (struct md_s *) opaque;
+    md_reset(md);
+    return 0;
+}
+
+struct pcmcia_card_s *dscm1xxxx_init(BlockDriverState *bdrv)
+{
+    struct md_s *md = (struct md_s *) qemu_mallocz(sizeof(struct md_s));
+    md->card.state = md;
+    md->card.attach = dscm1xxxx_attach;
+    md->card.detach = dscm1xxxx_detach;
+    md->card.cis = dscm1xxxx_cis;
+    md->card.cis_len = sizeof(dscm1xxxx_cis);
+
+    ide_init2(md->ide, bdrv, 0, qemu_allocate_irqs(md_set_irq, md, 1)[0]);
+    md->ide->is_cf = 1;
+    md->ide->mdata_size = METADATA_SIZE;
+    md->ide->mdata_storage = (uint8_t *) qemu_mallocz(METADATA_SIZE);
+    return &md->card;
+}

Modified: trunk/src/host/qemu-neo1973/hw/integratorcp.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/integratorcp.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/integratorcp.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /* 
  * ARM Integrator CP System emulation.
  *
- * Copyright (c) 2005-2006 CodeSourcery.
+ * Copyright (c) 2005-2007 CodeSourcery.
  * Written by Paul Brook
  *
  * This code is licenced under the GPL
@@ -267,28 +267,22 @@
 
 typedef struct icp_pic_state
 {
-  arm_pic_handler handler;
   uint32_t base;
   uint32_t level;
   uint32_t irq_enabled;
   uint32_t fiq_enabled;
-  void *parent;
-  int parent_irq;
-  int parent_fiq;
+  qemu_irq parent_irq;
+  qemu_irq parent_fiq;
 } icp_pic_state;
 
 static void icp_pic_update(icp_pic_state *s)
 {
     uint32_t flags;
 
-    if (s->parent_irq != -1) {
-        flags = (s->level & s->irq_enabled);
-        pic_set_irq_new(s->parent, s->parent_irq, flags != 0);
-    }
-    if (s->parent_fiq != -1) {
-        flags = (s->level & s->fiq_enabled);
-        pic_set_irq_new(s->parent, s->parent_fiq, flags != 0);
-    }
+    flags = (s->level & s->irq_enabled);
+    qemu_set_irq(s->parent_irq, flags != 0);
+    flags = (s->level & s->fiq_enabled);
+    qemu_set_irq(s->parent_fiq, flags != 0);
 }
 
 static void icp_pic_set_irq(void *opaque, int irq, int level)
@@ -345,11 +339,11 @@
         break;
     case 4: /* INT_SOFTSET */
         if (value & 1)
-            pic_set_irq_new(s, 0, 1);
+            icp_pic_set_irq(s, 0, 1);
         break;
     case 5: /* INT_SOFTCLR */
         if (value & 1)
-            pic_set_irq_new(s, 0, 0);
+            icp_pic_set_irq(s, 0, 0);
         break;
     case 10: /* FRQ_ENABLESET */
         s->fiq_enabled |= value;
@@ -380,25 +374,25 @@
    icp_pic_write
 };
 
-static icp_pic_state *icp_pic_init(uint32_t base, void *parent,
-                                   int parent_irq, int parent_fiq)
+static qemu_irq *icp_pic_init(uint32_t base,
+                              qemu_irq parent_irq, qemu_irq parent_fiq)
 {
     icp_pic_state *s;
     int iomemtype;
+    qemu_irq *qi;
 
     s = (icp_pic_state *)qemu_mallocz(sizeof(icp_pic_state));
     if (!s)
         return NULL;
-    s->handler = icp_pic_set_irq;
+    qi = qemu_allocate_irqs(icp_pic_set_irq, s, 32);
     s->base = base;
-    s->parent = parent;
     s->parent_irq = parent_irq;
     s->parent_fiq = parent_fiq;
     iomemtype = cpu_register_io_memory(0, icp_pic_readfn,
                                        icp_pic_writefn, s);
     cpu_register_physical_memory(base, 0x007fffff, iomemtype);
     /* ??? Save/restore.  */
-    return s;
+    return qi;
 }
 
 /* CP control registers.  */
@@ -471,15 +465,17 @@
 static void integratorcp_init(int ram_size, int vga_ram_size, int boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
-                     const char *initrd_filename, uint32_t cpuid)
+                     const char *initrd_filename, const char *cpu_model)
 {
     CPUState *env;
     uint32_t bios_offset;
-    icp_pic_state *pic;
-    void *cpu_pic;
+    qemu_irq *pic;
+    qemu_irq *cpu_pic;
 
     env = cpu_init();
-    cpu_arm_set_model(env, cpuid);
+    if (!cpu_model)
+        cpu_model = "arm926";
+    cpu_arm_set_model(env, cpu_model);
     bios_offset = ram_size + vga_ram_size;
     /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
     /* ??? RAM shoud repeat to fill physical memory space.  */
@@ -490,57 +486,33 @@
 
     integratorcm_init(ram_size >> 20, bios_offset);
     cpu_pic = arm_pic_init_cpu(env);
-    pic = icp_pic_init(0x14000000, cpu_pic, ARM_PIC_CPU_IRQ, ARM_PIC_CPU_FIQ);
-    icp_pic_init(0xca000000, pic, 26, -1);
+    pic = icp_pic_init(0x14000000, cpu_pic[ARM_PIC_CPU_IRQ],
+                       cpu_pic[ARM_PIC_CPU_FIQ]);
+    icp_pic_init(0xca000000, pic[26], NULL);
     icp_pit_init(0x13000000, pic, 5);
-    pl011_init(0x16000000, pic, 1, serial_hds[0]);
-    pl011_init(0x17000000, pic, 2, serial_hds[1]);
+    pl011_init(0x16000000, pic[1], serial_hds[0]);
+    pl011_init(0x17000000, pic[2], serial_hds[1]);
     icp_control_init(0xcb000000);
-    pl050_init(0x18000000, pic, 3, 0);
-    pl050_init(0x19000000, pic, 4, 1);
+    pl050_init(0x18000000, pic[3], 0);
+    pl050_init(0x19000000, pic[4], 1);
+    pl181_init(0x1c000000, sd_bdrv, pic[23], pic[24]);
     if (nd_table[0].vlan) {
         if (nd_table[0].model == NULL
             || strcmp(nd_table[0].model, "smc91c111") == 0) {
-            smc91c111_init(&nd_table[0], 0xc8000000, pic, 27);
+            smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
         } else {
             fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
             exit (1);
         }
     }
-    pl110_init(ds, 0xc0000000, pic, 22, 0);
+    pl110_init(ds, 0xc0000000, pic[22], 0);
 
-    arm_load_kernel(ram_size, kernel_filename, kernel_cmdline,
+    arm_load_kernel(env, ram_size, kernel_filename, kernel_cmdline,
                     initrd_filename, 0x113, 0x0);
 }
 
-static void integratorcp926_init(int ram_size, int vga_ram_size,
-    int boot_device, DisplayState *ds, const char **fd_filename, int snapshot,
-    const char *kernel_filename, const char *kernel_cmdline,
-    const char *initrd_filename)
-{
-    integratorcp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
-                      snapshot, kernel_filename, kernel_cmdline,
-                      initrd_filename, ARM_CPUID_ARM926);
-}
-
-static void integratorcp1026_init(int ram_size, int vga_ram_size,
-    int boot_device, DisplayState *ds, const char **fd_filename, int snapshot,
-    const char *kernel_filename, const char *kernel_cmdline,
-    const char *initrd_filename)
-{
-    integratorcp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
-                      snapshot, kernel_filename, kernel_cmdline,
-                      initrd_filename, ARM_CPUID_ARM1026);
-}
-
-QEMUMachine integratorcp926_machine = {
-    "integratorcp926",
+QEMUMachine integratorcp_machine = {
+    "integratorcp",
     "ARM Integrator/CP (ARM926EJ-S)",
-    integratorcp926_init,
+    integratorcp_init,
 };
-
-QEMUMachine integratorcp1026_machine = {
-    "integratorcp1026",
-    "ARM Integrator/CP (ARM1026EJ-S)",
-    integratorcp1026_init,
-};

Added: trunk/src/host/qemu-neo1973/hw/irq.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/irq.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/irq.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,57 @@
+/*
+ * QEMU IRQ/GPIO common code.
+ * 
+ * Copyright (c) 2007 CodeSourcery.
+ * 
+ * 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"
+
+struct IRQState {
+    qemu_irq_handler handler;
+    void *opaque;
+    int n;
+};
+
+void qemu_set_irq(qemu_irq irq, int level)
+{
+    if (!irq)
+        return;
+
+    irq->handler(irq->opaque, irq->n, level);
+}
+
+qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n)
+{
+    qemu_irq *s;
+    struct IRQState *p;
+    int i;
+
+    s = (qemu_irq *)qemu_mallocz(sizeof(qemu_irq) * n);
+    p = (struct IRQState *)qemu_mallocz(sizeof(struct IRQState) * n);
+    for (i = 0; i < n; i++) {
+        p->handler = handler;
+        p->opaque = opaque;
+        p->n = i;
+        s[i] = p;
+        p++;
+    }
+    return s;
+}
+

Added: trunk/src/host/qemu-neo1973/hw/irq.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/irq.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/irq.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,21 @@
+/* Generic IRQ/GPIO pin infrastructure.  */
+
+typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
+
+typedef struct IRQState *qemu_irq;
+
+void qemu_set_irq(qemu_irq irq, int level);
+
+static inline void qemu_irq_raise(qemu_irq irq)
+{
+    qemu_set_irq(irq, 1);
+}
+
+static inline void qemu_irq_lower(qemu_irq irq)
+{
+    qemu_set_irq(irq, 0);
+}
+
+/* Returns an array of N IRQs.  */
+qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n);
+

Modified: trunk/src/host/qemu-neo1973/hw/lsi53c895a.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/lsi53c895a.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/lsi53c895a.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -251,7 +251,7 @@
     uint32_t ia;
     uint32_t sbc;
     uint32_t csbc;
-    uint32_t scratch[13]; /* SCRATCHA-SCRATCHR */
+    uint32_t scratch[18]; /* SCRATCHA-SCRATCHR */
 
     /* Script ram is stored as 32-bit words in host byteorder.  */
     uint32_t script_ram[2048];
@@ -374,7 +374,7 @@
                 level, s->dstat, s->sist1, s->sist0);
         last_level = level;
     }
-    pci_set_irq(&s->pci_dev, 0, level);
+    qemu_set_irq(s->pci_dev.irq[0], level);
 }
 
 /* Stop SCRIPTS execution and raise a SCSI interrupt.  */
@@ -855,6 +855,7 @@
             offset = sxt24(addr);
             cpu_physical_memory_read(s->dsa + offset, (uint8_t *)buf, 8);
             s->dbc = cpu_to_le32(buf[0]);
+            s->rbc = s->dbc;
             addr = cpu_to_le32(buf[1]);
         }
         if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) {
@@ -864,6 +865,8 @@
             break;
         }
         s->dnad = addr;
+        /* ??? Set ESA.  */
+        s->ia = s->dsp - 8;
         switch (s->sstat1 & 0x7) {
         case PHASE_DO:
             s->waiting = 2;
@@ -898,8 +901,6 @@
         s->sbc = s->dbc;
         s->rbc -= s->dbc;
         s->ua = addr + s->dbc;
-        /* ??? Set ESA.  */
-        s->ia = s->dsp - 8;
         break;
 
     case 1: /* IO or Read/Write instruction.  */
@@ -1038,7 +1039,7 @@
                 op0 |= op1;
                 break;
             case 3: /* XOR */
-                op0 |= op1;
+                op0 ^= op1;
                 break;
             case 4: /* AND */
                 op0 &= op1;
@@ -1046,6 +1047,7 @@
             case 5: /* SHR */
                 op1 = op0 & 1;
                 op0 = (op0 >> 1) | (s->carry << 7);
+                s->carry = op1;
                 break;
             case 6: /* ADD */
                 op0 += op1;
@@ -1388,7 +1390,7 @@
         break;
     case 0x02: /* SCNTL2 */
         val &= ~(LSI_SCNTL2_WSR | LSI_SCNTL2_WSS);
-        s->scntl3 = val;
+        s->scntl2 = val;
         break;
     case 0x03: /* SCNTL3 */
         s->scntl3 = val;
@@ -1433,10 +1435,13 @@
         if (val & LSI_ISTAT0_SRST) {
             lsi_soft_reset(s);
         }
+        break;
     case 0x16: /* MBOX0 */
         s->mbox0 = val;
+        break;
     case 0x17: /* MBOX1 */
         s->mbox1 = val;
+        break;
     case 0x1b: /* CTEST3 */
         s->ctest3 = val & 0x0f;
         break;
@@ -1453,19 +1458,19 @@
         }
         s->ctest5 = val;
         break;
-    case 0x2c: /* DSPS[0:7] */
+    case 0x2c: /* DSP[0:7] */
         s->dsp &= 0xffffff00;
         s->dsp |= val;
         break;
-    case 0x2d: /* DSPS[8:15] */
+    case 0x2d: /* DSP[8:15] */
         s->dsp &= 0xffff00ff;
         s->dsp |= val << 8;
         break;
-    case 0x2e: /* DSPS[16:23] */
+    case 0x2e: /* DSP[16:23] */
         s->dsp &= 0xff00ffff;
         s->dsp |= val << 16;
         break;
-    case 0x2f: /* DSPS[14:31] */
+    case 0x2f: /* DSP[24:31] */
         s->dsp &= 0x00ffffff;
         s->dsp |= val << 24;
         if ((s->dmode & LSI_DMODE_MAN) == 0
@@ -1765,7 +1770,7 @@
     lsi_reg_writeb(s, addr, val & 0xff);
     lsi_reg_writeb(s, addr + 1, (val >> 8) & 0xff);
     lsi_reg_writeb(s, addr + 2, (val >> 16) & 0xff);
-    lsi_reg_writeb(s, addr + 2, (val >> 24) & 0xff);
+    lsi_reg_writeb(s, addr + 3, (val >> 24) & 0xff);
 }
 
 static void lsi_io_mapfunc(PCIDevice *pci_dev, int region_num, 

Modified: trunk/src/host/qemu-neo1973/hw/m48t59.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/m48t59.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/m48t59.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /*
  * QEMU M48T59 and M48T08 NVRAM emulation for PPC PREP and Sparc platforms
  * 
- * Copyright (c) 2003-2005 Jocelyn Mayer
+ * Copyright (c) 2003-2005, 2007 Jocelyn Mayer
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -41,7 +41,7 @@
     /* Model parameters */
     int type; // 8 = m48t08, 59 = m48t59
     /* Hardware parameters */
-    int      IRQ;
+    qemu_irq IRQ;
     int mem_index;
     uint32_t mem_base;
     uint32_t io_base;
@@ -100,7 +100,7 @@
     uint64_t next_time;
     m48t59_t *NVRAM = opaque;
 
-    pic_set_irq(NVRAM->IRQ, 1);
+    qemu_set_irq(NVRAM->IRQ, 1);
     if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 && 
 	(NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
 	(NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
@@ -137,7 +137,7 @@
 	next_time = 1 + mktime(&tm_now);
     }
     qemu_mod_timer(NVRAM->alrm_timer, next_time * 1000);
-    pic_set_irq(NVRAM->IRQ, 0);
+    qemu_set_irq(NVRAM->IRQ, 0);
 }
 
 
@@ -173,8 +173,8 @@
         /* May it be a hw CPU Reset instead ? */
         qemu_system_reset_request();
     } else {
-	pic_set_irq(NVRAM->IRQ, 1);
-	pic_set_irq(NVRAM->IRQ, 0);
+	qemu_set_irq(NVRAM->IRQ, 1);
+	qemu_set_irq(NVRAM->IRQ, 0);
     }
 }
 
@@ -575,12 +575,47 @@
     &nvram_readl,
 };
 
+static void m48t59_save(QEMUFile *f, void *opaque)
+{
+    m48t59_t *s = opaque;
+
+    qemu_put_8s(f, &s->lock);
+    qemu_put_be16s(f, &s->addr);
+    qemu_put_buffer(f, s->buffer, s->size);
+}
+
+static int m48t59_load(QEMUFile *f, void *opaque, int version_id)
+{
+    m48t59_t *s = opaque;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    qemu_get_8s(f, &s->lock);
+    qemu_get_be16s(f, &s->addr);
+    qemu_get_buffer(f, s->buffer, s->size);
+
+    return 0;
+}
+
+static void m48t59_reset(void *opaque)
+{
+    m48t59_t *NVRAM = opaque;
+
+    if (NVRAM->alrm_timer != NULL)
+        qemu_del_timer(NVRAM->alrm_timer);
+
+    if (NVRAM->wd_timer != NULL)
+        qemu_del_timer(NVRAM->wd_timer);
+}
+
 /* Initialisation routine */
-m48t59_t *m48t59_init (int IRQ, target_ulong mem_base,
+m48t59_t *m48t59_init (qemu_irq IRQ, target_ulong mem_base,
                        uint32_t io_base, uint16_t size,
                        int type)
 {
     m48t59_t *s;
+    target_ulong save_base;
 
     s = qemu_mallocz(sizeof(m48t59_t));
     if (!s)
@@ -610,5 +645,9 @@
     }
     s->lock = 0;
 
+    qemu_register_reset(m48t59_reset, s);
+    save_base = mem_base ? mem_base : io_base;
+    register_savevm("m48t59", save_base, 1, m48t59_save, m48t59_load, s);
+
     return s;
 }

Modified: trunk/src/host/qemu-neo1973/hw/m48t59.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/m48t59.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/m48t59.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -6,7 +6,7 @@
 void m48t59_write (m48t59_t *NVRAM, uint32_t addr, uint32_t val);
 uint32_t m48t59_read (m48t59_t *NVRAM, uint32_t addr);
 void m48t59_toggle_lock (m48t59_t *NVRAM, int lock);
-m48t59_t *m48t59_init (int IRQ, target_ulong mem_base,
+m48t59_t *m48t59_init (qemu_irq IRQ, target_ulong mem_base,
                        uint32_t io_base, uint16_t size,
                        int type);
 

Modified: trunk/src/host/qemu-neo1973/hw/max111x.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/max111x.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/max111x.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,17 +1,16 @@
 /*
- * MAX1110/1111 ADC chip emulation.
+ * Maxim MAX1110/1111 ADC chip emulation.
  *
  * Copyright (c) 2006 Openedhand Ltd.
  * Written by Andrzej Zaborowski <balrog at zabor.org>
  *
- * This code is licensed under the GPLv2.
+ * This code is licensed under the GNU GPLv2.
  */
 
 #include <vl.h>
 
 struct max111x_s {
-    void (*interrupt)(void *opaque);
-    void *opaque;
+    qemu_irq interrupt;
     uint8_t tb1, rb2, rb3;
     int cycle;
 
@@ -87,10 +86,10 @@
     s->rb3 = (measure << 6) & 0xc0;
 
     if (s->interrupt)
-        s->interrupt(s->opaque);
+        qemu_irq_raise(s->interrupt);
 }
 
-struct max111x_s *max111x_init(void (*cb)(void *opaque), void *opaque)
+static struct max111x_s *max111x_init(qemu_irq cb)
 {
     struct max111x_s *s;
     s = (struct max111x_s *)
@@ -98,7 +97,6 @@
     memset(s, 0, sizeof(struct max111x_s));
 
     s->interrupt = cb;
-    s->opaque = opaque;
 
     /* TODO: add a user interface for setting these */
     s->input[0] = 0xf0;
@@ -113,16 +111,16 @@
     return s;
 }
 
-struct max111x_s *max1110_init(void (*cb)(void *opaque), void *opaque)
+struct max111x_s *max1110_init(qemu_irq cb)
 {
-    struct max111x_s *s = max111x_init(cb, opaque);
+    struct max111x_s *s = max111x_init(cb);
     s->inputs = 8;
     return s;
 }
 
-struct max111x_s *max1111_init(void (*cb)(void *opaque), void *opaque)
+struct max111x_s *max1111_init(qemu_irq cb)
 {
-    struct max111x_s *s = max111x_init(cb, opaque);
+    struct max111x_s *s = max111x_init(cb);
     s->inputs = 4;
     return s;
 }

Modified: trunk/src/host/qemu-neo1973/hw/max7310.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/max7310.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/max7310.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -10,22 +10,24 @@
 #include "vl.h"
 
 struct max7310_s {
+    i2c_slave i2c;
+    int i2c_command_byte;
+    int len;
+
     uint8_t level;
     uint8_t direction;
     uint8_t polarity;
     uint8_t status;
     uint8_t command;
-    int i2c_dir;
-    struct i2c_slave_s i2c;
     struct {
         gpio_handler_t fn;
         void *opaque;
     } handler[8];
 };
 
-void max7310_reset(struct i2c_slave_s *i2c)
+void max7310_reset(i2c_slave *i2c)
 {
-    struct max7310_s *s = (struct max7310_s *) i2c->opaque;
+    struct max7310_s *s = (struct max7310_s *) i2c;
     s->level &= s->direction;
     s->direction = 0xff;
     s->polarity = 0xf0;
@@ -33,91 +35,87 @@
     s->command = 0x00;
 }
 
-static void max7310_start(void *opaque, int dir)
+static int max7310_rx(i2c_slave *i2c)
 {
-    struct max7310_s *s = (struct max7310_s *) opaque;
-    s->i2c_dir = dir;
-}
+    struct max7310_s *s = (struct max7310_s *) i2c;
 
-static int max7310_read(void *opaque, uint8_t *data, int len)
-{
-    struct max7310_s *s = (struct max7310_s *) opaque;
-
     switch (s->command) {
     case 0x00:	/* Input port */
-        memset(data, s->level ^ s->polarity, len);
+        return s->level ^ s->polarity;
         break;
 
     case 0x01:	/* Output port */
-        memset(data, s->level & ~s->direction, len);
+        return s->level & ~s->direction;
         break;
 
     case 0x02:	/* Polarity inversion */
-        memset(data, s->polarity, len);
-        break;
+        return s->polarity;
 
     case 0x03:	/* Configuration */
-        memset(data, s->direction, len);
-        break;
+        return s->direction;
 
     case 0x04:	/* Timeout */
-        memset(data, s->status, len);
+        return s->status;
         break;
 
     case 0xff:	/* Reserved */
-        memset(data, 0xff, len);
-        break;
+        return 0xff;
 
     default:
 #ifdef VERBOSE
         printf("%s: unknown register %02x\n", __FUNCTION__, s->command);
 #endif
-        return 1;
+        break;
     }
-    return 0;
+    return 0xff;
 }
 
-static int max7310_write(void *opaque, uint8_t *data, int len)
+static int max7310_tx(i2c_slave *i2c, uint8_t data)
 {
-    struct max7310_s *s = (struct max7310_s *) opaque;
+    struct max7310_s *s = (struct max7310_s *) i2c;
     uint8_t diff;
     int line;
 
-    if (len >= 1)
-        s->command = data[0];
-
-    if (len < 2) {
+    if (s->len ++ > 1) {
 #ifdef VERBOSE
-        printf("%s: message too short (%i bytes)\n", __FUNCTION__, len);
+        printf("%s: message too long (%i bytes)\n", __FUNCTION__, s->len);
 #endif
+        return 1;
+    }
+
+    if (s->i2c_command_byte) {
+        s->command = data;
+        s->i2c_command_byte = 0;
         return 0;
     }
 
     switch (s->command) {
     case 0x01:	/* Output port */
-        for (diff = (data[1] ^ s->level) & ~s->direction; diff;
+        for (diff = (data ^ s->level) & ~s->direction; diff;
                         diff &= ~(1 << line)) {
             line = ffs(diff) - 1;
             if (s->handler[line].fn)
-                s->handler[line].fn(line, (data[1] >> line) & 1,
+                s->handler[line].fn(line, (data >> line) & 1,
                                 s->handler[line].opaque);
         }
-        s->level = (s->level & s->direction) | (data[1] & ~s->direction);
+        s->level = (s->level & s->direction) | (data & ~s->direction);
         break;
 
     case 0x02:	/* Polarity inversion */
-        s->polarity = data[1];
+        s->polarity = data;
         break;
 
     case 0x03:	/* Configuration */
-        s->level &= ~(s->direction ^ data[1]);
-        s->direction = data[1];
+        s->level &= ~(s->direction ^ data);
+        s->direction = data;
         break;
 
     case 0x04:	/* Timeout */
-        s->status = data[1];
+        s->status = data;
         break;
 
+    case 0x00:	/* Input port - ignore writes */
+	break;
     default:
 #ifdef VERBOSE
         printf("%s: unknown register %02x\n", __FUNCTION__, s->command);
@@ -128,33 +126,43 @@
     return 0;
 }
 
-static int max7310_tx(void *opaque, uint8_t *data, int len)
+static void max7310_event(i2c_slave *i2c, enum i2c_event event)
 {
-    struct max7310_s *s = (struct max7310_s *) opaque;
-    if (len) {
-        if (s->i2c_dir)
-            return max7310_write(opaque, data, len);
-        else
-            return max7310_read(opaque, data, len);
+    struct max7310_s *s = (struct max7310_s *) i2c;
+    s->len = 0;
+
+    switch (event) {
+    case I2C_START_SEND:
+        s->i2c_command_byte = 1;
+        break;
+    case I2C_FINISH:
+        if (s->len == 1)
+#ifdef VERBOSE
+            printf("%s: message too short (%i bytes)\n", __FUNCTION__, s->len);
+#endif
+        break;
+    default:
+        break;
     }
-
-    return 0;
 }
 
-struct i2c_slave_s *max7310_init(void)
+/* MAX7310 is SMBus-compatible (can be used with only SMBus protocols),
+ * but also accepts sequences that are not SMBus so return an I2C device.  */
+struct i2c_slave *max7310_init(i2c_bus *bus)
 {
-    struct max7310_s *s = qemu_mallocz(sizeof(struct max7310_s));
-    s->i2c.opaque = s;
-    s->i2c.tx = max7310_tx;
-    s->i2c.start = max7310_start;
+    struct max7310_s *s = (struct max7310_s *)
+            i2c_slave_init(bus, 0, sizeof(struct max7310_s));
+    s->i2c.event = max7310_event;
+    s->i2c.recv = max7310_rx;
+    s->i2c.send = max7310_tx;
 
     max7310_reset(&s->i2c);
     return &s->i2c;
 }
 
-void max7310_gpio_set(struct i2c_slave_s *i2c, int line, int level)
+void max7310_gpio_set(i2c_slave *i2c, int line, int level)
 {
-    struct max7310_s *s = (struct max7310_s *) i2c->opaque;
+    struct max7310_s *s = (struct max7310_s *) i2c;
     if (line >= sizeof(s->handler) / sizeof(*s->handler) || line  < 0)
         cpu_abort(cpu_single_env, "bad GPIO line");
 
@@ -164,10 +172,10 @@
         s->level &= ~(s->direction & (1 << line));
 }
 
-void max7310_gpio_handler_set(struct i2c_slave_s *i2c, int line,
+void max7310_gpio_handler_set(i2c_slave *i2c, int line,
                 gpio_handler_t handler, void *opaque)
 {
-    struct max7310_s *s = (struct max7310_s *) i2c->opaque;
+    struct max7310_s *s = (struct max7310_s *) i2c;
     if (line >= sizeof(s->handler) / sizeof(*s->handler) || line  < 0)
         cpu_abort(cpu_single_env, "bad GPIO line");
 

Modified: trunk/src/host/qemu-neo1973/hw/mc146818rtc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mc146818rtc.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/mc146818rtc.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -54,7 +54,9 @@
     uint8_t cmos_data[128];
     uint8_t cmos_index;
     struct tm current_tm;
-    int irq;
+    qemu_irq irq;
+    target_phys_addr_t base;
+    int it_shift;
     /* periodic timer */
     QEMUTimer *periodic_timer;
     int64_t next_periodic_time;
@@ -95,7 +97,7 @@
 
     rtc_timer_update(s, s->next_periodic_time);
     s->cmos_data[RTC_REG_C] |= 0xc0;
-    pic_set_irq(s->irq, 1);
+    qemu_irq_raise(s->irq);
 }
 
 static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
@@ -314,14 +316,14 @@
              s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
 
             s->cmos_data[RTC_REG_C] |= 0xa0; 
-            pic_set_irq(s->irq, 1);
+            qemu_irq_raise(s->irq);
         }
     }
 
     /* update ended interrupt */
     if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
         s->cmos_data[RTC_REG_C] |= 0x90; 
-        pic_set_irq(s->irq, 1);
+        qemu_irq_raise(s->irq);
     }
 
     /* clear update in progress bit */
@@ -353,7 +355,7 @@
             break;
         case RTC_REG_C:
             ret = s->cmos_data[s->cmos_index];
-            pic_set_irq(s->irq, 0);
+            qemu_irq_lower(s->irq);
             s->cmos_data[RTC_REG_C] = 0x00; 
             break;
         default:
@@ -453,7 +455,7 @@
     return 0;
 }
 
-RTCState *rtc_init(int base, int irq)
+RTCState *rtc_init(int base, qemu_irq irq)
 {
     RTCState *s;
 
@@ -486,3 +488,109 @@
     return s;
 }
 
+/* Memory mapped interface */
+uint32_t cmos_mm_readb (void *opaque, target_phys_addr_t addr)
+{
+    RTCState *s = opaque;
+
+    return cmos_ioport_read(s, (addr - s->base) >> s->it_shift) & 0xFF;
+}
+
+void cmos_mm_writeb (void *opaque,
+                     target_phys_addr_t addr, uint32_t value)
+{
+    RTCState *s = opaque;
+
+    cmos_ioport_write(s, (addr - s->base) >> s->it_shift, value & 0xFF);
+}
+
+uint32_t cmos_mm_readw (void *opaque, target_phys_addr_t addr)
+{
+    RTCState *s = opaque;
+    uint32_t val;
+
+    val = cmos_ioport_read(s, (addr - s->base) >> s->it_shift) & 0xFFFF;
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap16(val);
+#endif
+    return val;
+}
+
+void cmos_mm_writew (void *opaque,
+                     target_phys_addr_t addr, uint32_t value)
+{
+    RTCState *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+    value = bswap16(value);
+#endif
+    cmos_ioport_write(s, (addr - s->base) >> s->it_shift, value & 0xFFFF);
+}
+
+uint32_t cmos_mm_readl (void *opaque, target_phys_addr_t addr)
+{
+    RTCState *s = opaque;
+    uint32_t val;
+
+    val = cmos_ioport_read(s, (addr - s->base) >> s->it_shift);
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    return val;
+}
+
+void cmos_mm_writel (void *opaque,
+                     target_phys_addr_t addr, uint32_t value)
+{
+    RTCState *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+    value = bswap32(value);
+#endif
+    cmos_ioport_write(s, (addr - s->base) >> s->it_shift, value);
+}
+
+static CPUReadMemoryFunc *rtc_mm_read[] = {
+    &cmos_mm_readb,
+    &cmos_mm_readw,
+    &cmos_mm_readl,
+};
+
+static CPUWriteMemoryFunc *rtc_mm_write[] = {
+    &cmos_mm_writeb,
+    &cmos_mm_writew,
+    &cmos_mm_writel,
+};
+
+RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq)
+{
+    RTCState *s;
+    int io_memory;
+
+    s = qemu_mallocz(sizeof(RTCState));
+    if (!s)
+        return NULL;
+
+    s->irq = irq;
+    s->cmos_data[RTC_REG_A] = 0x26;
+    s->cmos_data[RTC_REG_B] = 0x02;
+    s->cmos_data[RTC_REG_C] = 0x00;
+    s->cmos_data[RTC_REG_D] = 0x80;
+    s->base = base;
+
+    rtc_set_date_from_host(s);
+
+    s->periodic_timer = qemu_new_timer(vm_clock,
+                                       rtc_periodic_timer, s);
+    s->second_timer = qemu_new_timer(vm_clock,
+                                     rtc_update_second, s);
+    s->second_timer2 = qemu_new_timer(vm_clock,
+                                      rtc_update_second2, s);
+
+    s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100;
+    qemu_mod_timer(s->second_timer2, s->next_second_time);
+
+    io_memory = cpu_register_io_memory(0, rtc_mm_read, rtc_mm_write, s);
+    cpu_register_physical_memory(base, 2 << it_shift, io_memory);
+
+    register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
+    return s;
+}

Deleted: trunk/src/host/qemu-neo1973/hw/md.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/md.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/md.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,499 +0,0 @@
-/*
- * DSCM-1XXXX Microdrive hard disk with CF+ II / PCMCIA interface.
- *
- * Copyright (c) 2006 Openedhand Ltd.
- * Written by Andrzej Zaborowski <balrog at zabor.org>
- *
- * This code is licensed under the GPLv2.
- */
-
-#include "vl.h"
-
-#define METADATA_SIZE	0x20
-
-struct md_s {
-    IDEState ide[2];
-    struct pcmcia_card_s card;
-    uint32_t attr_base;
-    uint32_t io_base;
-
-    /* Card state */
-    uint8_t opt;
-    uint8_t stat;
-    uint8_t pins;
-
-    uint8_t ctrl;
-    uint16_t io;
-    int cycle;
-};
-
-/* Register bitfields */
-enum md_opt {
-    OPT_MODE_MMAP	= 0,
-    OPT_MODE_IOMAP16	= 1,
-    OPT_MODE_IOMAP1	= 2,
-    OPT_MODE_IOMAP2	= 3,
-    OPT_MODE		= 0x3f,
-    OPT_LEVIREQ		= 0x40,
-    OPT_SRESET		= 0x80,
-};
-enum md_cstat {
-    STAT_INT		= 0x02,
-    STAT_PWRDWN		= 0x04,
-    STAT_XE		= 0x10,
-    STAT_IOIS8		= 0x20,
-    STAT_SIGCHG		= 0x40,
-    STAT_CHANGED	= 0x80,
-};
-enum md_pins {
-    PINS_MRDY		= 0x02,
-    PINS_CRDY		= 0x20,
-};
-enum md_ctrl {
-    CTRL_IEN		= 0x02,
-    CTRL_SRST		= 0x04,
-};
-
-static inline void md_interrupt_update(struct md_s *s)
-{
-    if (!s->card.slot)
-        return;
-
-    s->card.slot->set_irq(s->card.slot->opaque, 0,
-                    !(s->stat & STAT_INT) &&	/* Inverted */
-                    !(s->ctrl & (CTRL_IEN | CTRL_SRST)) &&
-                    !(s->opt & OPT_SRESET));
-}
-
-static void md_set_irq(void *opaque, int irq, int level)
-{
-    struct md_s *s = (struct md_s *) opaque;
-    if (level)
-        s->stat |= STAT_INT;
-    else
-        s->stat &= ~STAT_INT;
-
-    md_interrupt_update(s);
-}
-
-static void md_reset(struct md_s *s)
-{
-    s->opt = OPT_MODE_MMAP;
-    s->stat = 0;
-    s->pins = 0;
-    s->cycle = 0;
-    s->ctrl = 0;
-    ide_reset(s->ide);
-}
-
-static uint8_t md_attr_read(void *opaque, uint16_t at)
-{
-    struct md_s *s = (struct md_s *) opaque;
-    if (at < s->attr_base) {
-        if (at < s->card.cis_len)
-            return s->card.cis[at];
-        else
-            return 0x00;
-    }
-
-    at -= s->attr_base;
-
-    switch (at) {
-    case 0x00:	/* Configuration Option Register */
-        return s->opt;
-    case 0x02:	/* Card Configuration Status Register */
-        if (s->ctrl & CTRL_IEN)
-            return s->stat & ~STAT_INT;
-        else
-            return s->stat;
-    case 0x04:	/* Pin Replacement Register */
-        return (s->pins & PINS_CRDY) | 0x0c;
-    case 0x06:	/* Socket and Copy Register */
-        return 0x00;
-#ifdef VERBOSE
-    default:
-        printf("%s: Bad attribute space register %02x\n", __FUNCTION__, at);
-#endif
-    }
-
-    return 0;
-}
-
-static void md_attr_write(void *opaque, uint16_t at, uint8_t value)
-{
-    struct md_s *s = (struct md_s *) opaque;
-    at -= s->attr_base;
-
-    switch (at) {
-    case 0x00:	/* Configuration Option Register */
-        s->opt = value & 0xcf;
-        if (value & OPT_SRESET)
-            md_reset(s);
-        md_interrupt_update(s);
-        break;
-    case 0x02:	/* Card Configuration Status Register */
-        if ((s->stat ^ value) & STAT_PWRDWN)
-            s->pins |= PINS_CRDY;
-        s->stat &= 0x82;
-        s->stat |= value & 0x74;
-        md_interrupt_update(s);
-        /* Word 170 in Identify Device must be equal to STAT_XE */
-        break;
-    case 0x04:	/* Pin Replacement Register */
-        s->pins &= PINS_CRDY;
-        s->pins |= value & PINS_MRDY;
-        break;
-    case 0x06:	/* Socket and Copy Register */
-        break;
-    default:
-        printf("%s: Bad attribute space register %02x\n", __FUNCTION__, at);
-    }
-}
-
-static uint16_t md_common_read(void *opaque, uint16_t at)
-{
-    struct md_s *s = (struct md_s *) opaque;
-    uint16_t ret;
-    at -= s->io_base;
-
-    switch (s->opt & OPT_MODE) {
-    case OPT_MODE_MMAP:
-        if ((at & ~0x3ff) == 0x400)
-            at = 0;
-        break;
-    case OPT_MODE_IOMAP16:
-        at &= 0xf;
-        break;
-    case OPT_MODE_IOMAP1:
-        if ((at & ~0xf) == 0x3f0)
-            at -= 0x3e8;
-        else if ((at & ~0xf) == 0x1f0)
-            at -= 0x1f0;
-        break;
-    case OPT_MODE_IOMAP2:
-        if ((at & ~0xf) == 0x370)
-            at -= 0x368;
-        else if ((at & ~0xf) == 0x170)
-            at -= 0x170;
-    }
-
-    switch (at) {
-    case 0x0:	/* Even RD Data */
-    case 0x8:
-        return ide_data_readw(s->ide, 0);
-
-        /* TODO: 8-bit accesses */
-        if (s->cycle)
-            ret = s->io >> 8;
-        else {
-            s->io = ide_data_readw(s->ide, 0);
-            ret = s->io & 0xff;
-        }
-        s->cycle = !s->cycle;
-        return ret;
-    case 0x9:	/* Odd RD Data */
-        return s->io >> 8;
-    case 0xd:	/* Error */
-        return ide_ioport_read(s->ide, 0x1);
-    case 0xe:	/* Alternate Status */
-        if (s->ide->cur_drive->bs)
-            return s->ide->cur_drive->status;
-        else
-            return 0;
-    case 0xf:	/* Device Address */
-        return 0xc2 | ((~s->ide->select << 2) & 0x3c);
-    default:
-        return ide_ioport_read(s->ide, at);
-    }
-
-    return 0;
-}
-
-static void md_common_write(void *opaque, uint16_t at, uint16_t value)
-{
-    struct md_s *s = (struct md_s *) opaque;
-    at -= s->io_base;
-
-    switch (s->opt & OPT_MODE) {
-    case OPT_MODE_MMAP:
-        if ((at & ~0x3ff) == 0x400)
-            at = 0;
-        break;
-    case OPT_MODE_IOMAP16:
-        at &= 0xf;
-        break;
-    case OPT_MODE_IOMAP1:
-        if ((at & ~0xf) == 0x3f0)
-            at -= 0x3e8;
-        else if ((at & ~0xf) == 0x1f0)
-            at -= 0x1f0;
-        break;
-    case OPT_MODE_IOMAP2:
-        if ((at & ~0xf) == 0x370)
-            at -= 0x368;
-        else if ((at & ~0xf) == 0x170)
-            at -= 0x170;
-    }
-
-    switch (at) {
-    case 0x0:	/* Even WR Data */
-    case 0x8:
-        ide_data_writew(s->ide, 0, value);
-        break;
-
-        /* TODO: 8-bit accesses */
-        if (s->cycle)
-            ide_data_writew(s->ide, 0, s->io | (value << 8));
-        else
-            s->io = value & 0xff;
-        s->cycle = !s->cycle;
-        break;
-    case 0x9:
-        s->io = value & 0xff;
-        s->cycle = !s->cycle;
-        break;
-    case 0xd:	/* Features */
-        ide_ioport_write(s->ide, 0x1, value);
-        break;
-    case 0xe:	/* Device Control */
-        s->ctrl = value;
-        if (value & CTRL_SRST)
-            md_reset(s);
-        md_interrupt_update(s);
-        break;
-    default:
-        if (s->stat & STAT_PWRDWN) {
-            s->pins |= PINS_CRDY;
-            s->stat &= ~STAT_PWRDWN;
-        }
-        ide_ioport_write(s->ide, at, value);
-    }
-}
-
-static const uint8_t dscm1xxxx_cis[0x14a] = {
-    [0x000] = CISTPL_DEVICE,	/* 5V Device Information */
-    [0x002] = 0x03,		/* Tuple length = 4 bytes */
-    [0x004] = 0xdb,		/* ID: DTYPE_FUNCSPEC, non WP, DSPEED_150NS */
-    [0x006] = 0x01,		/* Size = 2K bytes */
-    [0x008] = CISTPL_ENDMARK,
-
-    [0x00a] = CISTPL_DEVICE_OC,	/* Additional Device Information */
-    [0x00c] = 0x04,		/* Tuple length = 4 byest */
-    [0x00e] = 0x03,		/* Conditions: Ext = 0, Vcc 3.3V, MWAIT = 1 */
-    [0x010] = 0xdb,		/* ID: DTYPE_FUNCSPEC, non WP, DSPEED_150NS */
-    [0x012] = 0x01,		/* Size = 2K bytes */
-    [0x014] = CISTPL_ENDMARK,
-
-    [0x016] = CISTPL_JEDEC_C,	/* JEDEC ID */
-    [0x018] = 0x02,		/* Tuple length = 2 bytes */
-    [0x01a] = 0xdf,		/* PC Card ATA with no Vpp required */
-    [0x01c] = 0x01,
-
-    [0x01e] = CISTPL_MANFID,	/* Manufacture ID */
-    [0x020] = 0x04,		/* Tuple length = 4 bytes */
-    [0x022] = 0xa4,		/* TPLMID_MANF = 00a4 (IBM) */
-    [0x024] = 0x00,
-    [0x026] = 0x00,		/* PLMID_CARD = 0000 */
-    [0x028] = 0x00,
-
-    [0x02a] = CISTPL_VERS_1,	/* Level 1 Version */
-    [0x02c] = 0x12,		/* Tuple length = 23 bytes */
-    [0x02e] = 0x04,		/* Major Version = JEIDA 4.2 / PCMCIA 2.1 */
-    [0x030] = 0x01,		/* Minor Version = 1 */
-    [0x032] = 'I',
-    [0x034] = 'B',
-    [0x036] = 'M',
-    [0x038] = 0x00,
-    [0x03a] = 'm',
-    [0x03c] = 'i',
-    [0x03e] = 'c',
-    [0x040] = 'r',
-    [0x042] = 'o',
-    [0x044] = 'd',
-    [0x046] = 'r',
-    [0x048] = 'i',
-    [0x04a] = 'v',
-    [0x04c] = 'e',
-    [0x04e] = 0x00,
-    [0x050] = CISTPL_ENDMARK,
-
-    [0x052] = CISTPL_FUNCID,	/* Function ID */
-    [0x054] = 0x02,		/* Tuple length = 2 bytes */
-    [0x056] = 0x04,		/* TPLFID_FUNCTION = Fixed Disk */
-    [0x058] = 0x01,		/* TPLFID_SYSINIT: POST = 1, ROM = 0 */
-
-    [0x05a] = CISTPL_FUNCE,	/* Function Extension */
-    [0x05c] = 0x02,		/* Tuple length = 2 bytes */
-    [0x05e] = 0x01,		/* TPLFE_TYPE = Disk Device Interface */
-    [0x060] = 0x01,		/* TPLFE_DATA = PC Card ATA Interface */
-
-    [0x062] = CISTPL_FUNCE,	/* Function Extension */
-    [0x064] = 0x03,		/* Tuple length = 3 bytes */
-    [0x066] = 0x02,		/* TPLFE_TYPE = Basic PC Card ATA Interface */
-    [0x068] = 0x08,		/* TPLFE_DATA: Rotating, Unique, Single */
-    [0x06a] = 0x0f,		/* TPLFE_DATA: Sleep, Standby, Idle, Auto */
-
-    [0x06c] = CISTPL_CONFIG,	/* Configuration */
-    [0x06e] = 0x05,		/* Tuple length = 5 bytes */
-    [0x070] = 0x01,		/* TPCC_RASZ = 2 bytes, TPCC_RMSZ = 1 byte */
-    [0x072] = 0x07,		/* TPCC_LAST = 7 */
-    [0x074] = 0x00,		/* TPCC_RADR = 0200 */
-    [0x076] = 0x02,
-    [0x078] = 0x0f,		/* TPCC_RMSK = 200, 202, 204, 206 */
-
-    [0x07a] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
-    [0x07c] = 0x0b,		/* Tuple length = 11 bytes */
-    [0x07e] = 0xc0,		/* TPCE_INDX = Memory Mode, Default, Iface */
-    [0x080] = 0xc0,		/* TPCE_IF = Memory, no BVDs, no WP, READY */
-    [0x082] = 0xa1,		/* TPCE_FS = Vcc only, no I/O, Memory, Misc */
-    [0x084] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
-    [0x086] = 0x55,		/* NomV: 5.0 V */
-    [0x088] = 0x4d,		/* MinV: 4.5 V */
-    [0x08a] = 0x5d,		/* MaxV: 5.5 V */
-    [0x08c] = 0x4e,		/* Peakl: 450 mA */
-    [0x08e] = 0x08,		/* TPCE_MS = 1 window, 1 byte, Host address */
-    [0x090] = 0x00,		/* Window descriptor: Window length = 0 */
-    [0x092] = 0x20,		/* TPCE_MI: support power down mode, RW */
-
-    [0x094] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
-    [0x096] = 0x06,		/* Tuple length = 6 bytes */
-    [0x098] = 0x00,		/* TPCE_INDX = Memory Mode, no Default */
-    [0x09a] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
-    [0x09c] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
-    [0x09e] = 0xb5,		/* NomV: 3.3 V */
-    [0x0a0] = 0x1e,
-    [0x0a2] = 0x3e,		/* Peakl: 350 mA */
-
-    [0x0a4] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
-    [0x0a6] = 0x0d,		/* Tuple length = 13 bytes */
-    [0x0a8] = 0xc1,		/* TPCE_INDX = I/O and Memory Mode, Default */
-    [0x0aa] = 0x41,		/* TPCE_IF = I/O and Memory, no BVD, no WP */
-    [0x0ac] = 0x99,		/* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
-    [0x0ae] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
-    [0x0b0] = 0x55,		/* NomV: 5.0 V */
-    [0x0b2] = 0x4d,		/* MinV: 4.5 V */
-    [0x0b4] = 0x5d,		/* MaxV: 5.5 V */
-    [0x0b6] = 0x4e,		/* Peakl: 450 mA */
-    [0x0b8] = 0x64,		/* TPCE_IO = 16-byte boundary, 16/8 accesses */
-    [0x0ba] = 0xf0,		/* TPCE_IR =  MASK, Level, Pulse, Share */
-    [0x0bc] = 0xff,		/* IRQ0..IRQ7 supported */
-    [0x0be] = 0xff,		/* IRQ8..IRQ15 supported */
-    [0x0c0] = 0x20,		/* TPCE_MI = support power down mode */
-
-    [0x0c2] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
-    [0x0c4] = 0x06,		/* Tuple length = 6 bytes */
-    [0x0c6] = 0x01,		/* TPCE_INDX = I/O and Memory Mode */
-    [0x0c8] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
-    [0x0ca] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
-    [0x0cc] = 0xb5,		/* NomV: 3.3 V */
-    [0x0ce] = 0x1e,
-    [0x0d0] = 0x3e,		/* Peakl: 350 mA */
-
-    [0x0d2] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
-    [0x0d4] = 0x12,		/* Tuple length = 18 bytes */
-    [0x0d6] = 0xc2,		/* TPCE_INDX = I/O Primary Mode */
-    [0x0d8] = 0x41,		/* TPCE_IF = I/O and Memory, no BVD, no WP */
-    [0x0da] = 0x99,		/* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
-    [0x0dc] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
-    [0x0de] = 0x55,		/* NomV: 5.0 V */
-    [0x0e0] = 0x4d,		/* MinV: 4.5 V */
-    [0x0e2] = 0x5d,		/* MaxV: 5.5 V */
-    [0x0e4] = 0x4e,		/* Peakl: 450 mA */
-    [0x0e6] = 0xea,		/* TPCE_IO = 1K boundary, 16/8 access, Range */
-    [0x0e8] = 0x61,		/* Range: 2 fields, 2 bytes addr, 1 byte len */
-    [0x0ea] = 0xf0,		/* Field 1 address = 0x01f0 */
-    [0x0ec] = 0x01,
-    [0x0ee] = 0x07,		/* Address block length = 8 */
-    [0x0f0] = 0xf6,		/* Field 2 address = 0x03f6 */
-    [0x0f2] = 0x03,
-    [0x0f4] = 0x01,		/* Address block length = 2 */
-    [0x0f6] = 0xee,		/* TPCE_IR = IRQ E, Level, Pulse, Share */
-    [0x0f8] = 0x20,		/* TPCE_MI = support power down mode */
-
-    [0x0fa] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
-    [0x0fc] = 0x06,		/* Tuple length = 6 bytes */
-    [0x0fe] = 0x02,		/* TPCE_INDX = I/O Primary Mode, no Default */
-    [0x100] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
-    [0x102] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
-    [0x104] = 0xb5,		/* NomV: 3.3 V */
-    [0x106] = 0x1e,
-    [0x108] = 0x3e,		/* Peakl: 350 mA */
-
-    [0x10a] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
-    [0x10c] = 0x12,		/* Tuple length = 18 bytes */
-    [0x10e] = 0xc3,		/* TPCE_INDX = I/O Secondary Mode, Default */
-    [0x110] = 0x41,		/* TPCE_IF = I/O and Memory, no BVD, no WP */
-    [0x112] = 0x99,		/* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
-    [0x114] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
-    [0x116] = 0x55,		/* NomV: 5.0 V */
-    [0x118] = 0x4d,		/* MinV: 4.5 V */
-    [0x11a] = 0x5d,		/* MaxV: 5.5 V */
-    [0x11c] = 0x4e,		/* Peakl: 450 mA */
-    [0x11e] = 0xea,		/* TPCE_IO = 1K boundary, 16/8 access, Range */
-    [0x120] = 0x61,		/* Range: 2 fields, 2 byte addr, 1 byte len */
-    [0x122] = 0x70,		/* Field 1 address = 0x0170 */
-    [0x124] = 0x01,
-    [0x126] = 0x07,		/* Address block length = 8 */
-    [0x128] = 0x76,		/* Field 2 address = 0x0376 */
-    [0x12a] = 0x03,
-    [0x12c] = 0x01,		/* Address block length = 2 */
-    [0x12e] = 0xee,		/* TPCE_IR = IRQ E, Level, Pulse, Share */
-    [0x130] = 0x20,		/* TPCE_MI = support power down mode */
-
-    [0x132] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
-    [0x134] = 0x06,		/* Tuple length = 6 bytes */
-    [0x136] = 0x03,		/* TPCE_INDX = I/O Secondary Mode */
-    [0x138] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
-    [0x13a] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
-    [0x13c] = 0xb5,		/* NomV: 3.3 V */
-    [0x13e] = 0x1e,
-    [0x140] = 0x3e,		/* Peakl: 350 mA */
-
-    [0x142] = CISTPL_NO_LINK,	/* No Link */
-    [0x144] = 0x00,		/* Tuple length = 0 bytes */
-
-    [0x146] = CISTPL_END,	/* Tuple End */
-};
-
-static int dscm1xxxx_attach(void *opaque)
-{
-    struct md_s *md = (struct md_s *) opaque;
-    md->card.attr_read = md_attr_read;
-    md->card.attr_write = md_attr_write;
-    md->card.common_read = md_common_read;
-    md->card.common_write = md_common_write;
-    md->card.io_read = md_common_read;
-    md->card.io_write = md_common_write;
-
-    md->attr_base = md->card.cis[0x74] | (md->card.cis[0x76] << 8);
-    md->io_base = 0x0;
-
-    md_reset(md);
-    md_interrupt_update(md);
-
-    md->card.slot->card_string = "DSCM-1xxxx Hitachi Microdrive";
-    return 0;
-}
-
-static int dscm1xxxx_detach(void *opaque)
-{
-    struct md_s *md = (struct md_s *) opaque;
-    md_reset(md);
-    return 0;
-}
-
-struct pcmcia_card_s *dscm1xxxx_init(BlockDriverState *bdrv)
-{
-    struct md_s *md = (struct md_s *) qemu_mallocz(sizeof(struct md_s));
-    md->card.state = md;
-    md->card.attach = dscm1xxxx_attach;
-    md->card.detach = dscm1xxxx_detach;
-    md->card.cis = dscm1xxxx_cis;
-    md->card.cis_len = sizeof(dscm1xxxx_cis);
-
-    ide_init2(md->ide, bdrv, 0, md_set_irq, md, 0);
-    md->ide->is_cf = 1;
-    md->ide->mdata_size = METADATA_SIZE;
-    md->ide->mdata_storage = (uint8_t *) qemu_mallocz(METADATA_SIZE);
-    return &md->card;
-}

Added: trunk/src/host/qemu-neo1973/hw/mips_int.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_int.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/mips_int.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,44 @@
+#include "vl.h"
+#include "cpu.h"
+
+/* Raise IRQ to CPU if necessary. It must be called every time the active
+   IRQ may change */
+void cpu_mips_update_irq(CPUState *env)
+{
+    if ((env->CP0_Status & (1 << CP0St_IE)) &&
+        !(env->CP0_Status & (1 << CP0St_EXL)) &&
+        !(env->CP0_Status & (1 << CP0St_ERL)) &&
+        !(env->hflags & MIPS_HFLAG_DM)) {
+        if ((env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
+            !(env->interrupt_request & CPU_INTERRUPT_HARD)) {
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+	}
+    } else
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+}
+
+static void cpu_mips_irq_request(void *opaque, int irq, int level)
+{
+    CPUState *env = (CPUState *)opaque;
+
+    if (irq < 0 || irq > 7)
+        return;
+
+    if (level) {
+        env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
+    } else {
+        env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
+    }
+    cpu_mips_update_irq(env);
+}
+
+void cpu_mips_irq_init_cpu(CPUState *env)
+{
+    qemu_irq *qi;
+    int i;
+
+    qi = qemu_allocate_irqs(cpu_mips_irq_request, env, 8);
+    for (i = 0; i < 8; i++) {
+        env->irq[i] = qi[i];
+    }
+}

Added: trunk/src/host/qemu-neo1973/hw/mips_malta.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_malta.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/mips_malta.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,883 @@
+/*
+ * QEMU Malta board support
+ *
+ * Copyright (c) 2006 Aurelien Jarno
+ *
+ * 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"
+
+#ifdef TARGET_WORDS_BIGENDIAN
+#define BIOS_FILENAME "mips_bios.bin"
+#else
+#define BIOS_FILENAME "mipsel_bios.bin"
+#endif
+
+#ifdef TARGET_MIPS64
+#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
+#else
+#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
+#endif
+
+#define ENVP_ADDR (int32_t)0x80002000
+#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
+
+#define ENVP_NB_ENTRIES	 	16
+#define ENVP_ENTRY_SIZE	 	256
+
+
+extern FILE *logfile;
+
+typedef struct {
+    uint32_t leds;
+    uint32_t brk;
+    uint32_t gpout;
+    uint32_t i2cin;
+    uint32_t i2coe;
+    uint32_t i2cout;
+    uint32_t i2csel;
+    CharDriverState *display;
+    char display_text[9];
+    SerialState *uart;
+} MaltaFPGAState;
+
+static PITState *pit;
+
+/* Malta FPGA */
+static void malta_fpga_update_display(void *opaque)
+{
+    char leds_text[9];
+    int i;
+    MaltaFPGAState *s = opaque;
+
+    for (i = 7 ; i >= 0 ; i--) {
+        if (s->leds & (1 << i))
+            leds_text[i] = '#';
+	else
+            leds_text[i] = ' ';
+    }
+    leds_text[8] = '\0';
+
+    qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
+    qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
+}
+
+/*
+ * EEPROM 24C01 / 24C02 emulation.
+ *
+ * Emulation for serial EEPROMs:
+ * 24C01 - 1024 bit (128 x 8)
+ * 24C02 - 2048 bit (256 x 8)
+ *
+ * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
+ */
+
+//~ #define DEBUG
+
+#if defined(DEBUG)
+#  define logout(fmt, args...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ##args)
+#else
+#  define logout(fmt, args...) ((void)0)
+#endif
+
+struct _eeprom24c0x_t {
+  uint8_t tick;
+  uint8_t address;
+  uint8_t command;
+  uint8_t ack;
+  uint8_t scl;
+  uint8_t sda;
+  uint8_t data;
+  //~ uint16_t size;
+  uint8_t contents[256];
+};
+
+typedef struct _eeprom24c0x_t eeprom24c0x_t;
+
+static eeprom24c0x_t eeprom = {
+    contents: {
+        /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
+        /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
+        /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
+        /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
+        /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
+        /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
+        /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
+    },
+};
+
+static uint8_t eeprom24c0x_read()
+{
+    logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
+        eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
+    return eeprom.sda;
+}
+
+static void eeprom24c0x_write(int scl, int sda)
+{
+    if (eeprom.scl && scl && (eeprom.sda != sda)) {
+        logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
+                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
+        if (!sda) {
+            eeprom.tick = 1;
+            eeprom.command = 0;
+        }
+    } else if (eeprom.tick == 0 && !eeprom.ack) {
+        /* Waiting for start. */
+        logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
+                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
+    } else if (!eeprom.scl && scl) {
+        logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
+                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
+        if (eeprom.ack) {
+            logout("\ti2c ack bit = 0\n");
+            sda = 0;
+            eeprom.ack = 0;
+        } else if (eeprom.sda == sda) {
+            uint8_t bit = (sda != 0);
+            logout("\ti2c bit = %d\n", bit);
+            if (eeprom.tick < 9) {
+                eeprom.command <<= 1;
+                eeprom.command += bit;
+                eeprom.tick++;
+                if (eeprom.tick == 9) {
+                    logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
+                    eeprom.ack = 1;
+                }
+            } else if (eeprom.tick < 17) {
+                if (eeprom.command & 1) {
+                    sda = ((eeprom.data & 0x80) != 0);
+                }
+                eeprom.address <<= 1;
+                eeprom.address += bit;
+                eeprom.tick++;
+                eeprom.data <<= 1;
+                if (eeprom.tick == 17) {
+                    eeprom.data = eeprom.contents[eeprom.address];
+                    logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
+                    eeprom.ack = 1;
+                    eeprom.tick = 0;
+                }
+            } else if (eeprom.tick >= 17) {
+                sda = 0;
+            }
+        } else {
+            logout("\tsda changed with raising scl\n");
+        }
+    } else {
+        logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
+    }
+    eeprom.scl = scl;
+    eeprom.sda = sda;
+}
+
+static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
+{
+    MaltaFPGAState *s = opaque;
+    uint32_t val = 0;
+    uint32_t saddr;
+
+    saddr = (addr & 0xfffff);
+
+    switch (saddr) {
+
+    /* SWITCH Register */
+    case 0x00200:
+        val = 0x00000000;		/* All switches closed */
+	break;
+
+    /* STATUS Register */
+    case 0x00208:
+#ifdef TARGET_WORDS_BIGENDIAN
+        val = 0x00000012;
+#else
+        val = 0x00000010;
+#endif
+        break;
+
+    /* JMPRS Register */
+    case 0x00210:
+        val = 0x00;
+        break;
+
+    /* LEDBAR Register */
+    case 0x00408:
+        val = s->leds;
+        break;
+
+    /* BRKRES Register */
+    case 0x00508:
+        val = s->brk;
+        break;
+
+    /* UART Registers */
+    case 0x00900:
+    case 0x00908:
+    case 0x00910:
+    case 0x00918:
+    case 0x00920:
+    case 0x00928:
+    case 0x00930:
+    case 0x00938:
+        val = serial_mm_readb(s->uart, addr);
+        break;
+
+    /* GPOUT Register */
+    case 0x00a00:
+        val = s->gpout;
+        break;
+
+    /* XXX: implement a real I2C controller */
+
+    /* GPINP Register */
+    case 0x00a08:
+        /* IN = OUT until a real I2C control is implemented */
+        if (s->i2csel)
+            val = s->i2cout;
+        else
+            val = 0x00;
+        break;
+
+    /* I2CINP Register */
+    case 0x00b00:
+        val = ((s->i2cin & ~1) | eeprom24c0x_read());
+        break;
+
+    /* I2COE Register */
+    case 0x00b08:
+        val = s->i2coe;
+        break;
+
+    /* I2COUT Register */
+    case 0x00b10:
+        val = s->i2cout;
+        break;
+
+    /* I2CSEL Register */
+    case 0x00b18:
+        val = s->i2csel;
+        break;
+
+    default:
+#if 0
+        printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
+		addr);
+#endif
+        break;
+    }
+    return val;
+}
+
+static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
+                              uint32_t val)
+{
+    MaltaFPGAState *s = opaque;
+    uint32_t saddr;
+
+    saddr = (addr & 0xfffff);
+
+    switch (saddr) {
+
+    /* SWITCH Register */
+    case 0x00200:
+        break;
+
+    /* JMPRS Register */
+    case 0x00210:
+        break;
+
+    /* LEDBAR Register */
+    /* XXX: implement a 8-LED array */
+    case 0x00408:
+        s->leds = val & 0xff;
+        break;
+
+    /* ASCIIWORD Register */
+    case 0x00410:
+        snprintf(s->display_text, 9, "%08X", val);
+        malta_fpga_update_display(s);
+        break;
+
+    /* ASCIIPOS0 to ASCIIPOS7 Registers */
+    case 0x00418:
+    case 0x00420:
+    case 0x00428:
+    case 0x00430:
+    case 0x00438:
+    case 0x00440:
+    case 0x00448:
+    case 0x00450:
+        s->display_text[(saddr - 0x00418) >> 3] = (char) val;
+        malta_fpga_update_display(s);
+        break;
+
+    /* SOFTRES Register */
+    case 0x00500:
+        if (val == 0x42)
+            qemu_system_reset_request ();
+        break;
+
+    /* BRKRES Register */
+    case 0x00508:
+        s->brk = val & 0xff;
+        break;
+
+    /* UART Registers */
+    case 0x00900:
+    case 0x00908:
+    case 0x00910:
+    case 0x00918:
+    case 0x00920:
+    case 0x00928:
+    case 0x00930:
+    case 0x00938:
+        serial_mm_writeb(s->uart, addr, val);
+        break;
+
+    /* GPOUT Register */
+    case 0x00a00:
+        s->gpout = val & 0xff;
+        break;
+
+    /* I2COE Register */
+    case 0x00b08:
+        s->i2coe = val & 0x03;
+        break;
+
+    /* I2COUT Register */
+    case 0x00b10:
+        eeprom24c0x_write(val & 0x02, val & 0x01);
+        s->i2cout = val;
+        break;
+
+    /* I2CSEL Register */
+    case 0x00b18:
+        s->i2csel = val & 0x01;
+        break;
+
+    default:
+#if 0
+        printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
+		addr);
+#endif
+        break;
+    }
+}
+
+static CPUReadMemoryFunc *malta_fpga_read[] = {
+   malta_fpga_readl,
+   malta_fpga_readl,
+   malta_fpga_readl
+};
+
+static CPUWriteMemoryFunc *malta_fpga_write[] = {
+   malta_fpga_writel,
+   malta_fpga_writel,
+   malta_fpga_writel
+};
+
+void malta_fpga_reset(void *opaque)
+{
+    MaltaFPGAState *s = opaque;
+
+    s->leds   = 0x00;
+    s->brk    = 0x0a;
+    s->gpout  = 0x00;
+    s->i2cin  = 0x3;
+    s->i2coe  = 0x0;
+    s->i2cout = 0x3;
+    s->i2csel = 0x1;
+
+    s->display_text[8] = '\0';
+    snprintf(s->display_text, 9, "        ");
+    malta_fpga_update_display(s);
+}
+
+MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, CPUState *env)
+{
+    MaltaFPGAState *s;
+    CharDriverState *uart_chr;
+    int malta;
+
+    s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
+
+    malta = cpu_register_io_memory(0, malta_fpga_read,
+                                   malta_fpga_write, s);
+
+    cpu_register_physical_memory(base, 0x100000, malta);
+
+    s->display = qemu_chr_open("vc");
+    qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
+    qemu_chr_printf(s->display, "+--------+\r\n");
+    qemu_chr_printf(s->display, "+        +\r\n");
+    qemu_chr_printf(s->display, "+--------+\r\n");
+    qemu_chr_printf(s->display, "\n");
+    qemu_chr_printf(s->display, "Malta ASCII\r\n");
+    qemu_chr_printf(s->display, "+--------+\r\n");
+    qemu_chr_printf(s->display, "+        +\r\n");
+    qemu_chr_printf(s->display, "+--------+\r\n");
+
+    uart_chr = qemu_chr_open("vc");
+    qemu_chr_printf(uart_chr, "CBUS UART\r\n");
+    s->uart = serial_mm_init(base, 3, env->irq[2], uart_chr, 0);
+
+    malta_fpga_reset(s);
+    qemu_register_reset(malta_fpga_reset, s);
+
+    return s;
+}
+
+/* Audio support */
+#ifdef HAS_AUDIO
+static void audio_init (PCIBus *pci_bus)
+{
+    struct soundhw *c;
+    int audio_enabled = 0;
+
+    for (c = soundhw; !audio_enabled && c->name; ++c) {
+        audio_enabled = c->enabled;
+    }
+
+    if (audio_enabled) {
+        AudioState *s;
+
+        s = AUD_init ();
+        if (s) {
+            for (c = soundhw; c->name; ++c) {
+                if (c->enabled) {
+                    if (c->isa) {
+                        fprintf(stderr, "qemu: Unsupported Sound Card: %s\n", c->name);
+                        exit(1);
+                    }
+                    else {
+                        if (pci_bus) {
+                            c->init.init_pci (pci_bus, s);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+#endif
+
+/* Network support */
+static void network_init (PCIBus *pci_bus)
+{
+    int i;
+    NICInfo *nd;
+
+    for(i = 0; i < nb_nics; i++) {
+        nd = &nd_table[i];
+        if (!nd->model) {
+            nd->model = "pcnet";
+        }
+        if (i == 0  && strcmp(nd->model, "pcnet") == 0) {
+            /* The malta board has a PCNet card using PCI SLOT 11 */
+            pci_nic_init(pci_bus, nd, 88);
+        } else {
+            pci_nic_init(pci_bus, nd, -1);
+        }
+    }
+}
+
+/* ROM and pseudo bootloader
+
+   The following code implements a very very simple bootloader. It first
+   loads the registers a0 to a3 to the values expected by the OS, and
+   then jump at the kernel address.
+
+   The bootloader should pass the locations of the kernel arguments and
+   environment variables tables. Those tables contain the 32-bit address
+   of NULL terminated strings. The environment variables table should be
+   terminated by a NULL address.
+
+   For a simpler implementation, the number of kernel arguments is fixed
+   to two (the name of the kernel and the command line), and the two
+   tables are actually the same one.
+
+   The registers a0 to a3 should contain the following values:
+     a0 - number of kernel arguments
+     a1 - 32-bit address of the kernel arguments table
+     a2 - 32-bit address of the environment variables table
+     a3 - RAM size in bytes
+*/
+
+static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_entry)
+{
+    uint32_t *p;
+
+    /* Small bootloader */
+    p = (uint32_t *) (phys_ram_base + bios_offset);
+    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
+    stl_raw(p++, 0x00000000);                                      /* nop */
+
+    /* YAMON service vector */
+    stl_raw(phys_ram_base + bios_offset + 0x500, 0xbfc00580);      /* start: */					
+    stl_raw(phys_ram_base + bios_offset + 0x504, 0xbfc0083c);      /* print_count: */
+    stl_raw(phys_ram_base + bios_offset + 0x520, 0xbfc00580);      /* start: */					
+    stl_raw(phys_ram_base + bios_offset + 0x52c, 0xbfc00800);      /* flush_cache: */
+    stl_raw(phys_ram_base + bios_offset + 0x534, 0xbfc00808);      /* print: */
+    stl_raw(phys_ram_base + bios_offset + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
+    stl_raw(phys_ram_base + bios_offset + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
+    stl_raw(phys_ram_base + bios_offset + 0x540, 0xbfc00800);      /* reg_ic_isr: */
+    stl_raw(phys_ram_base + bios_offset + 0x544, 0xbfc00800);      /* unred_ic_isr: */
+    stl_raw(phys_ram_base + bios_offset + 0x548, 0xbfc00800);      /* reg_esr: */
+    stl_raw(phys_ram_base + bios_offset + 0x54c, 0xbfc00800);      /* unreg_esr: */
+    stl_raw(phys_ram_base + bios_offset + 0x550, 0xbfc00800);      /* getchar: */
+    stl_raw(phys_ram_base + bios_offset + 0x554, 0xbfc00800);      /* syscon_read: */
+
+
+    /* Second part of the bootloader */
+    p = (uint32_t *) (phys_ram_base + bios_offset + 0x580);
+    stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
+    stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
+    stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, a0, low(ENVP_ADDR) */
+    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
+    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a0, low(ENVP_ADDR) */
+    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
+    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
+    stl_raw(p++, 0x3c070000 | (env->ram_size >> 16));              /* lui a3, high(env->ram_size) */
+    stl_raw(p++, 0x34e70000 | (env->ram_size & 0xffff));           /* ori a3, a3, low(env->ram_size) */
+
+    /* Load BAR registers as done by YAMON */
+    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
+#else
+    stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
+#endif
+    stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
+#else
+    stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
+#endif
+    stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
+#else
+    stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
+#endif
+    stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
+#else
+    stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
+#endif
+    stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
+#else
+    stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
+#endif
+    stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
+#else
+    stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
+#endif
+    stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
+
+    /* Jump to kernel code */
+    stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
+    stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
+    stl_raw(p++, 0x03e00008);                                      /* jr ra */
+    stl_raw(p++, 0x00000000);                                      /* nop */
+
+    /* YAMON subroutines */
+    p = (uint32_t *) (phys_ram_base + bios_offset + 0x800);
+    stl_raw(p++, 0x03e00008);                                     /* jr ra */
+    stl_raw(p++, 0x24020000);                                     /* li v0,0 */
+   /* 808 YAMON print */
+    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
+    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
+    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
+    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
+    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
+    stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x08000205);                                     /* j 814 */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
+    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
+    /* 0x83c YAMON print_count */
+    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
+    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
+    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
+    stl_raw(p++, 0x00c06021);                                     /* move t4,a2 */
+    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
+    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
+    stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
+    stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
+    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
+    /* 0x870 */
+    stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
+    stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
+    stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
+    stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x03e00008);                                     /* jr ra */
+    stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
+
+}
+
+static void prom_set(int index, const char *string, ...)
+{
+    va_list ap;
+    int32_t *p;
+    int32_t table_addr;
+    char *s;
+
+    if (index >= ENVP_NB_ENTRIES)
+        return;
+
+    p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
+    p += index;
+
+    if (string == NULL) {
+        stl_raw(p, 0);
+        return;
+    }
+
+    table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
+    s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
+
+    stl_raw(p, table_addr);
+
+    va_start(ap, string);
+    vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
+    va_end(ap);
+}
+
+/* Kernel */
+static int64_t load_kernel (CPUState *env)
+{
+    int64_t kernel_entry, kernel_low, kernel_high;
+    int index = 0;
+    long initrd_size;
+    ram_addr_t initrd_offset;
+
+    if (load_elf(env->kernel_filename, VIRT_TO_PHYS_ADDEND,
+                 &kernel_entry, &kernel_low, &kernel_high) < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                env->kernel_filename);
+      exit(1);
+    }
+
+    /* load initrd */
+    initrd_size = 0;
+    initrd_offset = 0;
+    if (env->initrd_filename) {
+        initrd_size = get_image_size (env->initrd_filename);
+        if (initrd_size > 0) {
+            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
+            if (initrd_offset + initrd_size > env->ram_size) {
+                fprintf(stderr,
+                        "qemu: memory too small for initial ram disk '%s'\n",
+                        env->initrd_filename);
+                exit(1);
+            }
+            initrd_size = load_image(env->initrd_filename,
+                                     phys_ram_base + initrd_offset);
+        }
+        if (initrd_size == (target_ulong) -1) {
+            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                    env->initrd_filename);
+            exit(1);
+        }
+    }
+
+    /* Store command line.  */
+    prom_set(index++, env->kernel_filename);
+    if (initrd_size > 0)
+        prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
+                 PHYS_TO_VIRT(initrd_offset), initrd_size,
+                 env->kernel_cmdline);
+    else
+        prom_set(index++, env->kernel_cmdline);
+
+    /* Setup minimum environment variables */
+    prom_set(index++, "memsize");
+    prom_set(index++, "%i", env->ram_size);
+    prom_set(index++, "modetty0");
+    prom_set(index++, "38400n8r");
+    prom_set(index++, NULL);
+
+    return kernel_entry;
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+    cpu_reset(env);
+
+    /* The bootload does not need to be rewritten as it is located in a
+       read only location. The kernel location and the arguments table
+       location does not change. */
+    if (env->kernel_filename) {
+        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
+        load_kernel (env);
+    }
+}
+
+static
+void mips_malta_init (int ram_size, int vga_ram_size, int boot_device,
+                      DisplayState *ds, const char **fd_filename, int snapshot,
+                      const char *kernel_filename, const char *kernel_cmdline,
+                      const char *initrd_filename, const char *cpu_model)
+{
+    char buf[1024];
+    unsigned long bios_offset;
+    int64_t kernel_entry;
+    PCIBus *pci_bus;
+    CPUState *env;
+    RTCState *rtc_state;
+    /* fdctrl_t *floppy_controller; */
+    MaltaFPGAState *malta_fpga;
+    int ret;
+    mips_def_t *def;
+    qemu_irq *i8259;
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+#ifdef TARGET_MIPS64
+        cpu_model = "R4000";
+#else
+        cpu_model = "24Kf";
+#endif
+    }
+    if (mips_find_by_name(cpu_model, &def) != 0)
+        def = NULL;
+    env = cpu_init();
+    cpu_mips_register(env, def);
+    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
+    qemu_register_reset(main_cpu_reset, env);
+
+    /* allocate RAM */
+    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
+
+    /* Map the bios at two physical locations, as on the real board */
+    bios_offset = ram_size + vga_ram_size;
+    cpu_register_physical_memory(0x1e000000LL,
+                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
+    cpu_register_physical_memory(0x1fc00000LL,
+                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
+
+    /* Load a BIOS image except if a kernel image has been specified. In
+       the later case, just write a small bootloader to the flash
+       location. */
+    if (kernel_filename) {
+        env->ram_size = ram_size;
+        env->kernel_filename = kernel_filename;
+        env->kernel_cmdline = kernel_cmdline;
+        env->initrd_filename = initrd_filename;
+        kernel_entry = load_kernel(env);
+        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
+        write_bootloader(env, bios_offset, kernel_entry);
+    } else {
+        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+        ret = load_image(buf, phys_ram_base + bios_offset);
+        if (ret < 0 || ret > BIOS_SIZE) {
+            fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
+                    buf);
+            exit(1);
+        }
+    }
+
+    /* Board ID = 0x420 (Malta Board with CoreLV)
+       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
+       map to the board ID. */
+    stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
+
+    /* Init internal devices */
+    cpu_mips_irq_init_cpu(env);
+    cpu_mips_clock_init(env);
+    cpu_mips_irqctrl_init();
+
+    /* FPGA */
+    malta_fpga = malta_fpga_init(0x1f000000LL, env);
+
+    /* Interrupt controller */
+    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
+    i8259 = i8259_init(env->irq[2]);
+
+    /* Northbridge */
+    pci_bus = pci_gt64120_init(i8259);
+
+    /* Southbridge */
+    piix4_init(pci_bus, 80);
+    pci_piix3_ide_init(pci_bus, bs_table, 81, i8259);
+    usb_uhci_init(pci_bus, 82);
+    piix4_pm_init(pci_bus, 83);
+    pit = pit_init(0x40, i8259[0]);
+    DMA_init(0);
+
+    /* Super I/O */
+    i8042_init(i8259[1], i8259[12], 0x60);
+    rtc_state = rtc_init(0x70, i8259[8]);
+    if (serial_hds[0])
+        serial_init(0x3f8, i8259[4], serial_hds[0]);
+    if (serial_hds[1])
+        serial_init(0x2f8, i8259[3], serial_hds[1]);
+    if (parallel_hds[0])
+        parallel_init(0x378, i8259[7], parallel_hds[0]);
+    /* XXX: The floppy controller does not work correctly, something is
+       probably wrong.
+    floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd_table); */
+
+    /* Sound card */
+#ifdef HAS_AUDIO
+    audio_init(pci_bus);
+#endif
+
+    /* Network card */
+    network_init(pci_bus);
+
+    /* Optional PCI video card */
+    pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size,
+                        ram_size, vga_ram_size);
+}
+
+QEMUMachine mips_malta_machine = {
+    "malta",
+    "MIPS Malta Core LV",
+    mips_malta_init,
+};

Added: trunk/src/host/qemu-neo1973/hw/mips_pica61.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_pica61.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/mips_pica61.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,179 @@
+/*
+ * QEMU Malta board support
+ *
+ * Copyright (c) 2007 Hervé Poussineau
+ *
+ * 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"
+
+#ifdef TARGET_WORDS_BIGENDIAN
+#define BIOS_FILENAME "mips_bios.bin"
+#else
+#define BIOS_FILENAME "mipsel_bios.bin"
+#endif
+
+#ifdef TARGET_MIPS64
+#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
+#else
+#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
+#endif
+
+#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
+
+static const int ide_iobase[2] = { 0x1f0, 0x170 };
+static const int ide_iobase2[2] = { 0x3f6, 0x376 };
+static const int ide_irq[2] = { 14, 15 };
+
+static uint32_t serial_base[MAX_SERIAL_PORTS] = { 0x80006000, 0x80007000 };
+static int serial_irq[MAX_SERIAL_PORTS] = { 8, 9 };
+
+extern FILE *logfile;
+
+static void main_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+    cpu_reset(env);
+}
+
+static
+void mips_pica61_init (int ram_size, int vga_ram_size, int boot_device,
+                    DisplayState *ds, const char **fd_filename, int snapshot,
+                    const char *kernel_filename, const char *kernel_cmdline,
+                    const char *initrd_filename, const char *cpu_model)
+{
+    char buf[1024];
+    unsigned long bios_offset;
+    int bios_size;
+    CPUState *env;
+    int i;
+    mips_def_t *def;
+    int available_ram;
+    qemu_irq *i8259;
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+#ifdef TARGET_MIPS64
+        cpu_model = "R4000";
+#else
+        /* FIXME: All wrong, this maybe should be R3000 for the older PICAs. */
+        cpu_model = "24Kf";
+#endif
+    }
+    if (mips_find_by_name(cpu_model, &def) != 0)
+        def = NULL;
+    env = cpu_init();
+    cpu_mips_register(env, def);
+    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
+    qemu_register_reset(main_cpu_reset, env);
+
+    /* allocate RAM (limited to 256 MB) */
+    if (ram_size < 256 * 1024 * 1024)
+        available_ram = ram_size;
+    else
+        available_ram = 256 * 1024 * 1024;
+    cpu_register_physical_memory(0, available_ram, IO_MEM_RAM);
+
+    /* load a BIOS image */
+    bios_offset = ram_size + vga_ram_size;
+    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+    bios_size = load_image(buf, phys_ram_base + bios_offset);
+    if ((bios_size <= 0) || (bios_size > BIOS_SIZE)) {
+        /* fatal */
+        fprintf(stderr, "qemu: Error, could not load MIPS bios '%s'\n",
+                buf);
+        exit(1);
+    }
+    cpu_register_physical_memory(0x1fc00000,
+                                     BIOS_SIZE, bios_offset | IO_MEM_ROM);
+
+    /* Device map
+     *
+     * addr 0xe0004000: mc146818
+     * addr 0xe0005000 intr 6: ps2 keyboard
+     * addr 0xe0005000 intr 7: ps2 mouse
+     * addr 0xe0006000 intr 8: ns16550a,
+     * addr 0xe0007000 intr 9: ns16550a
+     * isa_io_base 0xe2000000 isa_mem_base 0xe3000000
+     */
+
+    /* Init CPU internal devices */
+    cpu_mips_irq_init_cpu(env);
+    cpu_mips_clock_init(env);
+    cpu_mips_irqctrl_init();
+
+    /* Register 64 KB of ISA IO space at 0x10000000 */
+    isa_mmio_init(0x10000000, 0x00010000);
+    isa_mem_base = 0x11000000;
+
+    /* PC style IRQ (i8259/i8254) and DMA (i8257) */
+    /* The PIC is attached to the MIPS CPU INT0 pin */
+    i8259 = i8259_init(env->irq[2]);
+    rtc_mm_init(0x80004070, 1, i8259[14]);
+    pit_init(0x40, 0);
+
+    /* Keyboard (i8042) */
+    i8042_mm_init(i8259[6], i8259[7], 0x80005060, 0);
+
+    /* IDE controller */
+    for(i = 0; i < 2; i++)
+        isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
+                     bs_table[2 * i], bs_table[2 * i + 1]);
+
+    /* Network controller */
+    /* FIXME: missing NS SONIC DP83932 */
+
+    /* SCSI adapter */
+    /* FIXME: missing NCR 53C94 */
+
+    /* ISA devices (floppy, serial, parallel) */
+    fdctrl_init(i8259[1], 1, 1, 0x80003000, fd_table);
+    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
+        if (serial_hds[i]) {
+            serial_mm_init(serial_base[i], 0, i8259[serial_irq[i]], serial_hds[i], 1);
+        }
+    }
+    for (i = 0; i < MAX_PARALLEL_PORTS; i++) {
+        if (parallel_hds[i]) {
+            /* FIXME: memory mapped! parallel_init(0x80008000, i8259[17], parallel_hds[i]); */
+        }
+    }
+
+    /* Sound card */
+    /* FIXME: missing Jazz sound, IRQ 18 */
+
+    /* LED indicator */
+    /* FIXME: missing LED indicator */
+
+    /* NVRAM */
+    ds1225y_init(0x80009000, "nvram");
+
+    /* Video card */
+    /* FIXME: This card is not the real one which was in the original PICA,
+     * but let's do with what Qemu currenly emulates... */
+    isa_vga_mm_init(ds, phys_ram_base + ram_size, ram_size, vga_ram_size,
+                    0x40000000, 0x60000000, 0);
+}
+
+QEMUMachine mips_pica61_machine = {
+    "pica61",
+    "Acer Pica 61",
+    mips_pica61_init,
+};

Modified: trunk/src/host/qemu-neo1973/hw/mips_r4k.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_r4k.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/mips_r4k.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -14,11 +14,11 @@
 #else
 #define BIOS_FILENAME "mipsel_bios.bin"
 #endif
-//#define BIOS_FILENAME "system.bin"
-#ifdef MIPS_HAS_MIPS64
-#define INITRD_LOAD_ADDR (int64_t)(int32_t)0x80800000
+
+#ifdef TARGET_MIPS64
+#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
 #else
-#define INITRD_LOAD_ADDR (int32_t)0x80800000
+#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
 #endif
 
 #define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
@@ -35,18 +35,6 @@
 static PITState *pit; /* PIT i8254 */
 
 /*i8254 PIT is attached to the IRQ0 at PIC i8259 */
-/*The PIC is attached to the MIPS CPU INT0 pin */
-static void pic_irq_request(void *opaque, int level)
-{
-    CPUState *env = first_cpu;
-    if (level) {
-        env->CP0_Cause |= 0x00000400;
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    } else {
-	env->CP0_Cause &= ~0x00000400;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
-}
 
 static void mips_qemu_writel (void *opaque, target_phys_addr_t addr,
 			      uint32_t val)
@@ -80,10 +68,12 @@
 		  const char *kernel_cmdline,
 		  const char *initrd_filename)
 {
-    int64_t entry = 0;
+    int64_t entry, kernel_low, kernel_high;
     long kernel_size, initrd_size;
+    ram_addr_t initrd_offset;
 
-    kernel_size = load_elf(kernel_filename, VIRT_TO_PHYS_ADDEND, &entry);
+    kernel_size = load_elf(kernel_filename, VIRT_TO_PHYS_ADDEND,
+                           &entry, &kernel_low, &kernel_high);
     if (kernel_size >= 0) {
         if ((entry & ~0x7fffffffULL) == 0x80000000)
             entry = (int32_t)entry;
@@ -96,9 +86,20 @@
 
     /* load initrd */
     initrd_size = 0;
+    initrd_offset = 0;
     if (initrd_filename) {
-        initrd_size = load_image(initrd_filename,
-                                 phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
+        initrd_size = get_image_size (initrd_filename);
+        if (initrd_size > 0) {
+            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
+            if (initrd_offset + initrd_size > ram_size) {
+                fprintf(stderr,
+                        "qemu: memory too small for initial ram disk '%s'\n",
+                        initrd_filename);
+                exit(1);
+            }
+            initrd_size = load_image(initrd_filename,
+                                     phys_ram_base + initrd_offset);
+        }
         if (initrd_size == (target_ulong) -1) {
             fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
                     initrd_filename);
@@ -110,8 +111,8 @@
     if (initrd_size > 0) {
         int ret;
         ret = sprintf(phys_ram_base + (16 << 20) - 256,
-                      "rd_start=0x" TLSZ " rd_size=%li ",
-                      INITRD_LOAD_ADDR,
+                      "rd_start=0x" TARGET_FMT_lx " rd_size=%li ",
+                      PHYS_TO_VIRT((uint32_t)initrd_offset),
                       initrd_size);
         strcpy (phys_ram_base + (16 << 20) - 256 + ret, kernel_cmdline);
     }
@@ -119,8 +120,8 @@
         strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline);
     }
 
-    *(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678);
-    *(int *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
+    *(int32_t *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678);
+    *(int32_t *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
 }
 
 static void main_cpu_reset(void *opaque)
@@ -133,19 +134,33 @@
                      env->kernel_cmdline, env->initrd_filename);
 }
 
+static
 void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device,
                     DisplayState *ds, const char **fd_filename, int snapshot,
                     const char *kernel_filename, const char *kernel_cmdline,
-                    const char *initrd_filename)
+                    const char *initrd_filename, const char *cpu_model)
 {
     char buf[1024];
     unsigned long bios_offset;
     int bios_size;
     CPUState *env;
-    static RTCState *rtc_state;
+    RTCState *rtc_state;
     int i;
+    mips_def_t *def;
+    qemu_irq *i8259;
 
+    /* init CPUs */
+    if (cpu_model == NULL) {
+#ifdef TARGET_MIPS64
+        cpu_model = "R4000";
+#else
+        cpu_model = "24Kf";
+#endif
+    }
+    if (mips_find_by_name(cpu_model, &def) != 0)
+        def = NULL;
     env = cpu_init();
+    cpu_mips_register(env, def);
     register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
     qemu_register_reset(main_cpu_reset, env);
 
@@ -154,7 +169,7 @@
 
     if (!mips_qemu_iomemtype) {
         mips_qemu_iomemtype = cpu_register_io_memory(0, mips_qemu_read,
-						     mips_qemu_write, NULL);
+                                                     mips_qemu_write, NULL);
     }
     cpu_register_physical_memory(0x1fbf0000, 0x10000, mips_qemu_iomemtype);
 
@@ -166,7 +181,7 @@
     snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
     bios_size = load_image(buf, phys_ram_base + bios_offset);
     if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
-	cpu_register_physical_memory((uint32_t)(0x1fc00000),
+	cpu_register_physical_memory(0x1fc00000,
 				     BIOS_SIZE, bios_offset | IO_MEM_ROM);
     } else {
 	/* not fatal */
@@ -184,22 +199,24 @@
     }
 
     /* Init CPU internal devices */
+    cpu_mips_irq_init_cpu(env);
     cpu_mips_clock_init(env);
     cpu_mips_irqctrl_init();
 
-    rtc_state = rtc_init(0x70, 8);
+    /* The PIC is attached to the MIPS CPU INT0 pin */
+    i8259 = i8259_init(env->irq[2]);
 
+    rtc_state = rtc_init(0x70, i8259[8]);
+
     /* Register 64 KB of ISA IO space at 0x14000000 */
     isa_mmio_init(0x14000000, 0x00010000);
     isa_mem_base = 0x10000000;
 
-    isa_pic = pic_init(pic_irq_request, env);
-    pit = pit_init(0x40, 0);
+    pit = pit_init(0x40, i8259[0]);
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
-            serial_init(&pic_set_irq_new, isa_pic,
-                        serial_io[i], serial_irq[i], serial_hds[i]);
+            serial_init(serial_io[i], i8259[serial_irq[i]], serial_hds[i]);
         }
     }
 
@@ -209,7 +226,7 @@
     if (nd_table[0].vlan) {
         if (nd_table[0].model == NULL
             || strcmp(nd_table[0].model, "ne2k_isa") == 0) {
-            isa_ne2000_init(0x300, 9, &nd_table[0]);
+            isa_ne2000_init(0x300, i8259[9], &nd_table[0]);
         } else {
             fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
             exit (1);
@@ -217,8 +234,11 @@
     }
 
     for(i = 0; i < 2; i++)
-        isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
+        isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
                      bs_table[2 * i], bs_table[2 * i + 1]);
+
+    i8042_init(i8259[1], i8259[12], 0x60);
+    ds1225y_init(0x9000, "nvram");
 }
 
 QEMUMachine mips_machine = {

Modified: trunk/src/host/qemu-neo1973/hw/mips_timer.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_timer.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/mips_timer.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -10,7 +10,7 @@
     static uint32_t seed = 0;
     uint32_t idx;
     seed = seed * 314159 + 1;
-    idx = (seed >> 16) % (MIPS_TLB_NB - env->CP0_Wired) + env->CP0_Wired;
+    idx = (seed >> 16) % (env->nb_tlb - env->CP0_Wired) + env->CP0_Wired;
     return idx;
 }
 
@@ -22,11 +22,11 @@
                            100 * 1000 * 1000, ticks_per_sec);
 }
 
-static void cpu_mips_update_count (CPUState *env, uint32_t count,
-                                   uint32_t compare)
+void cpu_mips_store_count (CPUState *env, uint32_t count)
 {
     uint64_t now, next;
     uint32_t tmp;
+    uint32_t compare = env->CP0_Compare;
 
     tmp = count;
     if (count == compare)
@@ -49,16 +49,21 @@
     qemu_mod_timer(env->timer, next);
 }
 
-void cpu_mips_store_count (CPUState *env, uint32_t value)
+static void cpu_mips_update_count (CPUState *env, uint32_t count)
 {
-    cpu_mips_update_count(env, value, env->CP0_Compare);
+    if (env->CP0_Cause & (1 << CP0Ca_DC))
+        return;
+
+    cpu_mips_store_count(env, count);
 }
 
 void cpu_mips_store_compare (CPUState *env, uint32_t value)
 {
-    cpu_mips_update_count(env, cpu_mips_get_count(env), value);
-    env->CP0_Cause &= ~0x00008000;
-    cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    env->CP0_Compare = value;
+    cpu_mips_update_count(env, cpu_mips_get_count(env));
+    if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR))
+        env->CP0_Cause &= ~(1 << CP0Ca_TI);
+    qemu_irq_lower(env->irq[7]);
 }
 
 static void mips_timer_cb (void *opaque)
@@ -71,15 +76,15 @@
         fprintf(logfile, "%s\n", __func__);
     }
 #endif
-    cpu_mips_update_count(env, cpu_mips_get_count(env), env->CP0_Compare);
-    env->CP0_Cause |= 0x00008000;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_mips_update_count(env, cpu_mips_get_count(env));
+    if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR))
+        env->CP0_Cause |= 1 << CP0Ca_TI;
+    qemu_irq_raise(env->irq[7]);
 }
 
 void cpu_mips_clock_init (CPUState *env)
 {
     env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env);
     env->CP0_Compare = 0;
-    cpu_mips_update_count(env, 1, 0);
+    cpu_mips_update_count(env, 1);
 }
-

Modified: trunk/src/host/qemu-neo1973/hw/modem.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/modem.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/modem.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -11,9 +11,6 @@
 struct modem_s {
     int enable;
     CharDriverState chr;
-    IOCanRWHandler *can_read;
-    IOReadHandler *read;
-    void *opaque;
     int cmd_len;
     char cmd[1024];
 #define FIFO_LEN	4096
@@ -31,24 +28,15 @@
     s->baud_delay = ticks_per_sec;
 }
 
-static void modem_add_read_handler(CharDriverState *chr,
-                IOCanRWHandler *modem_can_read, IOReadHandler *modem_read,
-                void *opaque)
-{
-    struct modem_s *s = (struct modem_s *) chr->opaque;
-
-    s->can_read = modem_can_read;
-    s->read = modem_read;
-    s->opaque = opaque;
-}
-
 static inline void modem_fifo_wake(struct modem_s *s)
 {
     if (!s->enable || !s->out_len)
         return;
 
-    if (s->can_read && s->can_read(s->opaque) && s->read) {
-        s->read(s->opaque, s->outfifo + s->out_start ++, 1);
+    if (s->chr.chr_can_read && s->chr.chr_can_read(s->chr.handler_opaque) &&
+                    s->chr.chr_read) {
+        s->chr.chr_read(s->chr.handler_opaque,
+                        s->outfifo + s->out_start ++, 1);
         s->out_len --;
         s->out_start &= FIFO_LEN - 1;
     }
@@ -440,7 +428,6 @@
     s->chr.opaque = s;
     s->chr.chr_write = modem_write;
     s->chr.chr_ioctl = modem_ioctl;
-    s->chr.chr_add_read_handler = modem_add_read_handler;
     s->out_tm = qemu_new_timer(vm_clock, modem_out_tick, s);
 
     return &s->chr;

Modified: trunk/src/host/qemu-neo1973/hw/nand.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/nand.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/nand.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -6,7 +6,7 @@
  * Copyright (c) 2006 Openedhand Ltd.
  * Written by Andrzej Zaborowski <balrog at zabor.org>
  *
- * This code is licensed under the GPLv2.
+ * This code is licensed under the GNU GPL v2.
  */
 
 #ifndef NAND_IO
@@ -396,24 +396,14 @@
 {
     int pagesize;
     struct nand_flash_s *s;
-    BlockDriverState *bs = 0;
 
     if (nand_flash_ids[chip_id].size == 0) {
         cpu_abort(cpu_single_env, "%s: Unsupported NAND chip ID.\n",
                         __FUNCTION__);
     }
 
-    if (mtd_filename) {
-        bs = bdrv_new("mtd");
-        if (bdrv_open(bs, mtd_filename, snapshot ? BDRV_O_SNAPSHOT : 0) < 0 ||
-                        qemu_key_check(bs, mtd_filename)) {
-            bdrv_delete(bs);
-            bs = 0;
-        }
-    }
- 
     s = (struct nand_flash_s *) qemu_mallocz(sizeof(struct nand_flash_s));
-    s->bdrv = bs;
+    s->bdrv = mtd_bdrv;
     s->manf_id = manf_id;
     s->chip_id = chip_id;
     s->size = nand_flash_ids[s->chip_id].size << 20;
@@ -442,13 +432,13 @@
 
     pagesize = 1 << s->oob_shift;
     s->mem_oob = 1;
-    if (bs && bdrv_getlength(bs) >=
+    if (s->bdrv && bdrv_getlength(s->bdrv) >=
                     (s->pages << s->page_shift) + (s->pages << s->oob_shift)) {
         pagesize = 0;
         s->mem_oob = 0;
     }
 
-    if (!bs)
+    if (!s->bdrv)
         pagesize += 1 << s->page_shift;
     if (pagesize)
         s->storage = (uint8_t *) memset(qemu_malloc(s->pages * pagesize),

Modified: trunk/src/host/qemu-neo1973/hw/ne2000.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ne2000.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/ne2000.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -136,7 +136,7 @@
     uint8_t phys[6]; /* mac address */
     uint8_t curpag;
     uint8_t mult[8]; /* multicast mask array */
-    int irq;
+    qemu_irq irq;
     PCIDevice *pci_dev;
     VLANClientState *vc;
     uint8_t macaddr[6];
@@ -164,16 +164,10 @@
     int isr;
     isr = (s->isr & s->imr) & 0x7f;
 #if defined(DEBUG_NE2000)
-    printf("NE2000: Set IRQ line %d to %d (%02x %02x)\n",
-	   s->irq, isr ? 1 : 0, s->isr, s->imr);
+    printf("NE2000: Set IRQ to %d (%02x %02x)\n",
+	   isr ? 1 : 0, s->isr, s->imr);
 #endif
-    if (s->irq == 16) {
-        /* PCI irq */
-        pci_set_irq(s->pci_dev, 0, (isr != 0));
-    } else {
-        /* ISA irq */
-        pic_set_irq(s->irq, (isr != 0));
-    }
+    qemu_set_irq(s->irq, (isr != 0));
 }
 
 #define POLYNOMIAL 0x04c11db6
@@ -206,7 +200,7 @@
 
     index = s->curpag << 8;
     boundary = s->boundary << 8;
-    if (index <= boundary)
+    if (index < boundary)
         avail = boundary - index;
     else
         avail = (s->stop - s->start) - (index - boundary);
@@ -647,6 +641,7 @@
 static void ne2000_save(QEMUFile* f,void* opaque)
 {
 	NE2000State* s=(NE2000State*)opaque;
+        int tmp;
 
         if (s->pci_dev)
             pci_device_save(s->pci_dev, f);
@@ -669,7 +664,8 @@
 	qemu_put_buffer(f, s->phys, 6);
 	qemu_put_8s(f, &s->curpag);
 	qemu_put_buffer(f, s->mult, 8);
-	qemu_put_be32s(f, &s->irq);
+        tmp = 0;
+	qemu_put_be32s(f, &tmp); /* ignored, was irq */
 	qemu_put_buffer(f, s->mem, NE2000_MEM_SIZE);
 }
 
@@ -677,6 +673,7 @@
 {
 	NE2000State* s=(NE2000State*)opaque;
         int ret;
+        int tmp;
 
         if (version_id > 3)
             return -EINVAL;
@@ -709,13 +706,13 @@
 	qemu_get_buffer(f, s->phys, 6);
 	qemu_get_8s(f, &s->curpag);
 	qemu_get_buffer(f, s->mult, 8);
-	qemu_get_be32s(f, &s->irq);
+	qemu_get_be32s(f, &tmp); /* ignored */
 	qemu_get_buffer(f, s->mem, NE2000_MEM_SIZE);
 
 	return 0;
 }
 
-void isa_ne2000_init(int base, int irq, NICInfo *nd)
+void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd)
 {
     NE2000State *s;
     
@@ -781,7 +778,7 @@
     register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
 }
 
-void pci_ne2000_init(PCIBus *bus, NICInfo *nd)
+void pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
     PCINE2000State *d;
     NE2000State *s;
@@ -789,7 +786,7 @@
     
     d = (PCINE2000State *)pci_register_device(bus,
                                               "NE2000", sizeof(PCINE2000State),
-                                              -1, 
+                                              devfn, 
                                               NULL, NULL);
     pci_conf = d->dev.config;
     pci_conf[0x00] = 0xec; // Realtek 8029
@@ -804,7 +801,7 @@
     pci_register_io_region(&d->dev, 0, 0x100, 
                            PCI_ADDRESS_SPACE_IO, ne2000_map);
     s = &d->ne2000;
-    s->irq = 16; // PCI interrupt
+    s->irq = d->dev.irq[0];
     s->pci_dev = (PCIDevice *)d;
     memcpy(s->macaddr, nd->macaddr, 6);
     ne2000_reset(s);

Modified: trunk/src/host/qemu-neo1973/hw/neo1973.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/neo1973.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/neo1973.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -56,15 +56,15 @@
 
 struct neo_board_s {
     struct s3c_state_s *cpu;
-    struct i2c_slave_s *pmu;
-    struct i2c_slave_s *wm;
-    struct i2c_slave_s *lcm;
+    i2c_slave *pmu;
+    i2c_slave *wm;
+    i2c_slave *lcm;
     CharDriverState *modem;
-    void *kbd_pic;
+    qemu_irq *kbd_pic;
 };
 
 /* Handlers for output ports */
-static void neo_bl_switch(int line, int level, void *opaque)
+static void neo_bl_switch(void *opaque, int line, int level)
 {
     neo_printf("LCD Backlight now %s.\n", level ? "on" : "off");
 }
@@ -80,46 +80,46 @@
 #endif
 }
 
-static void neo_gpspwr_switch(int line, int level, void *opaque)
+static void neo_gpspwr_switch(void *opaque, int line, int level)
 {
     neo_printf("GPS powered %s.\n", level ? "up" : "down");
 }
 
-static void neo_modem_rst_switch(int line, int level, void *opaque)
+static void neo_modem_rst_switch(void *opaque, int line, int level)
 {
     if (level)
         neo_printf("Modem reset.\n");
 }
 
-static void neo_modem_switch(int line, int level, void *opaque)
+static void neo_modem_switch(void *opaque, int line, int level)
 {
     struct neo_board_s *s = (struct neo_board_s *) opaque;
     modem_enable(s->modem, level);
     neo_printf("Modem powered %s.\n", level ? "up" : "down");
 }
 
-static void neo_lcd_rst_switch(int line, int level, void *opaque)
+static void neo_lcd_rst_switch(void *opaque, int line, int level)
 {
     if (level)
         neo_printf("LCD reset.\n");
 }
 
-static void neo_vib_switch(int line, int level, void *opaque)
+static void neo_vib_switch(void *opaque, int line, int level)
 {
     neo_printf("%s.\n", level ? "Buzz, buzz" : "Vibrator stopped");
 }
 
-static void neo_gsm_switch(int line, int level, void *opaque)
+static void neo_gsm_switch(void *opaque, int line, int level)
 {
     neo_printf("GSM %sabled.\n", level ? "dis" : "en");
 }
 
-static void neo_bt_switch(int line, int level, void *opaque)
+static void neo_bt_switch(void *opaque, int line, int level)
 {
     neo_printf("Bluetooth transciever %sabled.\n", level ? "en" : "dis");
 }
 
-static void neo_gps_switch(int line, int level, void *opaque)
+static void neo_gps_switch(void *opaque, int line, int level)
 {
     neo_printf("GPS %sV supply is now %s.\n",
 #ifdef GTA01Bv3
@@ -130,19 +130,19 @@
                     level ? "on" : "off");
 }
 
-static void neo_gps_rst_switch(int line, int level, void *opaque)
+static void neo_gps_rst_switch(void *opaque, int line, int level)
 {
     if (level)
         neo_printf("GPS reset.\n");
 }
 
 /* Handlers for input ports */
-static void neo_mmc_cover_switch(void *pic, int in)
+static void neo_mmc_cover_switch(void *irq, int in)
 {
-    pic_set_irq_new(pic, GTA01_IRQ_nSD_DETECT, !in);
+    qemu_set_irq((qemu_irq) irq, !in);
 }
 
-static void neo_mmc_writeprotect_switch(void *pic, int wp)
+static void neo_mmc_writeprotect_switch(void *irq, int wp)
 {
 }
 
@@ -152,10 +152,10 @@
     struct neo_board_s *s = (struct neo_board_s *) opaque;
     switch (keycode & 0x7f) {
     case 0x1c:	/* Return */
-        pic_set_irq_new(s->kbd_pic, GTA01_IRQ_911_KEY, !(keycode & 0x80));
+        qemu_set_irq(s->kbd_pic[GTA01_IRQ_911_KEY], !(keycode & 0x80));
         break;
     case 0x39:	/* Space */
-        pic_set_irq_new(s->kbd_pic, GTA01_IRQ_HOLD_KEY, !(keycode & 0x80));
+        qemu_set_irq(s->kbd_pic[GTA01_IRQ_HOLD_KEY], !(keycode & 0x80));
         pcf_onkey_set(s->pmu, !(keycode & 80));	/* Active LOW */
         break;
     }
@@ -163,45 +163,47 @@
 
 static void neo_kbd_init(struct neo_board_s *s)
 {
-    s->kbd_pic = s->cpu->io;
+    s->kbd_pic = s3c_gpio_in_get(s->cpu->io);
     qemu_add_kbd_event_handler(neo_kbd_handler, s);
 }
 
 static void neo_gpio_setup(struct neo_board_s *s)
 {
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_BACKLIGHT,
-                    neo_bl_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_GPS_PWRON,
-                    neo_gpspwr_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_MODEM_RST,
-                    neo_modem_rst_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_MODEM_ON,
-                    neo_modem_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_LCD_RESET,
-                    neo_lcd_rst_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_VIBRATOR_ON,
-                    neo_vib_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_VIBRATOR_ON2,
-                    neo_vib_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01v3_GPIO_nGSM_EN,
-                    neo_gsm_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01Bv2_GPIO_nGSM_EN,
-                    neo_gsm_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_BT_EN,
-                    neo_bt_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_GPS_EN_2V8,
-                    neo_gps_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_GPS_EN_3V,
-                    neo_gps_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_GPS_EN_3V3,
-                    neo_gps_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_GPS_RESET,
-                    neo_gps_rst_switch, s);
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_BACKLIGHT,
+                    *qemu_allocate_irqs(neo_bl_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_GPS_PWRON,
+                    *qemu_allocate_irqs(neo_gpspwr_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_MODEM_RST,
+                    *qemu_allocate_irqs(neo_modem_rst_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_MODEM_ON,
+                    *qemu_allocate_irqs(neo_modem_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_LCD_RESET,
+                    *qemu_allocate_irqs(neo_lcd_rst_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_VIBRATOR_ON,
+                    *qemu_allocate_irqs(neo_vib_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_VIBRATOR_ON2,
+                    *qemu_allocate_irqs(neo_vib_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01v3_GPIO_nGSM_EN,
+                    *qemu_allocate_irqs(neo_gsm_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01Bv2_GPIO_nGSM_EN,
+                    *qemu_allocate_irqs(neo_gsm_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_BT_EN,
+                    *qemu_allocate_irqs(neo_bt_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_GPS_EN_2V8,
+                    *qemu_allocate_irqs(neo_gps_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_GPS_EN_3V,
+                    *qemu_allocate_irqs(neo_gps_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_GPS_EN_3V3,
+                    *qemu_allocate_irqs(neo_gps_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_GPS_RESET,
+                    *qemu_allocate_irqs(neo_gps_rst_switch, s, 1));
 
     s3c_timers_cmp_handler_set(s->cpu->timers, 0, neo_bl_intensity, s);
 
     /* MMC/SD host */
-    s3c_mmci_handlers(s->cpu->mmci, s->cpu->io, neo_mmc_writeprotect_switch,
+    s3c_mmci_handlers(s->cpu->mmci,
+                    s3c_gpio_in_get(s->cpu->io)[GTA01_IRQ_nSD_DETECT],
+                    neo_mmc_writeprotect_switch,
                     neo_mmc_cover_switch);
 }
 
@@ -214,48 +216,47 @@
 
 /* National Semiconductor LM4857 Boomer audio amplifier */
 struct lm4857_s {
-    int i2c_dir;
-    struct i2c_slave_s i2c;
+    i2c_slave i2c;
     uint8_t regs[4];
 };
 
-void lm_reset(struct i2c_slave_s *i2c)
+void lm_reset(i2c_slave *i2c)
 {
-    struct lm4857_s *s = (struct lm4857_s *) i2c->opaque;
+    struct lm4857_s *s = (struct lm4857_s *) i2c;
     memset(s->regs, 0, sizeof(s->regs));
 }
 
-static void lm_start(void *opaque, int dir)
+static void lm_event(i2c_slave *i2c, enum i2c_event event)
 {
-    struct lm4857_s *s = (struct lm4857_s *) opaque;
-    s->i2c_dir = dir;
 }
 
-static int lm_tx(void *opaque, uint8_t *data, int len)
+static int lm_rx(i2c_slave *i2c)
 {
-    struct lm4857_s *s = (struct lm4857_s *) opaque;
+    return 0x00;
+}
+
+static int lm_tx(i2c_slave *i2c, uint8_t data)
+{
+    struct lm4857_s *s = (struct lm4857_s *) i2c;
     int reg, value;
-    if (s->i2c_dir)
-        return 1;
 
-    while (len --) {
-        reg = *data >> 6;
-        value = *(data ++) & 0x3f;
+    reg = data >> 6;
+    value = data & 0x3f;
 
-        if ((reg == 1 || reg == 2) && ((s->regs[reg] ^ value) & (1 << 5)))
-            printf("%s: 3D enhance %s.\n", __FUNCTION__,
-                            (value & (1 << 5)) ? "On" : "Off");
-        s->regs[reg] = value;
-    }
+    if ((reg == 1 || reg == 2) && ((s->regs[reg] ^ value) & (1 << 5)))
+        printf("%s: 3D enhance %s.\n", __FUNCTION__,
+                        (value & (1 << 5)) ? "On" : "Off");
+    s->regs[reg] = value;
     return 0;
 }
 
-struct i2c_slave_s *lm4857_init()
+i2c_slave *lm4857_init(i2c_bus *bus)
 {
-    struct lm4857_s *s = qemu_mallocz(sizeof(struct lm4857_s));
-    s->i2c.opaque = s;
-    s->i2c.tx = lm_tx;
-    s->i2c.start = lm_start;
+    struct lm4857_s *s = (struct lm4857_s *)
+            i2c_slave_init(bus, 0, sizeof(struct lm4857_s));
+    s->i2c.event = lm_event;
+    s->i2c.send = lm_tx;
+    s->i2c.recv = lm_rx;
 
     lm_reset(&s->i2c);
 
@@ -269,34 +270,32 @@
 
 static void neo_i2c_setup(struct neo_board_s *s)
 {
-    struct i2c_bus_s *bus = (struct i2c_bus_s *)
-            qemu_mallocz(sizeof(struct i2c_bus_s));
+    /* Attach the CPU on one end of our I2C bus.  */
+    i2c_bus *bus = s3c_i2c_bus(s->cpu->i2c);
 #ifdef HAS_AUDIO
     AudioState *audio;
 #endif
 
-    s->pmu = pcf5060x_init(s->cpu->pic, GTA01_IRQ_PCF50606, 0);
-    s->lcm = lm4857_init();
-
-    /* Attach the CPU on one end of our I2C bus.  */
-    i2c_master_attach(bus, s3c_i2c_master(s->cpu->i2c));
-
     /* Attach a PCF50606 to the bus */
-    i2c_slave_attach(bus, NEO_PMU_ADDR, s->pmu);
+    s->pmu = pcf5060x_init(bus,
+                    s3c_gpio_in_get(s->cpu->io)[GTA01_IRQ_PCF50606], 0);
+    i2c_set_slave_address(s->pmu, NEO_PMU_ADDR);
 
     /* Attach a LM4857 to the bus */
-    i2c_slave_attach(bus, NEO_AMP_ADDR, s->lcm);
+    s->lcm = lm4857_init(bus);
+    i2c_set_slave_address(s->lcm, NEO_AMP_ADDR);
 
 #ifdef HAS_AUDIO
     audio = AUD_init();
     if (!audio)
         return;
-    s->wm = wm8753_init(audio);
 
     /* Attach a WM8750 to the bus */
-    i2c_slave_attach(bus, NEO_WM_ADDR, s->wm);
+    s->wm = wm8753_init(bus, audio);
+    i2c_set_slave_address(s->wm, NEO_WM_ADDR);
+
     /* .. and to the sound interface.  */
-    s->cpu->i2s->opaque = s->wm->opaque;
+    s->cpu->i2s->opaque = s->wm;
     s->cpu->i2s->codec_out = wm8753_dac_dat;
     s->cpu->i2s->codec_in = wm8753_adc_dat;
     wm8753_data_req_set(s->wm, s->cpu->i2s->data_req, s->cpu->i2s);
@@ -329,23 +328,23 @@
 static void neo_init(int ram_size, int vga_ram_size, int boot_device,
                 DisplayState *ds, const char **fd_filename, int snapshot,
                 const char *kernel_filename, const char *kernel_cmdline,
-                const char *initrd_filename)
+                const char *initrd_filename, const char *cpu_model)
 {
     uint32_t neo_ram = 0x08000000;
     struct neo_board_s *s = (struct neo_board_s *)
             qemu_mallocz(sizeof(struct neo_board_s));
 
-    s->cpu = s3c2410_init(ds);
-
-    /* Setup memory */
-    if (ram_size < neo_ram + s->cpu->free_ram_start) {
+    /* Setup CPU & memory */
+    if (ram_size < neo_ram + S3C_SRAM_SIZE) {
         fprintf(stderr, "This platform requires %i bytes of memory\n",
-                        neo_ram + s->cpu->free_ram_start);
+                        neo_ram + S3C_SRAM_SIZE);
         exit(1);
     }
-    cpu_register_physical_memory(S3C_RAM_BASE, neo_ram,
-                    s->cpu->free_ram_start | IO_MEM_RAM);
-    s->cpu->free_ram_start += neo_ram;
+    if (cpu_model && strcmp(cpu_model, "arm920t")) {
+        fprintf(stderr, "This platform requires an ARM920T core\n");
+        exit(2);
+    }
+    s->cpu = s3c2410_init(neo_ram, ds);
 
     s3c_nand_register(s->cpu, nand_init(NAND_MFR_SAMSUNG, 0x76));
 
@@ -370,9 +369,9 @@
                     initrd_filename, 0x49e, S3C_RAM_BASE);
 #else
     load_image("u-boot.bin",
-                    phys_ram_base + S3C_SRAM_SIZE + 0x03f80000);
+                    phys_ram_base + 0x03f80000);
     load_image(kernel_filename,
-                    phys_ram_base + S3C_SRAM_SIZE + 0x02000000);
+                    phys_ram_base + 0x02000000);
     s->cpu->env->regs[15] = S3C_RAM_BASE | 0x03f80000;
 #endif
 

Modified: trunk/src/host/qemu-neo1973/hw/openpic.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/openpic.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/openpic.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -159,10 +159,10 @@
     uint32_t pcsr; /* CPU sensitivity register */
     IRQ_queue_t raised;
     IRQ_queue_t servicing;
-    CPUState *env;
+    qemu_irq *irqs;
 } IRQ_dst_t;
 
-struct openpic_t {
+typedef struct openpic_t {
     PCIDevice pci_dev;
     int mem_index;
     /* Global registers */
@@ -170,6 +170,7 @@
     uint32_t glbc; /* Global configuration register  */
     uint32_t micr; /* MPIC interrupt configuration register */
     uint32_t veni; /* Vendor identification register */
+    uint32_t pint; /* Processor initialization register */
     uint32_t spve; /* Spurious vector register */
     uint32_t tifr; /* Timer frequency reporting register */
     /* Source registers */
@@ -195,7 +196,9 @@
 	uint32_t mbr;    /* Mailbox register */
     } mailboxes[MAX_MAILBOXES];
 #endif
-};
+    /* IRQ out is used when in bypass mode (not implemented) */
+    qemu_irq irq_out;
+} openpic_t;
 
 static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
 {
@@ -254,19 +257,34 @@
     priority = IPVP_PRIORITY(src->ipvp);
     if (priority <= dst->pctp) {
 	/* Too low priority */
+        DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
+                __func__, n_IRQ, n_CPU);
 	return;
     }
     if (IRQ_testbit(&dst->raised, n_IRQ)) {
 	/* Interrupt miss */
+        DPRINTF("%s: IRQ %d was missed on CPU %d\n",
+                __func__, n_IRQ, n_CPU);
 	return;
     }
     set_bit(&src->ipvp, IPVP_ACTIVITY);
     IRQ_setbit(&dst->raised, n_IRQ);
-    if (priority > dst->raised.priority) {
-        IRQ_get_next(opp, &dst->raised);
-        DPRINTF("Raise CPU IRQ\n");
-        cpu_interrupt(dst->env, CPU_INTERRUPT_HARD);
+    if (priority < dst->raised.priority) {
+        /* An higher priority IRQ is already raised */
+        DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
+                __func__, n_IRQ, dst->raised.next, n_CPU);
+        return;
     }
+    IRQ_get_next(opp, &dst->raised);
+    if (IRQ_get_next(opp, &dst->servicing) != -1 &&
+        priority < dst->servicing.priority) {
+        DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
+                __func__, n_IRQ, dst->servicing.next, n_CPU);
+        /* Already servicing a higher priority IRQ */
+        return;
+    }
+    DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
+    qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
 }
 
 /* update pic state because registers for n_IRQ have changed value */
@@ -279,27 +297,34 @@
 
     if (!src->pending) {
         /* no irq pending */
+        DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
         return;
     }
     if (test_bit(&src->ipvp, IPVP_MASK)) {
 	/* Interrupt source is disabled */
+        DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
 	return;
     }
     if (IPVP_PRIORITY(src->ipvp) == 0) {
 	/* Priority set to zero */
+        DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
 	return;
     }
     if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
         /* IRQ already active */
+        DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
         return;
     }
     if (src->ide == 0x00000000) {
 	/* No target */
+        DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
 	return;
     }
 
-    if (!test_bit(&src->ipvp, IPVP_MODE) ||
-        src->ide == (1 << src->last_cpu)) {
+    if (src->ide == (1 << src->last_cpu)) {
+        /* Only one CPU is allowed to receive this IRQ */
+        IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
+    } else if (!test_bit(&src->ipvp, IPVP_MODE)) {
         /* Directed delivery mode */
         for (i = 0; i < opp->nb_cpus; i++) {
             if (test_bit(&src->ide, i))
@@ -307,9 +332,8 @@
         }
     } else {
         /* Distributed delivery mode */
-        /* XXX: incorrect code */
-        for (i = src->last_cpu; i < src->last_cpu; i++) {
-            if (i == MAX_IRQ)
+        for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
+            if (i == opp->nb_cpus)
                 i = 0;
             if (test_bit(&src->ide, i)) {
                 IRQ_local_pipe(opp, i, n_IRQ);
@@ -320,7 +344,7 @@
     }
 }
 
-void openpic_set_irq(void *opaque, int n_IRQ, int level)
+static void openpic_set_irq(void *opaque, int n_IRQ, int level)
 {
     openpic_t *opp = opaque;
     IRQ_src_t *src;
@@ -349,6 +373,7 @@
     /* Initialise controller registers */
     opp->frep = ((EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
     opp->veni = VENI;
+    opp->pint = 0x00000000;
     opp->spve = 0x000000FF;
     opp->tifr = 0x003F7A00;
     /* ? */
@@ -359,7 +384,7 @@
 	opp->src[i].ide  = 0x00000000;
     }
     /* Initialise IRQ destinations */
-    for (i = 0; i < opp->nb_cpus; i++) {
+    for (i = 0; i < MAX_CPU; i++) {
 	opp->dst[i].pctp      = 0x0000000F;
 	opp->dst[i].pcsr      = 0x00000000;
 	memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
@@ -510,6 +535,8 @@
 static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val)
 {
     openpic_t *opp = opaque;
+    IRQ_dst_t *dst;
+    int idx;
 
     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
     if (addr & 0xF)
@@ -529,11 +556,18 @@
     case 0x80: /* VENI */
 	break;
     case 0x90: /* PINT */
-        /* XXX: Should be able to reset any CPU */
-        if (val & 1) {
-            DPRINTF("Reset CPU IRQ\n");
-            //            cpu_interrupt(first_cpu, CPU_INTERRUPT_RESET);
+        for (idx = 0; idx < opp->nb_cpus; idx++) {
+            if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
+                DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
+                dst = &opp->dst[idx];
+                qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
+            } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
+                DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
+                dst = &opp->dst[idx];
+                qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
+            }
         }
+        opp->pint = val;
 	break;
 #if MAX_IPI > 0
     case 0xA0: /* IPI_IPVP */
@@ -734,7 +768,7 @@
     openpic_t *opp = opaque;
     IRQ_src_t *src;
     IRQ_dst_t *dst;
-    int idx, n_IRQ;
+    int idx, s_IRQ, n_IRQ;
 
     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
     if (addr & 0xF)
@@ -769,21 +803,21 @@
 	break;
     case 0xB0: /* PEOI */
         DPRINTF("PEOI\n");
-	n_IRQ = IRQ_get_next(opp, &dst->servicing);
-	IRQ_resetbit(&dst->servicing, n_IRQ);
+	s_IRQ = IRQ_get_next(opp, &dst->servicing);
+	IRQ_resetbit(&dst->servicing, s_IRQ);
 	dst->servicing.next = -1;
-	src = &opp->src[n_IRQ];
 	/* Set up next servicing IRQ */
-	IRQ_get_next(opp, &dst->servicing);
-	/* Check queued interrupts. */
-	n_IRQ = IRQ_get_next(opp, &dst->raised);
-	if (n_IRQ != -1) {
-	    src = &opp->src[n_IRQ];
-	    if (IPVP_PRIORITY(src->ipvp) > dst->servicing.priority) {
-                DPRINTF("Raise CPU IRQ\n");
-                cpu_interrupt(dst->env, CPU_INTERRUPT_HARD);
-            }
-	}
+	s_IRQ = IRQ_get_next(opp, &dst->servicing);
+        /* Check queued interrupts. */
+        n_IRQ = IRQ_get_next(opp, &dst->raised);
+        src = &opp->src[n_IRQ];
+        if (n_IRQ != -1 &&
+            (s_IRQ == -1 ||
+             IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
+            DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
+                    idx, n_IRQ);
+            qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
+        }
 	break;
     default:
         break;
@@ -814,11 +848,13 @@
 	retval = idx;
 	break;
     case 0xA0: /* PIAC */
+        DPRINTF("Lower OpenPIC INT output\n");
+        qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
 	n_IRQ = IRQ_get_next(opp, &dst->raised);
         DPRINTF("PIAC: irq=%d\n", n_IRQ);
 	if (n_IRQ == -1) {
 	    /* No more interrupt pending */
-            retval = opp->spve;
+            retval = IPVP_VECTOR(opp->spve);
 	} else {
 	    src = &opp->src[n_IRQ];
 	    if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
@@ -963,8 +999,8 @@
 #endif
 }
 
-openpic_t *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
-                         CPUPPCState **envp)
+qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
+                        qemu_irq **irqs, qemu_irq irq_out)
 {
     openpic_t *opp;
     uint8_t *pci_conf;
@@ -994,7 +1030,6 @@
     } else {
         opp = qemu_mallocz(sizeof(openpic_t));
     }
-
     opp->mem_index = cpu_register_io_memory(0, openpic_read,
                                             openpic_write, opp);
     
@@ -1019,9 +1054,11 @@
         opp->src[i].type = IRQ_INTERNAL;
     }
     for (i = 0; i < nb_cpus; i++)
-        opp->dst[i].env = envp[i];
+        opp->dst[i].irqs = irqs[i];
+    opp->irq_out = irq_out;
     openpic_reset(opp);
     if (pmem_index)
         *pmem_index = opp->mem_index;
-    return opp;
+
+    return qemu_allocate_irqs(openpic_set_irq, opp, MAX_IRQ);
 }

Modified: trunk/src/host/qemu-neo1973/hw/parallel.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/parallel.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/parallel.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -2,6 +2,7 @@
  * QEMU Parallel PORT emulation
  * 
  * Copyright (c) 2003-2005 Fabrice Bellard
+ * Copyright (c) 2007 Marko Kohtala
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -25,6 +26,18 @@
 
 //#define DEBUG_PARALLEL
 
+#ifdef DEBUG_PARALLEL
+#define pdebug(fmt, arg...) printf("pp: " fmt, ##arg)
+#else
+#define pdebug(fmt, arg...) ((void)0)
+#endif
+
+#define PARA_REG_DATA 0
+#define PARA_REG_STS 1
+#define PARA_REG_CTR 2
+#define PARA_REG_EPP_ADDR 3
+#define PARA_REG_EPP_DATA 4
+
 /*
  * These are the definitions for the Printer Status Register
  */
@@ -33,129 +46,362 @@
 #define PARA_STS_PAPER	0x20	/* Out of paper */
 #define PARA_STS_ONLINE	0x10	/* Online */
 #define PARA_STS_ERROR	0x08	/* Error complement */
+#define PARA_STS_TMOUT	0x01	/* EPP timeout */
 
 /*
  * These are the definitions for the Printer Control Register
  */
+#define PARA_CTR_DIR	0x20	/* Direction (1=read, 0=write) */
 #define PARA_CTR_INTEN	0x10	/* IRQ Enable */
 #define PARA_CTR_SELECT	0x08	/* Select In complement */
 #define PARA_CTR_INIT	0x04	/* Initialize Printer complement */
 #define PARA_CTR_AUTOLF	0x02	/* Auto linefeed complement */
 #define PARA_CTR_STROBE	0x01	/* Strobe complement */
 
+#define PARA_CTR_SIGNAL (PARA_CTR_SELECT|PARA_CTR_INIT|PARA_CTR_AUTOLF|PARA_CTR_STROBE)
+
 struct ParallelState {
-    uint8_t data;
-    uint8_t status; /* read only register */
+    uint8_t dataw;
+    uint8_t datar;
+    uint8_t status;
     uint8_t control;
-    int irq;
+    qemu_irq irq;
     int irq_pending;
     CharDriverState *chr;
     int hw_driver;
+    int epp_timeout;
+    uint32_t last_read_offset; /* For debugging */
 };
 
 static void parallel_update_irq(ParallelState *s)
 {
     if (s->irq_pending)
-        pic_set_irq(s->irq, 1);
+        qemu_irq_raise(s->irq);
     else
-        pic_set_irq(s->irq, 0);
+        qemu_irq_lower(s->irq);
 }
 
-static void parallel_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+static void
+parallel_ioport_write_sw(void *opaque, uint32_t addr, uint32_t val)
 {
     ParallelState *s = opaque;
     
+    pdebug("write addr=0x%02x val=0x%02x\n", addr, val);
+
     addr &= 7;
-#ifdef DEBUG_PARALLEL
-    printf("parallel: write addr=0x%02x val=0x%02x\n", addr, val);
-#endif
     switch(addr) {
-    case 0:
-        if (s->hw_driver) {
-            s->data = val;
-            qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_WRITE_DATA, &s->data);
-        } else {
-            s->data = val;
-            parallel_update_irq(s);
-        }
+    case PARA_REG_DATA:
+	s->dataw = val;
+	parallel_update_irq(s);
         break;
-    case 2:
-        if (s->hw_driver) {
-            s->control = val;
-            qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_WRITE_CONTROL, &s->control);
-        } else {
-            if ((val & PARA_CTR_INIT) == 0 ) {
-                s->status = PARA_STS_BUSY;
-                s->status |= PARA_STS_ACK;
-                s->status |= PARA_STS_ONLINE;
-                s->status |= PARA_STS_ERROR;
-            }
-            else if (val & PARA_CTR_SELECT) {
-                if (val & PARA_CTR_STROBE) {
-                    s->status &= ~PARA_STS_BUSY;
-                    if ((s->control & PARA_CTR_STROBE) == 0)
-                        qemu_chr_write(s->chr, &s->data, 1);
-                } else {
-                    if (s->control & PARA_CTR_INTEN) {
-                        s->irq_pending = 1;
-                    }
-                }
-            }
-            parallel_update_irq(s);
-            s->control = val;
-        }
+    case PARA_REG_CTR:
+	if ((val & PARA_CTR_INIT) == 0 ) {
+	    s->status = PARA_STS_BUSY;
+	    s->status |= PARA_STS_ACK;
+	    s->status |= PARA_STS_ONLINE;
+	    s->status |= PARA_STS_ERROR;
+	}
+	else if (val & PARA_CTR_SELECT) {
+	    if (val & PARA_CTR_STROBE) {
+		s->status &= ~PARA_STS_BUSY;
+		if ((s->control & PARA_CTR_STROBE) == 0)
+		    qemu_chr_write(s->chr, &s->dataw, 1);
+	    } else {
+		if (s->control & PARA_CTR_INTEN) {
+		    s->irq_pending = 1;
+		}
+	    }
+	}
+	parallel_update_irq(s);
+	s->control = val;
         break;
     }
 }
 
-static uint32_t parallel_ioport_read(void *opaque, uint32_t addr)
+static void parallel_ioport_write_hw(void *opaque, uint32_t addr, uint32_t val)
 {
     ParallelState *s = opaque;
+    uint8_t parm = val;
+
+    /* Sometimes programs do several writes for timing purposes on old
+       HW. Take care not to waste time on writes that do nothing. */
+
+    s->last_read_offset = ~0U;
+
+    addr &= 7;
+    switch(addr) {
+    case PARA_REG_DATA:
+        if (s->dataw == val)
+	    return;
+	pdebug("wd%02x\n", val);
+	qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_WRITE_DATA, &parm);
+	s->dataw = val;
+        break;
+    case PARA_REG_STS:
+	pdebug("ws%02x\n", val);
+	if (val & PARA_STS_TMOUT)
+	    s->epp_timeout = 0;
+	break;
+    case PARA_REG_CTR:
+        val |= 0xc0;
+        if (s->control == val)
+	    return;
+	pdebug("wc%02x\n", val);
+	qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_WRITE_CONTROL, &parm);
+	s->control = val;
+        break;
+    case PARA_REG_EPP_ADDR:
+	if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT)
+	    /* Controls not correct for EPP address cycle, so do nothing */
+	    pdebug("wa%02x s\n", val);
+	else {
+	    struct ParallelIOArg ioarg = { .buffer = &parm, .count = 1 };
+	    if (qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE_ADDR, &ioarg)) {
+		s->epp_timeout = 1;
+		pdebug("wa%02x t\n", val);
+	    }
+	    else
+		pdebug("wa%02x\n", val);
+	}
+	break;
+    case PARA_REG_EPP_DATA:
+	if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT)
+	    /* Controls not correct for EPP data cycle, so do nothing */
+	    pdebug("we%02x s\n", val);
+	else {
+	    struct ParallelIOArg ioarg = { .buffer = &parm, .count = 1 };
+	    if (qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg)) {
+		s->epp_timeout = 1;
+		pdebug("we%02x t\n", val);
+	    }
+	    else
+		pdebug("we%02x\n", val);
+	}
+	break;
+    }
+}
+
+static void
+parallel_ioport_eppdata_write_hw2(void *opaque, uint32_t addr, uint32_t val)
+{
+    ParallelState *s = opaque;
+    uint16_t eppdata = cpu_to_le16(val);
+    int err;
+    struct ParallelIOArg ioarg = {
+	.buffer = &eppdata, .count = sizeof(eppdata)
+    };
+    if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT) {
+	/* Controls not correct for EPP data cycle, so do nothing */
+	pdebug("we%04x s\n", val);
+	return;
+    }
+    err = qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg);
+    if (err) {
+	s->epp_timeout = 1;
+	pdebug("we%04x t\n", val);
+    }
+    else
+	pdebug("we%04x\n", val);
+}
+
+static void
+parallel_ioport_eppdata_write_hw4(void *opaque, uint32_t addr, uint32_t val)
+{
+    ParallelState *s = opaque;
+    uint32_t eppdata = cpu_to_le32(val);
+    int err;
+    struct ParallelIOArg ioarg = {
+	.buffer = &eppdata, .count = sizeof(eppdata)
+    };
+    if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT) {
+	/* Controls not correct for EPP data cycle, so do nothing */
+	pdebug("we%08x s\n", val);
+	return;
+    }
+    err = qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg);
+    if (err) {
+	s->epp_timeout = 1;
+	pdebug("we%08x t\n", val);
+    }
+    else
+	pdebug("we%08x\n", val);
+}
+
+static uint32_t parallel_ioport_read_sw(void *opaque, uint32_t addr)
+{
+    ParallelState *s = opaque;
     uint32_t ret = 0xff;
 
     addr &= 7;
     switch(addr) {
-    case 0:
-        if (s->hw_driver) {
-            qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_DATA, &s->data);
-        } 
-        ret = s->data; 
+    case PARA_REG_DATA:
+	if (s->control & PARA_CTR_DIR)
+	    ret = s->datar;
+	else
+	    ret = s->dataw;
         break;
-    case 1:
-        if (s->hw_driver) {
-            qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_STATUS, &s->status);
-            ret = s->status; 
-        } else {
-            ret = s->status;
-            s->irq_pending = 0;
-            if ((s->status & PARA_STS_BUSY) == 0 && (s->control & PARA_CTR_STROBE) == 0) {
-                /* XXX Fixme: wait 5 microseconds */
-                if (s->status & PARA_STS_ACK)
-                    s->status &= ~PARA_STS_ACK;
-                else {
-                    /* XXX Fixme: wait 5 microseconds */
-                    s->status |= PARA_STS_ACK;
-                    s->status |= PARA_STS_BUSY;
-                }
-            }
-            parallel_update_irq(s);
-        }
+    case PARA_REG_STS:
+	ret = s->status;
+	s->irq_pending = 0;
+	if ((s->status & PARA_STS_BUSY) == 0 && (s->control & PARA_CTR_STROBE) == 0) {
+	    /* XXX Fixme: wait 5 microseconds */
+	    if (s->status & PARA_STS_ACK)
+		s->status &= ~PARA_STS_ACK;
+	    else {
+		/* XXX Fixme: wait 5 microseconds */
+		s->status |= PARA_STS_ACK;
+		s->status |= PARA_STS_BUSY;
+	    }
+	}
+	parallel_update_irq(s);
         break;
-    case 2:
-        if (s->hw_driver) {
-            qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_CONTROL, &s->control);
-        }
+    case PARA_REG_CTR:
         ret = s->control;
         break;
     }
-#ifdef DEBUG_PARALLEL
-    printf("parallel: read addr=0x%02x val=0x%02x\n", addr, ret);
-#endif
+    pdebug("read addr=0x%02x val=0x%02x\n", addr, ret);
     return ret;
 }
 
+static uint32_t parallel_ioport_read_hw(void *opaque, uint32_t addr)
+{
+    ParallelState *s = opaque;
+    uint8_t ret = 0xff;
+    addr &= 7;
+    switch(addr) {
+    case PARA_REG_DATA:
+	qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_DATA, &ret);
+	if (s->last_read_offset != addr || s->datar != ret)
+	    pdebug("rd%02x\n", ret);
+        s->datar = ret;
+        break;
+    case PARA_REG_STS:
+	qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_STATUS, &ret);
+	ret &= ~PARA_STS_TMOUT;
+	if (s->epp_timeout)
+	    ret |= PARA_STS_TMOUT;
+	if (s->last_read_offset != addr || s->status != ret)
+	    pdebug("rs%02x\n", ret);
+	s->status = ret;
+        break;
+    case PARA_REG_CTR:
+        /* s->control has some bits fixed to 1. It is zero only when
+	   it has not been yet written to.  */
+	if (s->control == 0) {
+	    qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_CONTROL, &ret);
+	    if (s->last_read_offset != addr)
+		pdebug("rc%02x\n", ret);
+	    s->control = ret;
+	}
+	else {
+	    ret = s->control;
+	    if (s->last_read_offset != addr)
+		pdebug("rc%02x\n", ret);
+	}
+        break;
+    case PARA_REG_EPP_ADDR:
+	if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT))
+	    /* Controls not correct for EPP addr cycle, so do nothing */
+	    pdebug("ra%02x s\n", ret);
+	else {
+	    struct ParallelIOArg ioarg = { .buffer = &ret, .count = 1 };
+	    if (qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ_ADDR, &ioarg)) {
+		s->epp_timeout = 1;
+		pdebug("ra%02x t\n", ret);
+	    }
+	    else
+		pdebug("ra%02x\n", ret);
+	}
+	break;
+    case PARA_REG_EPP_DATA:
+	if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT))
+	    /* Controls not correct for EPP data cycle, so do nothing */
+	    pdebug("re%02x s\n", ret);
+	else {
+	    struct ParallelIOArg ioarg = { .buffer = &ret, .count = 1 };
+	    if (qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg)) {
+		s->epp_timeout = 1;
+		pdebug("re%02x t\n", ret);
+	    }
+	    else
+		pdebug("re%02x\n", ret);
+	}
+	break;
+    }
+    s->last_read_offset = addr;
+    return ret;
+}
+
+static uint32_t
+parallel_ioport_eppdata_read_hw2(void *opaque, uint32_t addr)
+{
+    ParallelState *s = opaque;
+    uint32_t ret;
+    uint16_t eppdata = ~0;
+    int err;
+    struct ParallelIOArg ioarg = {
+	.buffer = &eppdata, .count = sizeof(eppdata)
+    };
+    if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT)) {
+	/* Controls not correct for EPP data cycle, so do nothing */
+	pdebug("re%04x s\n", eppdata);
+	return eppdata;
+    }
+    err = qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg);
+    ret = le16_to_cpu(eppdata);
+
+    if (err) {
+	s->epp_timeout = 1;
+	pdebug("re%04x t\n", ret);
+    }
+    else
+	pdebug("re%04x\n", ret);
+    return ret;
+}
+
+static uint32_t
+parallel_ioport_eppdata_read_hw4(void *opaque, uint32_t addr)
+{
+    ParallelState *s = opaque;
+    uint32_t ret;
+    uint32_t eppdata = ~0U;
+    int err;
+    struct ParallelIOArg ioarg = {
+	.buffer = &eppdata, .count = sizeof(eppdata)
+    };
+    if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT)) {
+	/* Controls not correct for EPP data cycle, so do nothing */
+	pdebug("re%08x s\n", eppdata);
+	return eppdata;
+    }
+    err = qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg);
+    ret = le32_to_cpu(eppdata);
+
+    if (err) {
+	s->epp_timeout = 1;
+	pdebug("re%08x t\n", ret);
+    }
+    else
+	pdebug("re%08x\n", ret);
+    return ret;
+}
+
+static void parallel_ioport_ecp_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    addr &= 7;
+    pdebug("wecp%d=%02x\n", addr, val);
+}
+
+static uint32_t parallel_ioport_ecp_read(void *opaque, uint32_t addr)
+{
+    uint8_t ret = 0xff;
+    addr &= 7;
+    pdebug("recp%d:%02x\n", addr, ret);
+    return ret;
+}
+
 /* If fd is zero, it means that the parallel device uses the console */
-ParallelState *parallel_init(int base, int irq, CharDriverState *chr)
+ParallelState *parallel_init(int base, qemu_irq irq, CharDriverState *chr)
 {
     ParallelState *s;
     uint8_t dummy;
@@ -163,21 +409,39 @@
     s = qemu_mallocz(sizeof(ParallelState));
     if (!s)
         return NULL;
-    s->chr = chr;
-    s->hw_driver = 0;
-    if (qemu_chr_ioctl(chr, CHR_IOCTL_PP_READ_STATUS, &dummy) == 0)
-        s->hw_driver = 1;
-
-    s->irq = irq;
-    s->data = 0;
+    s->datar = ~0;
+    s->dataw = ~0;
     s->status = PARA_STS_BUSY;
     s->status |= PARA_STS_ACK;
     s->status |= PARA_STS_ONLINE;
     s->status |= PARA_STS_ERROR;
     s->control = PARA_CTR_SELECT;
     s->control |= PARA_CTR_INIT;
+    s->irq = irq;
+    s->irq_pending = 0;
+    s->chr = chr;
+    s->hw_driver = 0;
+    s->epp_timeout = 0;
+    s->last_read_offset = ~0U;
 
-    register_ioport_write(base, 8, 1, parallel_ioport_write, s);
-    register_ioport_read(base, 8, 1, parallel_ioport_read, s);
+    if (qemu_chr_ioctl(chr, CHR_IOCTL_PP_READ_STATUS, &dummy) == 0) {
+        s->hw_driver = 1;
+	s->status = dummy;
+    }
+
+    if (s->hw_driver) {
+	register_ioport_write(base, 8, 1, parallel_ioport_write_hw, s);
+	register_ioport_read(base, 8, 1, parallel_ioport_read_hw, s);
+	register_ioport_write(base+4, 1, 2, parallel_ioport_eppdata_write_hw2, s);
+	register_ioport_read(base+4, 1, 2, parallel_ioport_eppdata_read_hw2, s);
+	register_ioport_write(base+4, 1, 4, parallel_ioport_eppdata_write_hw4, s);
+	register_ioport_read(base+4, 1, 4, parallel_ioport_eppdata_read_hw4, s);
+	register_ioport_write(base+0x400, 8, 1, parallel_ioport_ecp_write, s);
+	register_ioport_read(base+0x400, 8, 1, parallel_ioport_ecp_read, s);
+    }
+    else {
+	register_ioport_write(base, 8, 1, parallel_ioport_write_sw, s);
+	register_ioport_read(base, 8, 1, parallel_ioport_read_sw, s);
+    }
     return s;
 }

Modified: trunk/src/host/qemu-neo1973/hw/pc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pc.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pc.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -32,9 +32,11 @@
 #define LINUX_BOOT_FILENAME "linux_boot.bin"
 
 #define KERNEL_LOAD_ADDR     0x00100000
-#define INITRD_LOAD_ADDR     0x00600000
+#define MAX_INITRD_LOAD_ADDR 0x38000000
 #define KERNEL_PARAMS_ADDR   0x00090000
 #define KERNEL_CMDLINE_ADDR  0x00099000
+/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables.  */
+#define ACPI_DATA_SIZE       0x10000
 
 static fdctrl_t *floppy_controller;
 static RTCState *rtc_state;
@@ -47,15 +49,16 @@
 }
 
 /* MSDOS compatibility mode FPU exception support */
+static qemu_irq ferr_irq;
 /* XXX: add IGNNE support */
 void cpu_set_ferr(CPUX86State *s)
 {
-    pic_set_irq(13, 1);
+    qemu_irq_raise(ferr_irq);
 }
 
 static void ioportF0_write(void *opaque, uint32_t addr, uint32_t data)
 {
-    pic_set_irq(13, 0);
+    qemu_irq_lower(ferr_irq);
 }
 
 /* TSC handling */
@@ -99,7 +102,7 @@
     return intno;
 }
 
-static void pic_irq_request(void *opaque, int level)
+static void pic_irq_request(void *opaque, int irq, int level)
 {
     CPUState *env = opaque;
     if (level)
@@ -401,7 +404,7 @@
 static int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
 
 #ifdef HAS_AUDIO
-static void audio_init (PCIBus *pci_bus)
+static void audio_init (PCIBus *pci_bus, qemu_irq *pic)
 {
     struct soundhw *c;
     int audio_enabled = 0;
@@ -418,7 +421,7 @@
             for (c = soundhw; c->name; ++c) {
                 if (c->enabled) {
                     if (c->isa) {
-                        c->init.init_isa (s);
+                        c->init.init_isa (s, pic);
                     }
                     else {
                         if (pci_bus) {
@@ -432,13 +435,13 @@
 }
 #endif
 
-static void pc_init_ne2k_isa(NICInfo *nd)
+static void pc_init_ne2k_isa(NICInfo *nd, qemu_irq *pic)
 {
     static int nb_ne2k = 0;
 
     if (nb_ne2k == NE2000_NB_MAX)
         return;
-    isa_ne2000_init(ne2000_io[nb_ne2k], ne2000_irq[nb_ne2k], nd);
+    isa_ne2000_init(ne2000_io[nb_ne2k], pic[ne2000_irq[nb_ne2k]], nd);
     nb_ne2k++;
 }
 
@@ -451,12 +454,15 @@
 {
     char buf[1024];
     int ret, linux_boot, initrd_size, i;
-    unsigned long bios_offset, vga_bios_offset, option_rom_offset;
-    int bios_size, isa_bios_size;
+    ram_addr_t ram_addr, vga_ram_addr, bios_offset, vga_bios_offset;
+    ram_addr_t initrd_offset;
+    int bios_size, isa_bios_size, vga_bios_size;
     PCIBus *pci_bus;
     int piix3_devfn = -1;
     CPUState *env;
     NICInfo *nd;
+    qemu_irq *cpu_irq;
+    qemu_irq *i8259;
 
     linux_boot = (kernel_filename != NULL);
 
@@ -477,23 +483,24 @@
     }
 
     /* allocate RAM */
-    cpu_register_physical_memory(0, ram_size, 0);
+    ram_addr = qemu_ram_alloc(ram_size);
+    cpu_register_physical_memory(0, ram_size, ram_addr);
 
+    /* allocate VGA RAM */
+    vga_ram_addr = qemu_ram_alloc(vga_ram_size);
+
     /* BIOS load */
-    bios_offset = ram_size + vga_ram_size;
-    vga_bios_offset = bios_offset + 256 * 1024;
-
     snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
     bios_size = get_image_size(buf);
     if (bios_size <= 0 || 
-        (bios_size % 65536) != 0 ||
-        bios_size > (256 * 1024)) {
+        (bios_size % 65536) != 0) {
         goto bios_error;
     }
+    bios_offset = qemu_ram_alloc(bios_size);
     ret = load_image(buf, phys_ram_base + bios_offset);
     if (ret != bios_size) {
     bios_error:
-        fprintf(stderr, "qemu: could not load PC bios '%s'\n", buf);
+        fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", buf);
         exit(1);
     }
 
@@ -503,8 +510,18 @@
     } else {
         snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
     }
+    vga_bios_size = get_image_size(buf);
+    if (vga_bios_size <= 0 || vga_bios_size > 65536) 
+        goto vga_bios_error;
+    vga_bios_offset = qemu_ram_alloc(65536);
+
     ret = load_image(buf, phys_ram_base + vga_bios_offset);
-    
+    if (ret != vga_bios_size) {
+    vga_bios_error:
+        fprintf(stderr, "qemu: could not load VGA BIOS '%s'\n", buf);
+        exit(1);
+    }
+
     /* setup basic memory access */
     cpu_register_physical_memory(0xc0000, 0x10000, 
                                  vga_bios_offset | IO_MEM_ROM);
@@ -519,20 +536,32 @@
                                  isa_bios_size, 
                                  (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
 
-    option_rom_offset = 0;
-    for (i = 0; i < nb_option_roms; i++) {
-	int offset = bios_offset + bios_size + option_rom_offset;
-	int size;
+    {
+        ram_addr_t option_rom_offset;
+        int size, offset;
 
-	size = load_image(option_rom[i], phys_ram_base + offset);
-	if ((size + option_rom_offset) > 0x10000) {
-	    fprintf(stderr, "Too many option ROMS\n");
-	    exit(1);
-	}
-	cpu_register_physical_memory(0xd0000 + option_rom_offset,
-				     size, offset | IO_MEM_ROM);
-	option_rom_offset += size + 2047;
-	option_rom_offset -= (option_rom_offset % 2048);
+        offset = 0;
+        for (i = 0; i < nb_option_roms; i++) {
+            size = get_image_size(option_rom[i]);
+            if (size < 0) {
+                fprintf(stderr, "Could not load option rom '%s'\n", 
+                        option_rom[i]);
+                exit(1);
+            }
+            if (size > (0x10000 - offset))
+                goto option_rom_error;
+            option_rom_offset = qemu_ram_alloc(size);
+            ret = load_image(option_rom[i], phys_ram_base + option_rom_offset);
+            if (ret != size) {
+            option_rom_error:
+                fprintf(stderr, "Too many option ROMS\n");
+                exit(1);
+            }
+            size = (size + 4095) & ~4095;
+            cpu_register_physical_memory(0xd0000 + offset,
+                                         size, option_rom_offset | IO_MEM_ROM);
+            offset += size;
+        }
     }
 
     /* map all the bios at the top of memory */
@@ -576,8 +605,28 @@
         
         /* load initrd */
         initrd_size = 0;
+        initrd_offset = 0;
         if (initrd_filename) {
-            initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR);
+            initrd_size = get_image_size (initrd_filename);
+            if (initrd_size > 0) {
+                initrd_offset = (ram_size - initrd_size) & TARGET_PAGE_MASK;
+                /* Leave space for BIOS ACPI tables.  */
+                initrd_offset -= ACPI_DATA_SIZE;
+                /* Avoid the last 64k to avoid 2.2.x kernel bugs.  */
+                initrd_offset -= 0x10000;
+                if (initrd_offset > MAX_INITRD_LOAD_ADDR)
+                    initrd_offset = MAX_INITRD_LOAD_ADDR;
+
+                if (initrd_size > ram_size
+                    || initrd_offset < KERNEL_LOAD_ADDR + ret) {
+                    fprintf(stderr,
+                            "qemu: memory too small for initial ram disk '%s'\n",
+                            initrd_filename);
+                    exit(1);
+                }
+                initrd_size = load_image(initrd_filename,
+                                         phys_ram_base + initrd_offset);
+            }
             if (initrd_size < 0) {
                 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 
                         initrd_filename);
@@ -585,7 +634,7 @@
             }
         }
         if (initrd_size > 0) {
-            stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x218, INITRD_LOAD_ADDR);
+            stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x218, initrd_offset);
             stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x21c, initrd_size);
         }
         pstrcpy(phys_ram_base + KERNEL_CMDLINE_ADDR, 4096,
@@ -597,9 +646,13 @@
         stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x210, 0x01);
     }
 
+    cpu_irq = qemu_allocate_irqs(pic_irq_request, first_cpu, 1);
+    i8259 = i8259_init(cpu_irq[0]);
+    ferr_irq = i8259[13];
+
     if (pci_enabled) {
-        pci_bus = i440fx_init(&i440fx_state);
-        piix3_devfn = piix3_init(pci_bus);
+        pci_bus = i440fx_init(&i440fx_state, i8259);
+        piix3_devfn = piix3_init(pci_bus, -1);
     } else {
         pci_bus = NULL;
     }
@@ -612,23 +665,29 @@
     if (cirrus_vga_enabled) {
         if (pci_enabled) {
             pci_cirrus_vga_init(pci_bus, 
-                                ds, phys_ram_base + ram_size, ram_size, 
-                                vga_ram_size);
+                                ds, phys_ram_base + vga_ram_addr, 
+                                vga_ram_addr, vga_ram_size);
         } else {
-            isa_cirrus_vga_init(ds, phys_ram_base + ram_size, ram_size, 
-                                vga_ram_size);
+            isa_cirrus_vga_init(ds, phys_ram_base + vga_ram_addr, 
+                                vga_ram_addr, vga_ram_size);
         }
+    } else if (vmsvga_enabled) {
+        if (pci_enabled)
+            pci_vmsvga_init(pci_bus, ds, phys_ram_base + ram_size,
+                            ram_size, vga_ram_size);
+        else
+            fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
     } else {
         if (pci_enabled) {
-            pci_vga_init(pci_bus, ds, phys_ram_base + ram_size, ram_size, 
-                         vga_ram_size, 0, 0);
+            pci_vga_init(pci_bus, ds, phys_ram_base + vga_ram_addr, 
+                         vga_ram_addr, vga_ram_size, 0, 0);
         } else {
-            isa_vga_init(ds, phys_ram_base + ram_size, ram_size, 
-                         vga_ram_size);
+            isa_vga_init(ds, phys_ram_base + vga_ram_addr, 
+                         vga_ram_addr, vga_ram_size);
         }
     }
 
-    rtc_state = rtc_init(0x70, 8);
+    rtc_state = rtc_init(0x70, i8259[8]);
 
     register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
     register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
@@ -636,8 +695,7 @@
     if (pci_enabled) {
         ioapic = ioapic_init();
     }
-    isa_pic = pic_init(pic_irq_request, first_cpu);
-    pit = pit_init(0x40, 0);
+    pit = pit_init(0x40, i8259[0]);
     pcspk_init(pit);
     if (pci_enabled) {
         pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic);
@@ -645,14 +703,14 @@
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
-            serial_init(&pic_set_irq_new, isa_pic,
-                        serial_io[i], serial_irq[i], serial_hds[i]);
+            serial_init(serial_io[i], i8259[serial_irq[i]], serial_hds[i]);
         }
     }
 
     for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
         if (parallel_hds[i]) {
-            parallel_init(parallel_io[i], parallel_irq[i], parallel_hds[i]);
+            parallel_init(parallel_io[i], i8259[parallel_irq[i]],
+                          parallel_hds[i]);
         }
     }
 
@@ -666,11 +724,9 @@
             }
         }
         if (strcmp(nd->model, "ne2k_isa") == 0) {
-            pc_init_ne2k_isa(nd);
-        } else if (strcmp(nd->model, "usb") == 0) {
-            /* ignore */
+            pc_init_ne2k_isa(nd, i8259);
         } else if (pci_enabled) {
-            pci_nic_init(pci_bus, nd);
+            pci_nic_init(pci_bus, nd, -1);
         } else {
             fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
             exit(1);
@@ -678,21 +734,21 @@
     }
 
     if (pci_enabled) {
-        pci_piix3_ide_init(pci_bus, bs_table, piix3_devfn + 1);
+        pci_piix3_ide_init(pci_bus, bs_table, piix3_devfn + 1, i8259);
     } else {
         for(i = 0; i < 2; i++) {
-            isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
+            isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
                          bs_table[2 * i], bs_table[2 * i + 1]);
         }
     }
 
-    kbd_init();
+    i8042_init(i8259[1], i8259[12], 0x60);
     DMA_init(0);
 #ifdef HAS_AUDIO
-    audio_init(pci_enabled ? pci_bus : NULL);
+    audio_init(pci_enabled ? pci_bus : NULL, i8259);
 #endif
 
-    floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table);
+    floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd_table);
 
     cmos_init(ram_size, boot_device, bs_table);
 
@@ -701,7 +757,13 @@
     }
 
     if (pci_enabled && acpi_enabled) {
-        piix4_pm_init(pci_bus, piix3_devfn + 3);
+        uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
+        i2c_bus *smbus;
+
+        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3);
+        for (i = 0; i < 8; i++) {
+            smbus_eeprom_device_init(smbus, 0x50 + i, eeprom_buf + (i * 256));
+        }
     }
     
     if (i440fx_state) {
@@ -731,7 +793,8 @@
                         int snapshot, 
                         const char *kernel_filename, 
                         const char *kernel_cmdline,
-                        const char *initrd_filename)
+                        const char *initrd_filename,
+                        const char *cpu_model)
 {
     pc_init1(ram_size, vga_ram_size, boot_device,
              ds, fd_filename, snapshot,
@@ -744,7 +807,8 @@
                         int snapshot, 
                         const char *kernel_filename, 
                         const char *kernel_cmdline,
-                        const char *initrd_filename)
+                        const char *initrd_filename,
+                        const char *cpu_model)
 {
     pc_init1(ram_size, vga_ram_size, boot_device,
              ds, fd_filename, snapshot,

Modified: trunk/src/host/qemu-neo1973/hw/pcf5060x.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pcf5060x.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pcf5060x.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -12,10 +12,8 @@
 #define VERBOSE 1
 
 struct pcf_s {
-    int i2c_dir;
-    struct i2c_slave_s i2c;
-    void *pic;
-    int irq;
+    i2c_slave i2c;
+    qemu_irq irq;
 
     int firstbyte;
     int charging;
@@ -59,17 +57,14 @@
         uint8_t alm_mon;
         uint8_t alm_year;
     } rtc;
-    struct {
-        gpio_handler_t fn;
-        void *opaque;
-    } gpo_handler[6];
+    qemu_irq gpo_handler[6];
     uint8_t gpo;
     QEMUTimer *onkeylow;
 };
 
-void pcf_reset(struct i2c_slave_s *i2c)
+void pcf_reset(i2c_slave *i2c)
 {
-    struct pcf_s *s = (struct pcf_s *) i2c->opaque;
+    struct pcf_s *s = (struct pcf_s *) i2c;
     time_t ti;
     s->charging = 1;
     s->reg = 0x00;
@@ -132,7 +127,7 @@
 
 static inline void pcf_update(struct pcf_s *s)
 {
-    pic_set_irq_new(s->pic, s->irq,
+    qemu_set_irq(s->irq,
                     (s->intr[0] & ~s->intm[0]) ||
                     (s->intr[1] & ~s->intm[1]) ||
                     (s->intr[2] & ~s->intm[2]));
@@ -267,8 +262,8 @@
 static void pcf_gpo_set(struct pcf_s *s, int line, int state, int inv)
 {
     state = (!!state) ^ inv;
-    if (s->gpo_handler[line].fn && ((s->gpo & 1) ^ state))
-        s->gpo_handler[line].fn(line, state, s->gpo_handler[line].opaque);
+    if (s->gpo_handler[line] && ((s->gpo & 1) ^ state))
+        qemu_set_irq(s->gpo_handler[line], state);
     s->gpo &= ~(1 << line);
     s->gpo |= state << line;
 }
@@ -755,33 +750,33 @@
     }
 }
 
-static void pcf_start(void *opaque, int dir)
+static void pcf_event(i2c_slave *i2c, enum i2c_event event)
 {
-    struct pcf_s *s = (struct pcf_s *) opaque;
-    s->i2c_dir = dir;
-    s->firstbyte = 1;
+    struct pcf_s *s = (struct pcf_s *) i2c;
+
+    if (event == I2C_START_SEND)
+        s->firstbyte = 1;
 }
 
-static int pcf_tx(void *opaque, uint8_t *data, int len)
+static int pcf_tx(i2c_slave *i2c, uint8_t data)
 {
-    struct pcf_s *s = (struct pcf_s *) opaque;
+    struct pcf_s *s = (struct pcf_s *) i2c;
     /* Interpret register address byte */
-    if (s->firstbyte && len && !s->i2c_dir) {
-        s->reg = *(data ++);
-        len --;
+    if (s->firstbyte) {
+        s->reg = data;
         s->firstbyte = 0;
-    }
+    } else
+        pcf_write(s, s->reg ++, data);
 
-    while (len --) {
-        if (s->i2c_dir)
-            *(data ++) = pcf_read(opaque, s->reg ++);
-        else
-            pcf_write(opaque, s->reg ++, *(data ++));
-    }
-
     return 0;
 }
 
+static int pcf_rx(i2c_slave *i2c)
+{
+    struct pcf_s *s = (struct pcf_s *) i2c;
+    return pcf_read(s, s->reg ++);
+}
+
 static void pcf_onkey1s(void *opaque)
 {
     struct pcf_s *s = (struct pcf_s *) opaque;
@@ -790,14 +785,14 @@
     pcf_update(s);
 }
 
-struct i2c_slave_s *pcf5060x_init(void *pic, int irq, int tsc)
+i2c_slave *pcf5060x_init(i2c_bus *bus, qemu_irq irq, int tsc)
 {
-    struct pcf_s *s = qemu_mallocz(sizeof(struct pcf_s));
-    s->i2c.opaque = s;
-    s->i2c.tx = pcf_tx;
-    s->i2c.start = pcf_start;
+    struct pcf_s *s = (struct pcf_s *)
+            i2c_slave_init(bus, 0, sizeof(struct pcf_s));
+    s->i2c.event = pcf_event;
+    s->i2c.recv = pcf_rx;
+    s->i2c.send = pcf_tx;
 
-    s->pic = pic;
     s->irq = irq;
     s->rtc.hz = qemu_new_timer(rt_clock, pcf_rtc_hz, s);
     s->onkeylow = qemu_new_timer(vm_clock, pcf_onkey1s, s);
@@ -815,19 +810,17 @@
     return &s->i2c;
 }
 
-void pcf_gpo_handler_set(struct i2c_slave_s *i2c, int line,
-                gpio_handler_t handler, void *opaque)
+void pcf_gpo_handler_set(i2c_slave *i2c, int line, qemu_irq handler)
 {
-    struct pcf_s *s = (struct pcf_s *) i2c->opaque;
+    struct pcf_s *s = (struct pcf_s *) i2c;
     if (line >= 6 || line < 0)
         cpu_abort(cpu_single_env, "%s: No GPO line %i\n", __FUNCTION__, line);
-    s->gpo_handler[line].fn = handler;
-    s->gpo_handler[line].opaque = opaque;
+    s->gpo_handler[line] = handler;
 }
 
-void pcf_onkey_set(struct i2c_slave_s *i2c, int level)
+void pcf_onkey_set(i2c_slave *i2c, int level)
 {
-    struct pcf_s *s = (struct pcf_s *) i2c->opaque;
+    struct pcf_s *s = (struct pcf_s *) i2c;
     if (level) {
         s->oocs |= 1 << 0;		/* set ONKEY */
         s->intr[0] |= 1 << 0;		/* set ONKEYR */
@@ -840,9 +833,9 @@
     pcf_update(s);
 }
 
-void pcf_exton_set(struct i2c_slave_s *i2c, int level)
+void pcf_exton_set(i2c_slave *i2c, int level)
 {
-    struct pcf_s *s = (struct pcf_s *) i2c->opaque;
+    struct pcf_s *s = (struct pcf_s *) i2c;
     if (level) {
         s->oocs |= 1 << 1;		/* set EXTON */
         s->intr[0] |= 1 << 3;		/* set EXTONR */

Modified: trunk/src/host/qemu-neo1973/hw/pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pci.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pci.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -33,7 +33,7 @@
     uint32_t config_reg; /* XXX: suppress */
     /* low level pic */
     SetIRQFunc *low_set_irq;
-    void *irq_opaque;
+    qemu_irq *irq_opaque;
     PCIDevice *devices[256];
     PCIDevice *parent_dev;
     PCIBus *next;
@@ -43,13 +43,14 @@
 };
 
 static void pci_update_mappings(PCIDevice *d);
+static void pci_set_irq(void *opaque, int irq_num, int level);
 
 target_phys_addr_t pci_mem_base;
 static int pci_irq_index;
 static PCIBus *first_bus;
 
 PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
-                         void *pic, int devfn_min, int nirq)
+                         qemu_irq *pic, int devfn_min, int nirq)
 {
     PCIBus *bus;
     bus = qemu_mallocz(sizeof(PCIBus) + (nirq * sizeof(int)));
@@ -129,6 +130,7 @@
     pci_dev->config_write = config_write;
     pci_dev->irq_index = pci_irq_index++;
     bus->devices[devfn] = pci_dev;
+    pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, 4);
     return pci_dev;
 }
 
@@ -433,8 +435,9 @@
 /* generic PCI irq support */
 
 /* 0 <= irq_num <= 3. level must be 0 or 1 */
-void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level)
+static void pci_set_irq(void *opaque, int irq_num, int level)
 {
+    PCIDevice *pci_dev = (PCIDevice *)opaque;
     PCIBus *bus;
     int change;
     
@@ -466,11 +469,38 @@
 {
     { 0x0100, "SCSI controller"},
     { 0x0101, "IDE controller"},
+    { 0x0102, "Floppy controller"},
+    { 0x0103, "IPI controller"},
+    { 0x0104, "RAID controller"},
+    { 0x0106, "SATA controller"},
+    { 0x0107, "SAS controller"},
+    { 0x0180, "Storage controller"},
     { 0x0200, "Ethernet controller"},
+    { 0x0201, "Token Ring controller"},
+    { 0x0202, "FDDI controller"},
+    { 0x0203, "ATM controller"},
+    { 0x0280, "Network controller"},
     { 0x0300, "VGA controller"},
+    { 0x0301, "XGA controller"},
+    { 0x0302, "3D controller"},
+    { 0x0380, "Display controller"},
+    { 0x0400, "Video controller"},
+    { 0x0401, "Audio controller"},
+    { 0x0402, "Phone"},
+    { 0x0480, "Multimedia controller"},
+    { 0x0500, "RAM controller"},
+    { 0x0501, "Flash controller"},
+    { 0x0580, "Memory controller"},
     { 0x0600, "Host bridge"},
     { 0x0601, "ISA bridge"},
+    { 0x0602, "EISA bridge"},
+    { 0x0603, "MC bridge"},
     { 0x0604, "PCI bridge"},
+    { 0x0605, "PCMCIA bridge"},
+    { 0x0606, "NUBUS bridge"},
+    { 0x0607, "CARDBUS bridge"},
+    { 0x0608, "RACEWAY bridge"},
+    { 0x0680, "Bridge"},
     { 0x0c03, "USB controller"},
     { 0, NULL}
 };
@@ -544,14 +574,20 @@
 }
 
 /* Initialize a PCI NIC.  */
-void pci_nic_init(PCIBus *bus, NICInfo *nd)
+void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
     if (strcmp(nd->model, "ne2k_pci") == 0) {
-        pci_ne2000_init(bus, nd);
+        pci_ne2000_init(bus, nd, devfn);
+    } else if (strcmp(nd->model, "i82551") == 0) {
+        pci_i82551_init(bus, nd, devfn);
+    } else if (strcmp(nd->model, "i82557b") == 0) {
+        pci_i82557b_init(bus, nd, devfn);
+    } else if (strcmp(nd->model, "i82559er") == 0) {
+        pci_i82559er_init(bus, nd, devfn);
     } else if (strcmp(nd->model, "rtl8139") == 0) {
-        pci_rtl8139_init(bus, nd);
+        pci_rtl8139_init(bus, nd, devfn);
     } else if (strcmp(nd->model, "pcnet") == 0) {
-        pci_pcnet_init(bus, nd);
+        pci_pcnet_init(bus, nd, devfn);
     } else {
         fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
         exit (1);
@@ -587,7 +623,7 @@
     s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge), 
                                          devfn, NULL, pci_bridge_write_config);
     s->dev.config[0x00] = id >> 16;
-    s->dev.config[0x01] = id > 24;
+    s->dev.config[0x01] = id >> 24;
     s->dev.config[0x02] = id; // device_id
     s->dev.config[0x03] = id >> 8;
     s->dev.config[0x04] = 0x06; // command = bus master, pci mem

Modified: trunk/src/host/qemu-neo1973/hw/pckbd.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pckbd.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pckbd.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -121,6 +121,11 @@
     uint8_t pending;
     void *kbd;
     void *mouse;
+
+    qemu_irq irq_kbd;
+    qemu_irq irq_mouse;
+    target_phys_addr_t base;
+    int it_shift;
 } KBDState;
 
 KBDState kbd_state;
@@ -130,26 +135,26 @@
    incorrect, but it avoids having to simulate exact delays */
 static void kbd_update_irq(KBDState *s)
 {
-    int irq12_level, irq1_level;
+    int irq_kbd_level, irq_mouse_level;
 
-    irq1_level = 0;    
-    irq12_level = 0;    
+    irq_kbd_level = 0;
+    irq_mouse_level = 0;
     s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);
     if (s->pending) {
         s->status |= KBD_STAT_OBF;
-        /* kdb data takes priority over aux data.  */
+        /* kbd data takes priority over aux data.  */
         if (s->pending == KBD_PENDING_AUX) {
             s->status |= KBD_STAT_MOUSE_OBF;
             if (s->mode & KBD_MODE_MOUSE_INT)
-                irq12_level = 1;
+                irq_mouse_level = 1;
         } else {
             if ((s->mode & KBD_MODE_KBD_INT) && 
                 !(s->mode & KBD_MODE_DISABLE_KBD))
-                irq1_level = 1;
+                irq_kbd_level = 1;
         }
     }
-    pic_set_irq(1, irq1_level);
-    pic_set_irq(12, irq12_level);
+    qemu_set_irq(s->irq_kbd, irq_kbd_level);
+    qemu_set_irq(s->irq_mouse, irq_mouse_level);
 }
 
 static void kbd_update_kbd_irq(void *opaque, int level)
@@ -353,18 +358,89 @@
     return 0;
 }
 
-void kbd_init(void)
+void i8042_init(qemu_irq kbd_irq, qemu_irq mouse_irq, uint32_t io_base)
 {
     KBDState *s = &kbd_state;
-    
+
+    s->irq_kbd = kbd_irq;
+    s->irq_mouse = mouse_irq;
+
     kbd_reset(s);
     register_savevm("pckbd", 0, 3, kbd_save, kbd_load, s);
-    register_ioport_read(0x60, 1, 1, kbd_read_data, s);
-    register_ioport_write(0x60, 1, 1, kbd_write_data, s);
-    register_ioport_read(0x64, 1, 1, kbd_read_status, s);
-    register_ioport_write(0x64, 1, 1, kbd_write_command, s);
+    register_ioport_read(io_base, 1, 1, kbd_read_data, s);
+    register_ioport_write(io_base, 1, 1, kbd_write_data, s);
+    register_ioport_read(io_base + 4, 1, 1, kbd_read_status, s);
+    register_ioport_write(io_base + 4, 1, 1, kbd_write_command, s);
 
     s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s);
     s->mouse = ps2_mouse_init(kbd_update_aux_irq, s);
+#ifdef TARGET_I386
+    vmmouse_init(s->mouse);
+#endif
     qemu_register_reset(kbd_reset, s);
 }
+
+/* Memory mapped interface */
+uint32_t kbd_mm_readb (void *opaque, target_phys_addr_t addr)
+{
+    KBDState *s = opaque;
+
+    switch ((addr - s->base) >> s->it_shift) {
+    case 0:
+        return kbd_read_data(s, 0) & 0xff;
+    case 1:
+        return kbd_read_status(s, 0) & 0xff;
+    default:
+        return 0xff;
+    }
+}
+
+void kbd_mm_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    KBDState *s = opaque;
+
+    switch ((addr - s->base) >> s->it_shift) {
+    case 0:
+        kbd_write_data(s, 0, value & 0xff);
+        break;
+    case 1:
+        kbd_write_command(s, 0, value & 0xff);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc *kbd_mm_read[] = {
+    &kbd_mm_readb,
+    &kbd_mm_readb,
+    &kbd_mm_readb,
+};
+
+static CPUWriteMemoryFunc *kbd_mm_write[] = {
+    &kbd_mm_writeb,
+    &kbd_mm_writeb,
+    &kbd_mm_writeb,
+};
+
+void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, target_ulong base,
+                   int it_shift)
+{
+    KBDState *s = &kbd_state;
+    int s_io_memory;
+
+    s->irq_kbd = kbd_irq;
+    s->irq_mouse = mouse_irq;
+    s->base = base;
+    s->it_shift = it_shift;
+
+    kbd_reset(s);
+    register_savevm("pckbd", 0, 3, kbd_save, kbd_load, s);
+    s_io_memory = cpu_register_io_memory(0, kbd_mm_read, kbd_mm_write, s);
+    cpu_register_physical_memory(base, 8 << it_shift, s_io_memory);
+
+    s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s);
+    s->mouse = ps2_mouse_init(kbd_update_aux_irq, s);
+#ifdef TARGET_I386
+    vmmouse_init(s->mouse);
+#endif
+    qemu_register_reset(kbd_reset, s);
+}

Modified: trunk/src/host/qemu-neo1973/hw/pcnet.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pcnet.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pcnet.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -69,7 +69,7 @@
     int xmit_pos, recv_pos;
     uint8_t buffer[4096];
     int tx_busy;
-    void (*set_irq_cb)(void *s, int isr);
+    qemu_irq irq;
     void (*phys_mem_read)(void *dma_opaque, target_phys_addr_t addr,
                          uint8_t *buf, int len, int do_bswap);
     void (*phys_mem_write)(void *dma_opaque, target_phys_addr_t addr,
@@ -77,14 +77,6 @@
     void *dma_opaque;
 };
 
-/* XXX: using bitfields for target memory structures is almost surely
-   not portable, so it should be suppressed ASAP */
-#ifdef __GNUC__
-#define PACKED_FIELD(A) A __attribute__ ((packed))
-#else
-#error FixMe
-#endif
-
 struct qemu_ether_header {
     uint8_t ether_dhost[6];
     uint8_t ether_shost[6];
@@ -183,223 +175,291 @@
 };
 
 struct pcnet_TMD {
-    struct {
-        unsigned tbadr:32;
-    } tmd0;
-    struct {
-        unsigned PACKED_FIELD(bcnt:12), PACKED_FIELD(ones:4), PACKED_FIELD(res:7), PACKED_FIELD(bpe:1);
-        unsigned PACKED_FIELD(enp:1), PACKED_FIELD(stp:1), PACKED_FIELD(def:1), PACKED_FIELD(one:1);
-        unsigned PACKED_FIELD(ltint:1), PACKED_FIELD(nofcs:1), PACKED_FIELD(err:1), PACKED_FIELD(own:1);
-    } tmd1;
-    struct {
-        unsigned PACKED_FIELD(trc:4), PACKED_FIELD(res:12);
-        unsigned PACKED_FIELD(tdr:10), PACKED_FIELD(rtry:1), PACKED_FIELD(lcar:1);
-        unsigned PACKED_FIELD(lcol:1), PACKED_FIELD(exdef:1), PACKED_FIELD(uflo:1), PACKED_FIELD(buff:1);
-    } tmd2;
-    struct {
-        unsigned res:32;
-    } tmd3;    
+    uint32_t tbadr;
+    int16_t length;
+    int16_t status;
+    uint32_t misc;
+    uint32_t res;
 };
 
+#define TMDL_BCNT_MASK  0x0fff
+#define TMDL_BCNT_SH    0
+#define TMDL_ONES_MASK  0xf000
+#define TMDL_ONES_SH    12
+
+#define TMDS_BPE_MASK   0x0080
+#define TMDS_BPE_SH     7
+#define TMDS_ENP_MASK   0x0100
+#define TMDS_ENP_SH     8
+#define TMDS_STP_MASK   0x0200
+#define TMDS_STP_SH     9
+#define TMDS_DEF_MASK   0x0400
+#define TMDS_DEF_SH     10
+#define TMDS_ONE_MASK   0x0800
+#define TMDS_ONE_SH     11
+#define TMDS_LTINT_MASK 0x1000
+#define TMDS_LTINT_SH   12
+#define TMDS_NOFCS_MASK 0x2000
+#define TMDS_NOFCS_SH   13
+#define TMDS_ERR_MASK   0x4000
+#define TMDS_ERR_SH     14
+#define TMDS_OWN_MASK   0x8000
+#define TMDS_OWN_SH     15
+
+#define TMDM_TRC_MASK   0x0000000f
+#define TMDM_TRC_SH     0
+#define TMDM_TDR_MASK   0x03ff0000
+#define TMDM_TDR_SH     16
+#define TMDM_RTRY_MASK  0x04000000
+#define TMDM_RTRY_SH    26
+#define TMDM_LCAR_MASK  0x08000000
+#define TMDM_LCAR_SH    27
+#define TMDM_LCOL_MASK  0x10000000
+#define TMDM_LCOL_SH    28
+#define TMDM_EXDEF_MASK 0x20000000
+#define TMDM_EXDEF_SH   29
+#define TMDM_UFLO_MASK  0x40000000
+#define TMDM_UFLO_SH    30
+#define TMDM_BUFF_MASK  0x80000000
+#define TMDM_BUFF_SH    31
+
 struct pcnet_RMD {
-    struct {
-        unsigned rbadr:32;
-    } rmd0;
-    struct {
-        unsigned PACKED_FIELD(bcnt:12), PACKED_FIELD(ones:4), PACKED_FIELD(res:4);
-        unsigned PACKED_FIELD(bam:1), PACKED_FIELD(lafm:1), PACKED_FIELD(pam:1), PACKED_FIELD(bpe:1);
-        unsigned PACKED_FIELD(enp:1), PACKED_FIELD(stp:1), PACKED_FIELD(buff:1), PACKED_FIELD(crc:1);
-        unsigned PACKED_FIELD(oflo:1), PACKED_FIELD(fram:1), PACKED_FIELD(err:1), PACKED_FIELD(own:1);
-    } rmd1;
-    struct {
-        unsigned PACKED_FIELD(mcnt:12), PACKED_FIELD(zeros:4);
-        unsigned PACKED_FIELD(rpc:8), PACKED_FIELD(rcc:8);
-    } rmd2;    
-    struct {
-        unsigned res:32;
-    } rmd3;    
+    uint32_t rbadr;
+    int16_t buf_length;
+    int16_t status;
+    uint32_t msg_length;
+    uint32_t res;
 };
 
+#define RMDL_BCNT_MASK  0x0fff
+#define RMDL_BCNT_SH    0
+#define RMDL_ONES_MASK  0xf000
+#define RMDL_ONES_SH    12
 
-#define PRINT_TMD(T) printf(    \
-        "TMD0 : TBADR=0x%08x\n" \
+#define RMDS_BAM_MASK   0x0010
+#define RMDS_BAM_SH     4
+#define RMDS_LFAM_MASK  0x0020
+#define RMDS_LFAM_SH    5
+#define RMDS_PAM_MASK   0x0040
+#define RMDS_PAM_SH     6
+#define RMDS_BPE_MASK   0x0080
+#define RMDS_BPE_SH     7
+#define RMDS_ENP_MASK   0x0100
+#define RMDS_ENP_SH     8
+#define RMDS_STP_MASK   0x0200
+#define RMDS_STP_SH     9
+#define RMDS_BUFF_MASK  0x0400
+#define RMDS_BUFF_SH    10
+#define RMDS_CRC_MASK   0x0800
+#define RMDS_CRC_SH     11
+#define RMDS_OFLO_MASK  0x1000
+#define RMDS_OFLO_SH    12
+#define RMDS_FRAM_MASK  0x2000
+#define RMDS_FRAM_SH    13
+#define RMDS_ERR_MASK   0x4000
+#define RMDS_ERR_SH     14
+#define RMDS_OWN_MASK   0x8000
+#define RMDS_OWN_SH     15
+
+#define RMDM_MCNT_MASK  0x00000fff
+#define RMDM_MCNT_SH    0
+#define RMDM_ZEROS_MASK 0x0000f000
+#define RMDM_ZEROS_SH   12
+#define RMDM_RPC_MASK   0x00ff0000
+#define RMDM_RPC_SH     16
+#define RMDM_RCC_MASK   0xff000000
+#define RMDM_RCC_SH     24
+
+#define SET_FIELD(regp, name, field, value)             \
+  (*(regp) = (*(regp) & ~(name ## _ ## field ## _MASK)) \
+             | ((value) << name ## _ ## field ## _SH))
+
+#define GET_FIELD(reg, name, field)                     \
+  (((reg) & name ## _ ## field ## _MASK) >> name ## _ ## field ## _SH)
+
+#define PRINT_TMD(T) printf(                            \
+        "TMD0 : TBADR=0x%08x\n"                         \
         "TMD1 : OWN=%d, ERR=%d, FCS=%d, LTI=%d, "       \
         "ONE=%d, DEF=%d, STP=%d, ENP=%d,\n"             \
         "       BPE=%d, BCNT=%d\n"                      \
         "TMD2 : BUF=%d, UFL=%d, EXD=%d, LCO=%d, "       \
         "LCA=%d, RTR=%d,\n"                             \
         "       TDR=%d, TRC=%d\n",                      \
-        (T)->tmd0.tbadr,                                \
-        (T)->tmd1.own, (T)->tmd1.err, (T)->tmd1.nofcs,  \
-        (T)->tmd1.ltint, (T)->tmd1.one, (T)->tmd1.def,  \
-        (T)->tmd1.stp, (T)->tmd1.enp, (T)->tmd1.bpe,    \
-        4096-(T)->tmd1.bcnt,                            \
-        (T)->tmd2.buff, (T)->tmd2.uflo, (T)->tmd2.exdef,\
-        (T)->tmd2.lcol, (T)->tmd2.lcar, (T)->tmd2.rtry, \
-        (T)->tmd2.tdr, (T)->tmd2.trc)
+        (T)->tbadr,                                     \
+        GET_FIELD((T)->status, TMDS, OWN),              \
+        GET_FIELD((T)->status, TMDS, ERR),              \
+        GET_FIELD((T)->status, TMDS, NOFCS),            \
+        GET_FIELD((T)->status, TMDS, LTINT),            \
+        GET_FIELD((T)->status, TMDS, ONE),              \
+        GET_FIELD((T)->status, TMDS, DEF),              \
+        GET_FIELD((T)->status, TMDS, STP),              \
+        GET_FIELD((T)->status, TMDS, ENP),              \
+        GET_FIELD((T)->status, TMDS, BPE),              \
+        4096-GET_FIELD((T)->length, TMDL, BCNT),        \
+        GET_FIELD((T)->misc, TMDM, BUFF),               \
+        GET_FIELD((T)->misc, TMDM, UFLO),               \
+        GET_FIELD((T)->misc, TMDM, EXDEF),              \
+        GET_FIELD((T)->misc, TMDM, LCOL),               \
+        GET_FIELD((T)->misc, TMDM, LCAR),               \
+        GET_FIELD((T)->misc, TMDM, RTRY),               \
+        GET_FIELD((T)->misc, TMDM, TDR),                \
+        GET_FIELD((T)->misc, TMDM, TRC))
 
-#define PRINT_RMD(R) printf(    \
-        "RMD0 : RBADR=0x%08x\n" \
+#define PRINT_RMD(R) printf(                            \
+        "RMD0 : RBADR=0x%08x\n"                         \
         "RMD1 : OWN=%d, ERR=%d, FRAM=%d, OFLO=%d, "     \
         "CRC=%d, BUFF=%d, STP=%d, ENP=%d,\n       "     \
-        "BPE=%d, PAM=%d, LAFM=%d, BAM=%d, ONES=%d, BCNT=%d\n"    \
+        "BPE=%d, PAM=%d, LAFM=%d, BAM=%d, ONES=%d, BCNT=%d\n" \
         "RMD2 : RCC=%d, RPC=%d, MCNT=%d, ZEROS=%d\n",   \
-        (R)->rmd0.rbadr,                                \
-        (R)->rmd1.own, (R)->rmd1.err, (R)->rmd1.fram,   \
-        (R)->rmd1.oflo, (R)->rmd1.crc, (R)->rmd1.buff,  \
-        (R)->rmd1.stp, (R)->rmd1.enp, (R)->rmd1.bpe,    \
-        (R)->rmd1.pam, (R)->rmd1.lafm, (R)->rmd1.bam,   \
-        (R)->rmd1.ones, 4096-(R)->rmd1.bcnt,            \
-        (R)->rmd2.rcc, (R)->rmd2.rpc, (R)->rmd2.mcnt,   \
-        (R)->rmd2.zeros)
+        (R)->rbadr,                                     \
+        GET_FIELD((R)->status, RMDS, OWN),              \
+        GET_FIELD((R)->status, RMDS, ERR),              \
+        GET_FIELD((R)->status, RMDS, FRAM),             \
+        GET_FIELD((R)->status, RMDS, OFLO),             \
+        GET_FIELD((R)->status, RMDS, CRC),              \
+        GET_FIELD((R)->status, RMDS, BUFF),             \
+        GET_FIELD((R)->status, RMDS, STP),              \
+        GET_FIELD((R)->status, RMDS, ENP),              \
+        GET_FIELD((R)->status, RMDS, BPE),              \
+        GET_FIELD((R)->status, RMDS, PAM),              \
+        GET_FIELD((R)->status, RMDS, LFAM),             \
+        GET_FIELD((R)->status, RMDS, BAM),              \
+        GET_FIELD((R)->buf_length, RMDL, ONES),         \
+        4096-GET_FIELD((R)->buf_length, RMDL, BCNT),    \
+        GET_FIELD((R)->msg_length, RMDM, RCC),          \
+        GET_FIELD((R)->msg_length, RMDM, RPC),          \
+        GET_FIELD((R)->msg_length, RMDM, MCNT),         \
+        GET_FIELD((R)->msg_length, RMDM, ZEROS))
 
-static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd1, 
+static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd,
                                   target_phys_addr_t addr)
 {
-    uint32_t *tmd = (uint32_t *)tmd1;
-
-    if (!BCR_SWSTYLE(s)) {
-        uint16_t xda[4];
-        s->phys_mem_read(s->dma_opaque, addr,
-                (void *)&xda[0], sizeof(xda), 0);
-        le16_to_cpus(&xda[0]);
-        le16_to_cpus(&xda[1]);
-        le16_to_cpus(&xda[2]);
-        le16_to_cpus(&xda[3]);
-        tmd[0] = (xda[0]&0xffff) |
-            ((xda[1]&0x00ff) << 16);
-        tmd[1] = (xda[2]&0xffff)|
-            ((xda[1] & 0xff00) << 16);
-        tmd[2] =
-            (xda[3] & 0xffff) << 16;
-        tmd[3] = 0;
+    if (!BCR_SSIZE32(s)) {
+        struct {
+            uint32_t tbadr;
+            int16_t length;
+            int16_t status;
+	} xda;
+        s->phys_mem_read(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
+        tmd->tbadr = le32_to_cpu(xda.tbadr) & 0xffffff;
+        tmd->length = le16_to_cpu(xda.length);
+        tmd->status = (le32_to_cpu(xda.tbadr) >> 16) & 0xff00;
+        tmd->misc = le16_to_cpu(xda.status) << 16;
+        tmd->res = 0;
     } else {
-        uint32_t xda[4];
-        s->phys_mem_read(s->dma_opaque, addr,
-                (void *)&xda[0], sizeof(xda), 0);
-        le32_to_cpus(&xda[0]);
-        le32_to_cpus(&xda[1]);
-        le32_to_cpus(&xda[2]);
-        le32_to_cpus(&xda[3]);
-        if (BCR_SWSTYLE(s) != 3) {
-            memcpy(tmd, xda, sizeof(xda));
-        } else {
-            tmd[0] = xda[2];
-            tmd[1] = xda[1];
-            tmd[2] = xda[0];
-            tmd[3] = xda[3];
+        s->phys_mem_read(s->dma_opaque, addr, (void *)tmd, sizeof(*tmd), 0);
+        le32_to_cpus(&tmd->tbadr);
+        le16_to_cpus(&tmd->length);
+        le16_to_cpus(&tmd->status);
+        le32_to_cpus(&tmd->misc);
+        le32_to_cpus(&tmd->res);
+        if (BCR_SWSTYLE(s) == 3) {
+            uint32_t tmp = tmd->tbadr;
+            tmd->tbadr = tmd->misc;
+            tmd->misc = tmp;
         }
     }
 }
 
-static inline void pcnet_tmd_store(PCNetState *s, const struct pcnet_TMD *tmd1,
+static inline void pcnet_tmd_store(PCNetState *s, const struct pcnet_TMD *tmd,
                                    target_phys_addr_t addr)
 {
-    const uint32_t *tmd = (const uint32_t *)tmd1;
-    if (!BCR_SWSTYLE(s)) {
-        uint16_t xda[4];
-        xda[0] = tmd[0] & 0xffff;
-        xda[1] = ((tmd[0]>>16)&0x00ff) |
-            ((tmd[1]>>16)&0xff00);
-        xda[2] = tmd[1] & 0xffff;
-        xda[3] = tmd[2] >> 16;
-        cpu_to_le16s(&xda[0]);
-        cpu_to_le16s(&xda[1]);
-        cpu_to_le16s(&xda[2]);
-        cpu_to_le16s(&xda[3]);
-        s->phys_mem_write(s->dma_opaque, addr,
-                (void *)&xda[0], sizeof(xda), 0);
+    if (!BCR_SSIZE32(s)) {
+        struct {
+            uint32_t tbadr;
+            int16_t length;
+            int16_t status;
+        } xda;
+        xda.tbadr = cpu_to_le32((tmd->tbadr & 0xffffff) |
+                                ((tmd->status & 0xff00) << 16));
+        xda.length = cpu_to_le16(tmd->length);
+        xda.status = cpu_to_le16(tmd->misc >> 16);
+        s->phys_mem_write(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
     } else {
-        uint32_t xda[4];
-        if (BCR_SWSTYLE(s) != 3) {
-            memcpy(xda, tmd, sizeof(xda));
-        } else {
-            xda[0] = tmd[2];
-            xda[1] = tmd[1];
-            xda[2] = tmd[0];
-            xda[3] = tmd[3];
+        struct {
+            uint32_t tbadr;
+            int16_t length;
+            int16_t status;
+            uint32_t misc;
+            uint32_t res;
+        } xda;
+        xda.tbadr = cpu_to_le32(tmd->tbadr);
+        xda.length = cpu_to_le16(tmd->length);
+        xda.status = cpu_to_le16(tmd->status);
+        xda.misc = cpu_to_le32(tmd->misc);
+        xda.res = cpu_to_le32(tmd->res);
+        if (BCR_SWSTYLE(s) == 3) {
+            uint32_t tmp = xda.tbadr;
+            xda.tbadr = xda.misc;
+            xda.misc = tmp;
         }
-        cpu_to_le32s(&xda[0]);
-        cpu_to_le32s(&xda[1]);
-        cpu_to_le32s(&xda[2]);
-        cpu_to_le32s(&xda[3]);
-        s->phys_mem_write(s->dma_opaque, addr,
-                          (void *)&xda[0], sizeof(xda), 0);
+        s->phys_mem_write(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
     }
 }
 
-static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd1,
+static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd,
                                   target_phys_addr_t addr)
 {
-    uint32_t *rmd = (uint32_t *)rmd1;
-
-    if (!BCR_SWSTYLE(s)) {
-        uint16_t rda[4];
-        s->phys_mem_read(s->dma_opaque, addr, 
-                         (void *)&rda[0], sizeof(rda), 0);
-        le16_to_cpus(&rda[0]);
-        le16_to_cpus(&rda[1]);
-        le16_to_cpus(&rda[2]);
-        le16_to_cpus(&rda[3]);
-        rmd[0] = (rda[0]&0xffff)|
-            ((rda[1] & 0x00ff) << 16);
-        rmd[1] = (rda[2]&0xffff)|
-            ((rda[1] & 0xff00) << 16);
-        rmd[2] = rda[3] & 0xffff;
-        rmd[3] = 0;
+    if (!BCR_SSIZE32(s)) {
+        struct {
+            uint32_t rbadr;
+            int16_t buf_length;
+            int16_t msg_length;
+	} rda;
+        s->phys_mem_read(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
+        rmd->rbadr = le32_to_cpu(rda.rbadr) & 0xffffff;
+        rmd->buf_length = le16_to_cpu(rda.buf_length);
+        rmd->status = (le32_to_cpu(rda.rbadr) >> 16) & 0xff00;
+        rmd->msg_length = le16_to_cpu(rda.msg_length);
+        rmd->res = 0;
     } else {
-        uint32_t rda[4];
-        s->phys_mem_read(s->dma_opaque, addr, 
-                         (void *)&rda[0], sizeof(rda), 0);
-        le32_to_cpus(&rda[0]);
-        le32_to_cpus(&rda[1]);
-        le32_to_cpus(&rda[2]);
-        le32_to_cpus(&rda[3]);
-        if (BCR_SWSTYLE(s) != 3) {
-            memcpy(rmd, rda, sizeof(rda));
-        } else {
-            rmd[0] = rda[2];
-            rmd[1] = rda[1];
-            rmd[2] = rda[0];
-            rmd[3] = rda[3];
+        s->phys_mem_read(s->dma_opaque, addr, (void *)rmd, sizeof(*rmd), 0);
+        le32_to_cpus(&rmd->rbadr);
+        le16_to_cpus(&rmd->buf_length);
+        le16_to_cpus(&rmd->status);
+        le32_to_cpus(&rmd->msg_length);
+        le32_to_cpus(&rmd->res);
+        if (BCR_SWSTYLE(s) == 3) {
+            uint32_t tmp = rmd->rbadr;
+            rmd->rbadr = rmd->msg_length;
+            rmd->msg_length = tmp;
         }
     }
 }
 
-static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd1, 
+static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd,
                                    target_phys_addr_t addr)
 {
-    const uint32_t *rmd = (const uint32_t *)rmd1;
-
-    if (!BCR_SWSTYLE(s)) {
-        uint16_t rda[4];
-        rda[0] = rmd[0] & 0xffff;
-        rda[1] = ((rmd[0]>>16)&0xff)|
-            ((rmd[1]>>16)&0xff00);
-        rda[2] = rmd[1] & 0xffff;
-        rda[3] = rmd[2] & 0xffff;
-        cpu_to_le16s(&rda[0]);
-        cpu_to_le16s(&rda[1]);
-        cpu_to_le16s(&rda[2]);
-        cpu_to_le16s(&rda[3]);
-        s->phys_mem_write(s->dma_opaque, addr,
-                (void *)&rda[0], sizeof(rda), 0);
+    if (!BCR_SSIZE32(s)) {
+        struct {
+            uint32_t rbadr;
+            int16_t buf_length;
+            int16_t msg_length;
+        } rda;
+        rda.rbadr = cpu_to_le32((rmd->rbadr & 0xffffff) |
+                                ((rmd->status & 0xff00) << 16));
+        rda.buf_length = cpu_to_le16(rmd->buf_length);
+        rda.msg_length = cpu_to_le16(rmd->msg_length);
+        s->phys_mem_write(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
     } else {
-        uint32_t rda[4];
-        if (BCR_SWSTYLE(s) != 3) {
-            memcpy(rda, rmd, sizeof(rda));
-        } else {
-            rda[0] = rmd[2];
-            rda[1] = rmd[1];
-            rda[2] = rmd[0];
-            rda[3] = rmd[3];
+        struct {
+            uint32_t rbadr;
+            int16_t buf_length;
+            int16_t status;
+            uint32_t msg_length;
+            uint32_t res;
+        } rda;
+        rda.rbadr = cpu_to_le32(rmd->rbadr);
+        rda.buf_length = cpu_to_le16(rmd->buf_length);
+        rda.status = cpu_to_le16(rmd->status);
+        rda.msg_length = cpu_to_le32(rmd->msg_length);
+        rda.res = cpu_to_le32(rmd->res);
+        if (BCR_SWSTYLE(s) == 3) {
+            uint32_t tmp = rda.rbadr;
+            rda.rbadr = rda.msg_length;
+            rda.msg_length = tmp;
         }
-        cpu_to_le32s(&rda[0]);
-        cpu_to_le32s(&rda[1]);
-        cpu_to_le32s(&rda[2]);
-        cpu_to_le32s(&rda[3]);
-        s->phys_mem_write(s->dma_opaque, addr,
-                          (void *)&rda[0], sizeof(rda), 0);
+        s->phys_mem_write(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
     }
 }
 
@@ -417,14 +477,14 @@
 #define CHECK_RMD(ADDR,RES) do {                \
     struct pcnet_RMD rmd;                       \
     RMDLOAD(&rmd,(ADDR));                       \
-    (RES) |= (rmd.rmd1.ones != 15)              \
-          || (rmd.rmd2.zeros != 0);             \
+    (RES) |= (GET_FIELD(rmd.buf_length, RMDL, ONES) != 15) \
+          || (GET_FIELD(rmd.msg_length, RMDM, ZEROS) != 0); \
 } while (0)
 
 #define CHECK_TMD(ADDR,RES) do {                \
     struct pcnet_TMD tmd;                       \
     TMDLOAD(&tmd,(ADDR));                       \
-    (RES) |= (tmd.tmd1.ones != 15);             \
+    (RES) |= (GET_FIELD(tmd.length, TMDL, ONES) != 15); \
 } while (0)
 
 #else
@@ -434,8 +494,8 @@
     case 0x00:                                  \
         do {                                    \
             uint16_t rda[4];                    \
-            s->phys_mem_read(s->dma_opaque, (ADDR),    \
-                (void *)&rda[0], sizeof(rda), 0);  \
+            s->phys_mem_read(s->dma_opaque, (ADDR), \
+                (void *)&rda[0], sizeof(rda), 0); \
             (RES) |= (rda[2] & 0xf000)!=0xf000; \
             (RES) |= (rda[3] & 0xf000)!=0x0000; \
         } while (0);                            \
@@ -444,7 +504,7 @@
     case 0x02:                                  \
         do {                                    \
             uint32_t rda[4];                    \
-            s->phys_mem_read(s->dma_opaque, (ADDR),    \
+            s->phys_mem_read(s->dma_opaque, (ADDR), \
                 (void *)&rda[0], sizeof(rda), 0); \
             (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
             (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \
@@ -453,7 +513,7 @@
     case 0x03:                                  \
         do {                                    \
             uint32_t rda[4];                    \
-            s->phys_mem_read(s->dma_opaque, (ADDR),    \
+            s->phys_mem_read(s->dma_opaque, (ADDR), \
                 (void *)&rda[0], sizeof(rda), 0); \
             (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \
             (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
@@ -467,9 +527,9 @@
     case 0x00:                                  \
         do {                                    \
             uint16_t xda[4];                    \
-            s->phys_mem_read(s->dma_opaque, (ADDR),    \
-                (void *)&xda[0], sizeof(xda), 0);  \
-            (RES) |= (xda[2] & 0xf000)!=0xf000;\
+            s->phys_mem_read(s->dma_opaque, (ADDR), \
+                (void *)&xda[0], sizeof(xda), 0); \
+            (RES) |= (xda[2] & 0xf000)!=0xf000; \
         } while (0);                            \
         break;                                  \
     case 0x01:                                  \
@@ -477,8 +537,8 @@
     case 0x03:                                  \
         do {                                    \
             uint32_t xda[4];                    \
-            s->phys_mem_read(s->dma_opaque, (ADDR),    \
-                (void *)&xda[0], sizeof(xda), 0);  \
+            s->phys_mem_read(s->dma_opaque, (ADDR), \
+                (void *)&xda[0], sizeof(xda), 0); \
             (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \
         } while (0);                            \
         break;                                  \
@@ -488,15 +548,15 @@
 #endif
 
 #define PRINT_PKTHDR(BUF) do {                  \
-    struct qemu_ether_header *hdr = (void *)(BUF);   \
-    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "       \
-           "shost=%02x:%02x:%02x:%02x:%02x:%02x, "              \
-           "type=0x%04x\n",                          \
+    struct qemu_ether_header *hdr = (void *)(BUF); \
+    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, " \
+           "shost=%02x:%02x:%02x:%02x:%02x:%02x, " \
+           "type=0x%04x\n",                     \
            hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2], \
            hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5], \
            hdr->ether_shost[0],hdr->ether_shost[1],hdr->ether_shost[2], \
            hdr->ether_shost[3],hdr->ether_shost[4],hdr->ether_shost[5], \
-           be16_to_cpu(hdr->ether_type));                     \
+           be16_to_cpu(hdr->ether_type));       \
 } while (0)
 
 #define MULTICAST_FILTER_LEN 8
@@ -763,14 +823,14 @@
         printf("pcnet: INTA=%d\n", isr);
 #endif
     }
-    s->set_irq_cb(s, isr);
+    qemu_set_irq(s->irq, isr);
     s->isr = isr;
 }
 
 static void pcnet_init(PCNetState *s)
 {
     int rlen, tlen;
-    uint16_t *padr, *ladrf, mode;
+    uint16_t padr[3], ladrf[4], mode;
     uint32_t rdra, tdra;
 
 #ifdef PCNET_DEBUG
@@ -781,22 +841,30 @@
         struct pcnet_initblk32 initblk;
         s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
                 (uint8_t *)&initblk, sizeof(initblk), 0);
-        mode = initblk.mode;
+        mode = le16_to_cpu(initblk.mode);
         rlen = initblk.rlen >> 4;
         tlen = initblk.tlen >> 4;
-        ladrf = initblk.ladrf;
-        padr = initblk.padr;
+	ladrf[0] = le16_to_cpu(initblk.ladrf[0]);
+	ladrf[1] = le16_to_cpu(initblk.ladrf[1]);
+	ladrf[2] = le16_to_cpu(initblk.ladrf[2]);
+	ladrf[3] = le16_to_cpu(initblk.ladrf[3]);
+	padr[0] = le16_to_cpu(initblk.padr[0]);
+	padr[1] = le16_to_cpu(initblk.padr[1]);
+	padr[2] = le16_to_cpu(initblk.padr[2]);
         rdra = le32_to_cpu(initblk.rdra);
         tdra = le32_to_cpu(initblk.tdra);
-        s->rdra = PHYSADDR(s,initblk.rdra);
-        s->tdra = PHYSADDR(s,initblk.tdra);
     } else {
         struct pcnet_initblk16 initblk;
         s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
                 (uint8_t *)&initblk, sizeof(initblk), 0);
-        mode = initblk.mode;
-        ladrf = initblk.ladrf;
-        padr = initblk.padr;
+        mode = le16_to_cpu(initblk.mode);
+	ladrf[0] = le16_to_cpu(initblk.ladrf[0]);
+	ladrf[1] = le16_to_cpu(initblk.ladrf[1]);
+	ladrf[2] = le16_to_cpu(initblk.ladrf[2]);
+	ladrf[3] = le16_to_cpu(initblk.ladrf[3]);
+	padr[0] = le16_to_cpu(initblk.padr[0]);
+	padr[1] = le16_to_cpu(initblk.padr[1]);
+	padr[2] = le16_to_cpu(initblk.padr[2]);
         rdra = le32_to_cpu(initblk.rdra);
         tdra = le32_to_cpu(initblk.tdra);
         rlen = rdra >> 29;
@@ -804,22 +872,22 @@
         rdra &= 0x00ffffff;
         tdra &= 0x00ffffff;
     }
-    
+
 #if defined(PCNET_DEBUG)
-    printf("rlen=%d tlen=%d\n",
-           rlen, tlen);
+    printf("rlen=%d tlen=%d\n", rlen, tlen);
 #endif
+
     CSR_RCVRL(s) = (rlen < 9) ? (1 << rlen) : 512;
     CSR_XMTRL(s) = (tlen < 9) ? (1 << tlen) : 512;
     s->csr[ 6] = (tlen << 12) | (rlen << 8);
-    s->csr[15] = le16_to_cpu(mode);
-    s->csr[ 8] = le16_to_cpu(ladrf[0]);
-    s->csr[ 9] = le16_to_cpu(ladrf[1]);
-    s->csr[10] = le16_to_cpu(ladrf[2]);
-    s->csr[11] = le16_to_cpu(ladrf[3]);
-    s->csr[12] = le16_to_cpu(padr[0]);
-    s->csr[13] = le16_to_cpu(padr[1]);
-    s->csr[14] = le16_to_cpu(padr[2]);
+    s->csr[15] = mode;
+    s->csr[ 8] = ladrf[0];
+    s->csr[ 9] = ladrf[1];
+    s->csr[10] = ladrf[2];
+    s->csr[11] = ladrf[3];
+    s->csr[12] = padr[0];
+    s->csr[13] = padr[1];
+    s->csr[14] = padr[2];
     s->rdra = PHYSADDR(s, rdra);
     s->tdra = PHYSADDR(s, tdra);
 
@@ -914,12 +982,12 @@
     if (CSR_CRDA(s)) {
         struct pcnet_RMD rmd;
         RMDLOAD(&rmd, PHYSADDR(s,CSR_CRDA(s)));
-        CSR_CRBC(s) = rmd.rmd1.bcnt;
-        CSR_CRST(s) = ((uint32_t *)&rmd)[1] >> 16;
+        CSR_CRBC(s) = GET_FIELD(rmd.buf_length, RMDL, BCNT);
+        CSR_CRST(s) = rmd.status;
 #ifdef PCNET_DEBUG_RMD_X
-        printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMD1=0x%08x RMD2=0x%08x\n",
+        printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMDL=0x%04x RMDS=0x%04x RMDM=0x%08x\n",
                 PHYSADDR(s,CSR_CRDA(s)), CSR_CRST(s), CSR_RCVRC(s),
-                ((uint32_t *)&rmd)[1], ((uint32_t *)&rmd)[2]);
+                rmd.buf_length, rmd.status, rmd.msg_length);
         PRINT_RMD(&rmd);
 #endif
     } else {
@@ -929,8 +997,8 @@
     if (CSR_NRDA(s)) {
         struct pcnet_RMD rmd;
         RMDLOAD(&rmd, PHYSADDR(s,CSR_NRDA(s)));
-        CSR_NRBC(s) = rmd.rmd1.bcnt;
-        CSR_NRST(s) = ((uint32_t *)&rmd)[1] >> 16;
+        CSR_NRBC(s) = GET_FIELD(rmd.buf_length, RMDL, BCNT);
+        CSR_NRST(s) = rmd.status;
     } else {
         CSR_NRBC(s) = CSR_NRST(s) = 0;
     }
@@ -943,7 +1011,7 @@
     if (s->tdra) {
         target_phys_addr_t cxda = s->tdra + 
             (CSR_XMTRL(s) - CSR_XMTRC(s)) *
-            (BCR_SWSTYLE(s) ? 16 : 8 );
+            (BCR_SWSTYLE(s) ? 16 : 8);
         int bad = 0;
         CHECK_TMD(PHYSADDR(s, cxda),bad);
         if (!bad) {
@@ -955,8 +1023,7 @@
             }
             s->csr[34] = cxda & 0xffff;
             s->csr[35] = cxda >> 16;
-#ifdef PCNET_DEBUG
-        } else {
+#ifdef PCNET_DEBUG_X
             printf("pcnet: BAD TMD XDA=0x%08x\n", PHYSADDR(s,cxda));
 #endif
         }
@@ -967,8 +1034,8 @@
 
         TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));                
 
-        CSR_CXBC(s) = tmd.tmd1.bcnt;
-        CSR_CXST(s) = ((uint32_t *)&tmd)[1] >> 16;
+        CSR_CXBC(s) = GET_FIELD(tmd.length, TMDL, BCNT);
+        CSR_CXST(s) = tmd.status;
     } else {
         CSR_CXBC(s) = CSR_CXST(s) = 0;
     }
@@ -1029,7 +1096,7 @@
                     (CSR_RCVRL(s) - rcvrc) *
                     (BCR_SWSTYLE(s) ? 16 : 8 );
                 RMDLOAD(&rmd, PHYSADDR(s,nrda));                  
-                if (rmd.rmd1.own) {                
+                if (GET_FIELD(rmd.status, RMDS, OWN)) {
 #ifdef PCNET_DEBUG_RMD
                     printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n", 
                                 rcvrc, CSR_RCVRC(s));
@@ -1086,14 +1153,15 @@
 
             RMDLOAD(&rmd, PHYSADDR(s,crda));
             /*if (!CSR_LAPPEN(s))*/
-                rmd.rmd1.stp = 1;
+                SET_FIELD(&rmd.status, RMDS, STP, 1);
 
 #define PCNET_RECV_STORE() do {                                 \
-    int count = MIN(4096 - rmd.rmd1.bcnt,size);                 \
-    target_phys_addr_t rbadr = PHYSADDR(s, rmd.rmd0.rbadr);     \
-    s->phys_mem_write(s->dma_opaque, rbadr, src, count, CSR_BSWP(s));  \
+    int count = MIN(4096 - GET_FIELD(rmd.buf_length, RMDL, BCNT),size); \
+    target_phys_addr_t rbadr = PHYSADDR(s, rmd.rbadr);          \
+    s->phys_mem_write(s->dma_opaque, rbadr, src, count, CSR_BSWP(s)); \
     src += count; size -= count;                                \
-    rmd.rmd2.mcnt = count; rmd.rmd1.own = 0;                    \
+    SET_FIELD(&rmd.msg_length, RMDM, MCNT, count);              \
+    SET_FIELD(&rmd.status, RMDS, OWN, 0);                       \
     RMDSTORE(&rmd, PHYSADDR(s,crda));                           \
     pktcount++;                                                 \
 } while (0)
@@ -1102,12 +1170,12 @@
             if ((size > 0) && CSR_NRDA(s)) {
                 target_phys_addr_t nrda = CSR_NRDA(s);
                 RMDLOAD(&rmd, PHYSADDR(s,nrda));
-                if (rmd.rmd1.own) {
+                if (GET_FIELD(rmd.status, RMDS, OWN)) {
                     crda = nrda;
                     PCNET_RECV_STORE();
                     if ((size > 0) && (nrda=CSR_NNRD(s))) {
                         RMDLOAD(&rmd, PHYSADDR(s,nrda));
-                        if (rmd.rmd1.own) {
+                        if (GET_FIELD(rmd.status, RMDS, OWN)) {
                             crda = nrda;
                             PCNET_RECV_STORE();
                         }
@@ -1119,14 +1187,14 @@
 
             RMDLOAD(&rmd, PHYSADDR(s,crda));
             if (size == 0) {
-                rmd.rmd1.enp = 1;
-                rmd.rmd1.pam = !CSR_PROM(s) && is_padr;
-                rmd.rmd1.lafm = !CSR_PROM(s) && is_ladr;
-                rmd.rmd1.bam = !CSR_PROM(s) && is_bcast;
+                SET_FIELD(&rmd.status, RMDS, ENP, 1);
+                SET_FIELD(&rmd.status, RMDS, PAM, !CSR_PROM(s) && is_padr);
+                SET_FIELD(&rmd.status, RMDS, LFAM, !CSR_PROM(s) && is_ladr);
+                SET_FIELD(&rmd.status, RMDS, BAM, !CSR_PROM(s) && is_bcast);
             } else {
-                rmd.rmd1.oflo = 1;
-                rmd.rmd1.buff = 1;
-                rmd.rmd1.err = 1;
+                SET_FIELD(&rmd.status, RMDS, OFLO, 1);
+                SET_FIELD(&rmd.status, RMDS, BUFF, 1);
+                SET_FIELD(&rmd.status, RMDS, ERR, 1);
             }
             RMDSTORE(&rmd, PHYSADDR(s,crda));
             s->csr[0] |= 0x0400;
@@ -1172,30 +1240,30 @@
     if (pcnet_tdte_poll(s)) {
         struct pcnet_TMD tmd;
 
-        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));                
+        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
 
 #ifdef PCNET_DEBUG_TMD
         printf("  TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s)));
         PRINT_TMD(&tmd);
 #endif
-        if (tmd.tmd1.stp) {
-            s->xmit_pos = 0;                
-            if (!tmd.tmd1.enp) {
-                s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tmd0.tbadr),
-                                 s->buffer, 4096 - tmd.tmd1.bcnt, 
-                                 CSR_BSWP(s));
-                s->xmit_pos += 4096 - tmd.tmd1.bcnt;
-            } 
+        if (GET_FIELD(tmd.status, TMDS, STP)) {
+            s->xmit_pos = 0;
+            if (!GET_FIELD(tmd.status, TMDS, ENP)) {
+                int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
+                s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
+                                 s->buffer, bcnt, CSR_BSWP(s));
+                s->xmit_pos += bcnt;
+            }
             xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
         }
-        if (tmd.tmd1.enp && (s->xmit_pos >= 0)) {
-            s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tmd0.tbadr),
-                             s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt, 
-                             CSR_BSWP(s));
-            s->xmit_pos += 4096 - tmd.tmd1.bcnt;
+        if (GET_FIELD(tmd.status, TMDS, ENP) && (s->xmit_pos >= 0)) {
+            int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
+            s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
+                             s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
+            s->xmit_pos += bcnt;
 #ifdef PCNET_DEBUG
             printf("pcnet_transmit size=%d\n", s->xmit_pos);
-#endif            
+#endif
             if (CSR_LOOP(s))
                 pcnet_receive(s, s->buffer, s->xmit_pos);
             else
@@ -1206,9 +1274,9 @@
             s->xmit_pos = -1;
         }
 
-        tmd.tmd1.own = 0;
+        SET_FIELD(&tmd.status, TMDS, OWN, 0);
         TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
-        if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && tmd.tmd1.ltint))
+        if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && GET_FIELD(tmd.status, TMDS, LTINT)))
             s->csr[0] |= 0x0200;    /* set TINT */
 
         if (CSR_XMTRC(s)<=1)
@@ -1221,9 +1289,11 @@
     } else 
     if (s->xmit_pos >= 0) {
         struct pcnet_TMD tmd;
-        TMDLOAD(&tmd, PHYSADDR(s,xmit_cxda));                
-        tmd.tmd2.buff = tmd.tmd2.uflo = tmd.tmd1.err = 1;
-        tmd.tmd1.own = 0;
+        TMDLOAD(&tmd, PHYSADDR(s,xmit_cxda));
+        SET_FIELD(&tmd.misc, TMDM, BUFF, 1);
+        SET_FIELD(&tmd.misc, TMDM, UFLO, 1);
+        SET_FIELD(&tmd.status, TMDS, ERR, 1);
+        SET_FIELD(&tmd.status, TMDS, OWN, 0);
         TMDSTORE(&tmd, PHYSADDR(s,xmit_cxda));
         s->csr[0] |= 0x0200;    /* set TINT */
         if (!CSR_DXSUFLO(s)) {
@@ -1870,13 +1940,6 @@
     cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_index);
 }
 
-static void pcnet_pci_set_irq_cb(void *opaque, int isr)
-{
-    PCNetState *s = opaque;
-
-    pci_set_irq(&s->dev, 0, isr);
-}
-
 static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr,
                                       uint8_t *buf, int len, int do_bswap)
 {
@@ -1889,7 +1952,7 @@
     cpu_physical_memory_read(addr, buf, len);
 }
 
-void pci_pcnet_init(PCIBus *bus, NICInfo *nd)
+void pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
     PCNetState *d;
     uint8_t *pci_conf;
@@ -1900,7 +1963,7 @@
 #endif
 
     d = (PCNetState *)pci_register_device(bus, "PCNet", sizeof(PCNetState),
-                                          -1, NULL, NULL);
+                                          devfn, NULL, NULL);
                                           
     pci_conf = d->dev.config;
     
@@ -1931,7 +1994,7 @@
     pci_register_io_region((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE, 
                            PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map);
                            
-    d->set_irq_cb = pcnet_pci_set_irq_cb;
+    d->irq = d->dev.irq[0];
     d->phys_mem_read = pci_physical_memory_read;
     d->phys_mem_write = pci_physical_memory_write;
     d->pci_dev = &d->dev;
@@ -1955,15 +2018,8 @@
     (CPUWriteMemoryFunc *)&pcnet_ioport_writew,
 };
 
-static void pcnet_sparc_set_irq_cb(void *opaque, int isr)
+void *lance_init(NICInfo *nd, uint32_t leaddr, void *dma_opaque, qemu_irq irq)
 {
-    PCNetState *s = opaque;
-
-    ledma_set_irq(s->dma_opaque, isr);
-}
-
-void *lance_init(NICInfo *nd, uint32_t leaddr, void *dma_opaque)
-{
     PCNetState *d;
     int lance_io_memory;
 
@@ -1977,7 +2033,7 @@
     d->dma_opaque = dma_opaque;
     cpu_register_physical_memory(leaddr, 4, lance_io_memory);
 
-    d->set_irq_cb = pcnet_sparc_set_irq_cb;
+    d->irq = irq;
     d->phys_mem_read = ledma_memory_read;
     d->phys_mem_write = ledma_memory_write;
 

Modified: trunk/src/host/qemu-neo1973/hw/pcspk.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pcspk.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pcspk.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -92,7 +92,7 @@
     }
 }
 
-int pcspk_audio_init(AudioState *audio)
+int pcspk_audio_init(AudioState *audio, qemu_irq *pic)
 {
     PCSpkState *s = &pcspk_state;
     audsettings_t as = {PCSPK_SAMPLE_RATE, 1, AUD_FMT_U8, 0};

Modified: trunk/src/host/qemu-neo1973/hw/pflash_cfi02.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pflash_cfi02.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pflash_cfi02.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -91,7 +91,7 @@
     uint32_t ret;
     uint8_t *p;
 
-    DPRINTF("%s: offset %08x\n", __func__, offset);
+    DPRINTF("%s: offset " TARGET_FMT_lx "\n", __func__, offset);
     ret = -1;
     offset -= pfl->base;
     boff = offset & 0xFF;
@@ -161,7 +161,7 @@
         default:
             goto flash_read;
         }
-        DPRINTF("%s: ID %d %x\n", __func__, boff, ret);
+        DPRINTF("%s: ID " TARGET_FMT_ld " %x\n", __func__, boff, ret);
         break;
     case 0xA0:
     case 0x10:
@@ -208,18 +208,23 @@
 
     /* WARNING: when the memory area is in ROMD mode, the offset is a
        ram offset, not a physical address */
-    if (pfl->wcycle == 0)
-        offset -= (target_ulong)(long)pfl->storage;
-    else
-        offset -= pfl->base;
-        
     cmd = value;
-    DPRINTF("%s: offset %08x %08x %d\n", __func__, offset, value, width);
     if (pfl->cmd != 0xA0 && cmd == 0xF0) {
+#if 0
         DPRINTF("%s: flash reset asked (%02x %02x)\n",
                 __func__, pfl->cmd, cmd);
+#endif
         goto reset_flash;
     }
+    DPRINTF("%s: offset " TARGET_FMT_lx " %08x %d %d\n", __func__,
+            offset, value, width, pfl->wcycle);
+    if (pfl->wcycle == 0)
+        offset -= (target_ulong)(long)pfl->storage;
+    else
+        offset -= pfl->base;
+        
+    DPRINTF("%s: offset " TARGET_FMT_lx " %08x %d\n", __func__,
+            offset, value, width);
     /* Set the device in I/O access mode */
     cpu_register_physical_memory(pfl->base, pfl->total_len, pfl->fl_mem);
     boff = offset & (pfl->sector_len - 1);
@@ -239,7 +244,7 @@
             return;
         }
         if (boff != 0x555 || cmd != 0xAA) {
-            DPRINTF("%s: unlock0 failed %04x %02x %04x\n",
+            DPRINTF("%s: unlock0 failed " TARGET_FMT_lx " %02x %04x\n",
                     __func__, boff, cmd, 0x555);
             goto reset_flash;
         }
@@ -249,7 +254,8 @@
         /* We started an unlock sequence */
     check_unlock1:
         if (boff != 0x2AA || cmd != 0x55) {
-            DPRINTF("%s: unlock1 failed %04x %02x\n", __func__, boff, cmd);
+            DPRINTF("%s: unlock1 failed " TARGET_FMT_lx " %02x\n", __func__,
+                    boff, cmd);
             goto reset_flash;
         }
         DPRINTF("%s: unlock sequence done\n", __func__);
@@ -257,7 +263,8 @@
     case 2:
         /* We finished an unlock sequence */
         if (!pfl->bypass && boff != 0x555) {
-            DPRINTF("%s: command failed %04x %02x\n", __func__, boff, cmd);
+            DPRINTF("%s: command failed " TARGET_FMT_lx " %02x\n", __func__,
+                    boff, cmd);
             goto reset_flash;
         }
         switch (cmd) {
@@ -281,7 +288,7 @@
             /* We need another unlock sequence */
             goto check_unlock0;
         case 0xA0:
-            DPRINTF("%s: write data offset %08x %08x %d\n",
+            DPRINTF("%s: write data offset " TARGET_FMT_lx " %08x %d\n",
                     __func__, offset, value, width);
             p = pfl->storage;
             switch (width) {
@@ -352,7 +359,7 @@
         switch (cmd) {
         case 0x10:
             if (boff != 0x555) {
-                DPRINTF("%s: chip erase: invalid address %04x\n",
+                DPRINTF("%s: chip erase: invalid address " TARGET_FMT_lx "\n",
                         __func__, offset);
                 goto reset_flash;
             }
@@ -369,7 +376,8 @@
             /* Sector erase */
             p = pfl->storage;
             offset &= ~(pfl->sector_len - 1);
-            DPRINTF("%s: start sector erase at %08x\n", __func__, offset);
+            DPRINTF("%s: start sector erase at " TARGET_FMT_lx "\n", __func__,
+                    offset);
             memset(p + offset, 0xFF, pfl->sector_len);
             pflash_update(pfl, offset, pfl->sector_len);
             pfl->status = 0x00;
@@ -412,10 +420,8 @@
 
     /* Reset flash */
  reset_flash:
-    if (pfl->wcycle != 0) {
-        cpu_register_physical_memory(pfl->base, pfl->total_len,
-                                     pfl->off | IO_MEM_ROMD | pfl->fl_mem);
-    }
+    cpu_register_physical_memory(pfl->base, pfl->total_len,
+                                 pfl->off | IO_MEM_ROMD | pfl->fl_mem);
     pfl->bypass = 0;
     pfl->wcycle = 0;
     pfl->cmd = 0;
@@ -526,14 +532,17 @@
 
     total_len = sector_len * nb_blocs;
     /* XXX: to be fixed */
+#if 0
     if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) &&
         total_len != (32 * 1024 * 1024) && total_len != (64 * 1024 * 1024))
         return NULL;
+#endif
     pfl = qemu_mallocz(sizeof(pflash_t));
     if (pfl == NULL)
         return NULL;
     pfl->storage = phys_ram_base + off;
-    pfl->fl_mem = cpu_register_io_memory(0, pflash_read_ops, pflash_write_ops, pfl);
+    pfl->fl_mem = cpu_register_io_memory(0, pflash_read_ops, pflash_write_ops,
+                                         pfl);
     pfl->off = off;
     cpu_register_physical_memory(base, total_len,
                                  off | pfl->fl_mem | IO_MEM_ROMD);
@@ -609,7 +618,9 @@
     pfl->cfi_table[0x28] = 0x02;
     pfl->cfi_table[0x29] = 0x00;
     /* Max number of bytes in multi-bytes write */
-    pfl->cfi_table[0x2A] = 0x05;
+    /* XXX: disable buffered write as it's not supported */
+    //    pfl->cfi_table[0x2A] = 0x05;
+    pfl->cfi_table[0x2A] = 0x00;
     pfl->cfi_table[0x2B] = 0x00;
     /* Number of erase block regions (uniform) */
     pfl->cfi_table[0x2C] = 0x01;

Modified: trunk/src/host/qemu-neo1973/hw/piix_pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/piix_pci.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/piix_pci.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -40,7 +40,7 @@
     return s->config_reg;
 }
 
-static void piix3_set_irq(void *pic, int irq_num, int level);
+static void piix3_set_irq(qemu_irq *pic, int irq_num, int level);
 
 /* return the global irq number corresponding to a given device irq
    pin. We could also use the bus number to have a more precise
@@ -155,14 +155,14 @@
     return 0;
 }
 
-PCIBus *i440fx_init(PCIDevice **pi440fx_state)
+PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic)
 {
     PCIBus *b;
     PCIDevice *d;
     I440FXState *s;
 
     s = qemu_mallocz(sizeof(I440FXState));
-    b = pci_register_bus(piix3_set_irq, pci_slot_get_pirq, NULL, 0, 4);
+    b = pci_register_bus(piix3_set_irq, pci_slot_get_pirq, pic, 0, 4);
     s->bus = b;
 
     register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
@@ -196,14 +196,15 @@
 
 /* PIIX3 PCI to ISA bridge */
 
-static PCIDevice *piix3_dev;
+PCIDevice *piix3_dev;
+PCIDevice *piix4_dev;
 
 /* just used for simpler irq handling. */
 #define PCI_IRQ_WORDS   ((PCI_DEVICES_MAX + 31) / 32)
 
 static int pci_irq_levels[4];
 
-static void piix3_set_irq(void *pic, int irq_num, int level)
+static void piix3_set_irq(qemu_irq *pic, int irq_num, int level)
 {
     int i, pic_irq, pic_level;
 
@@ -220,7 +221,7 @@
             if (pic_irq == piix3_dev->config[0x60 + i])
                 pic_level |= pci_irq_levels[i];
         }
-        pic_set_irq(pic_irq, pic_level);
+        qemu_set_irq(pic[pic_irq], pic_level);
     }
 }
 
@@ -245,6 +246,42 @@
     pci_conf[0x80] = 0x00;
     pci_conf[0x82] = 0x00;
     pci_conf[0xa0] = 0x08;
+    pci_conf[0xa2] = 0x00;
+    pci_conf[0xa3] = 0x00;
+    pci_conf[0xa4] = 0x00;
+    pci_conf[0xa5] = 0x00;
+    pci_conf[0xa6] = 0x00;
+    pci_conf[0xa7] = 0x00;
+    pci_conf[0xa8] = 0x0f;
+    pci_conf[0xaa] = 0x00;
+    pci_conf[0xab] = 0x00;
+    pci_conf[0xac] = 0x00;
+    pci_conf[0xae] = 0x00;
+}
+
+static void piix4_reset(PCIDevice *d)
+{
+    uint8_t *pci_conf = d->config;
+
+    pci_conf[0x04] = 0x07; // master, memory and I/O
+    pci_conf[0x05] = 0x00;
+    pci_conf[0x06] = 0x00;
+    pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
+    pci_conf[0x4c] = 0x4d;
+    pci_conf[0x4e] = 0x03;
+    pci_conf[0x4f] = 0x00;
+    pci_conf[0x60] = 0x0a; // PCI A -> IRQ 10
+    pci_conf[0x61] = 0x0a; // PCI B -> IRQ 10
+    pci_conf[0x62] = 0x0b; // PCI C -> IRQ 11
+    pci_conf[0x63] = 0x0b; // PCI D -> IRQ 11
+    pci_conf[0x69] = 0x02;
+    pci_conf[0x70] = 0x80;
+    pci_conf[0x76] = 0x0c;
+    pci_conf[0x77] = 0x0c;
+    pci_conf[0x78] = 0x02;
+    pci_conf[0x79] = 0x00;
+    pci_conf[0x80] = 0x00;
+    pci_conf[0x82] = 0x00;
     pci_conf[0xa0] = 0x08;
     pci_conf[0xa2] = 0x00;
     pci_conf[0xa3] = 0x00;
@@ -273,13 +310,38 @@
     return pci_device_load(d, f);
 }
 
-int piix3_init(PCIBus *bus)
+int piix_init(PCIBus *bus, int devfn)
 {
     PCIDevice *d;
     uint8_t *pci_conf;
 
+    d = pci_register_device(bus, "PIIX", sizeof(PCIDevice),
+                                    devfn, NULL, NULL);
+    register_savevm("PIIX", 0, 2, piix_save, piix_load, d);
+
+    piix3_dev = d;
+    pci_conf = d->config;
+
+    pci_conf[0x00] = 0x86; // Intel
+    pci_conf[0x01] = 0x80;
+    pci_conf[0x02] = 0x2E; // 82371FB PIIX PCI-to-ISA bridge
+    pci_conf[0x03] = 0x12;
+    pci_conf[0x08] = 0x02; // Step A1
+    pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
+    pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
+    pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
+
+    piix3_reset(d);
+    return d->devfn;
+}
+
+int piix3_init(PCIBus *bus, int devfn)
+{
+    PCIDevice *d;
+    uint8_t *pci_conf;
+
     d = pci_register_device(bus, "PIIX3", sizeof(PCIDevice),
-                                    -1, NULL, NULL);
+                                    devfn, NULL, NULL);
     register_savevm("PIIX3", 0, 2, piix_save, piix_load, d);
 
     piix3_dev = d;
@@ -296,3 +358,27 @@
     piix3_reset(d);
     return d->devfn;
 }
+
+int piix4_init(PCIBus *bus, int devfn)
+{
+    PCIDevice *d;
+    uint8_t *pci_conf;
+
+    d = pci_register_device(bus, "PIIX4", sizeof(PCIDevice),
+                                    devfn, NULL, NULL);
+    register_savevm("PIIX4", 0, 2, piix_save, piix_load, d);
+
+    piix4_dev = d;
+    pci_conf = d->config;
+
+    pci_conf[0x00] = 0x86; // Intel
+    pci_conf[0x01] = 0x80;
+    pci_conf[0x02] = 0x10; // 82371AB/EB/MB PIIX4 PCI-to-ISA bridge
+    pci_conf[0x03] = 0x71;
+    pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
+    pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
+    pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
+
+    piix4_reset(d);
+    return d->devfn;
+}

Modified: trunk/src/host/qemu-neo1973/hw/pl011.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pl011.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pl011.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -27,8 +27,7 @@
     int read_count;
     int read_trigger;
     CharDriverState *chr;
-    void *pic;
-    int irq;
+    qemu_irq irq;
 } pl011_state;
 
 #define PL011_INT_TX 0x20
@@ -47,7 +46,7 @@
     uint32_t flags;
     
     flags = s->int_level & s->int_enabled;
-    pic_set_irq_new(s->pic, s->irq, flags != 0);
+    qemu_set_irq(s->irq, flags != 0);
 }
 
 static uint32_t pl011_read(void *opaque, target_phys_addr_t offset)
@@ -224,7 +223,7 @@
    pl011_write
 };
 
-void pl011_init(uint32_t base, void *pic, int irq,
+void pl011_init(uint32_t base, qemu_irq irq,
                 CharDriverState *chr)
 {
     int iomemtype;
@@ -235,7 +234,6 @@
                                        pl011_writefn, s);
     cpu_register_physical_memory(base, 0x00000fff, iomemtype);
     s->base = base;
-    s->pic = pic;
     s->irq = irq;
     s->chr = chr;
     s->read_trigger = 1;
@@ -243,8 +241,8 @@
     s->cr = 0x300;
     s->flags = 0x90;
     if (chr){ 
-        qemu_chr_add_read_handler(chr, pl011_can_recieve, pl011_recieve, s);
-        qemu_chr_add_event_handler(chr, pl011_event);
+        qemu_chr_add_handlers(chr, pl011_can_recieve, pl011_recieve,
+                              pl011_event, s);
     }
     /* ??? Save/restore.  */
 }

Modified: trunk/src/host/qemu-neo1973/hw/pl050.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pl050.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pl050.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /* 
  * Arm PrimeCell PL050 Keyboard / Mouse Interface
  *
- * Copyright (c) 2006 CodeSourcery.
+ * Copyright (c) 2006-2007 CodeSourcery.
  * Written by Paul Brook
  *
  * This code is licenced under the GPL.
@@ -15,12 +15,19 @@
     uint32_t cr;
     uint32_t clk;
     uint32_t last;
-    void *pic;
     int pending;
-    int irq;
+    qemu_irq irq;
     int is_mouse;
 } pl050_state;
 
+#define PL050_TXEMPTY         (1 << 6)
+#define PL050_TXBUSY          (1 << 5)
+#define PL050_RXFULL          (1 << 4)
+#define PL050_RXBUSY          (1 << 3)
+#define PL050_RXPARITY        (1 << 2)
+#define PL050_KMIC            (1 << 1)
+#define PL050_KMID            (1 << 0)
+
 static const unsigned char pl050_id[] =
 { 0x50, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
 
@@ -32,7 +39,7 @@
     s->pending = level;
     raise = (s->pending && (s->cr & 0x10) != 0)
             || (s->cr & 0x08) != 0;
-    pic_set_irq_new(s->pic, s->irq, raise);
+    qemu_set_irq(s->irq, raise);
 }
 
 static uint32_t pl050_read(void *opaque, target_phys_addr_t offset)
@@ -46,11 +53,22 @@
     case 0: /* KMICR */
         return s->cr;
     case 1: /* KMISTAT */
-        /* KMIC and KMID bits not implemented.  */
-        if (s->pending) {
-            return 0x10;
-        } else {
-            return 0;
+        {
+            uint8_t val;
+            uint32_t stat;
+
+            val = s->last;
+            val = val ^ (val >> 4);
+            val = val ^ (val >> 2);
+            val = (val ^ (val >> 1)) & 1;
+
+            stat = PL050_TXEMPTY;
+            if (val)
+                stat |= PL050_RXPARITY;
+            if (s->pending)
+                stat |= PL050_RXFULL;
+
+            return stat;
         }
     case 2: /* KMIDATA */
         if (s->pending)
@@ -105,7 +123,7 @@
    pl050_write
 };
 
-void pl050_init(uint32_t base, void *pic, int irq, int is_mouse)
+void pl050_init(uint32_t base, qemu_irq irq, int is_mouse)
 {
     int iomemtype;
     pl050_state *s;
@@ -115,7 +133,6 @@
                                        pl050_writefn, s);
     cpu_register_physical_memory(base, 0x00000fff, iomemtype);
     s->base = base;
-    s->pic = pic;
     s->irq = irq;
     s->is_mouse = is_mouse;
     if (is_mouse)

Modified: trunk/src/host/qemu-neo1973/hw/pl080.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pl080.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pl080.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -49,8 +49,7 @@
     int nchannels;
     /* Flag to avoid recursive DMA invocations.  */
     int running;
-    void *pic;
-    int irq;
+    qemu_irq irq;
 } pl080_state;
 
 static const unsigned char pl080_id[] =
@@ -63,9 +62,9 @@
 {
     if ((s->tc_int & s->tc_mask)
             || (s->err_int & s->err_mask))
-        pic_set_irq_new(s->pic, s->irq, 1);
+        qemu_irq_raise(s->irq);
     else
-        pic_set_irq_new(s->pic, s->irq, 1);
+        qemu_irq_lower(s->irq);
 }
 
 static void pl080_run(pl080_state *s)
@@ -325,7 +324,7 @@
 
 /* The PL080 and PL081 are the same except for the number of channels
    they implement (8 and 2 respectively).  */
-void *pl080_init(uint32_t base, void *pic, int irq, int nchannels)
+void *pl080_init(uint32_t base, qemu_irq irq, int nchannels)
 {
     int iomemtype;
     pl080_state *s;
@@ -335,7 +334,6 @@
                                        pl080_writefn, s);
     cpu_register_physical_memory(base, 0x00000fff, iomemtype);
     s->base = base;
-    s->pic = pic;
     s->irq = irq;
     s->nchannels = nchannels;
     /* ??? Save/restore.  */

Modified: trunk/src/host/qemu-neo1973/hw/pl110.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pl110.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pl110.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -29,7 +29,6 @@
     DisplayState *ds;
     /* The Versatile/PB uses a slightly modified PL110 controller.  */
     int versatile;
-    void *pic;
     uint32_t timing[4];
     uint32_t cr;
     uint32_t upbase;
@@ -42,7 +41,7 @@
     int invalidate;
     uint32_t pallette[256];
     uint32_t raw_pallette[128];
-    int irq;
+    qemu_irq irq;
 } pl110_state;
 
 static const unsigned char pl110_id[] =
@@ -399,7 +398,7 @@
    pl110_write
 };
 
-void *pl110_init(DisplayState *ds, uint32_t base, void *pic, int irq,
+void *pl110_init(DisplayState *ds, uint32_t base, qemu_irq irq,
                  int versatile)
 {
     pl110_state *s;
@@ -412,7 +411,6 @@
     s->base = base;
     s->ds = ds;
     s->versatile = versatile;
-    s->pic = pic;
     s->irq = irq;
     graphic_console_init(ds, pl110_update_display, pl110_invalidate_display,
                          NULL, s);

Added: trunk/src/host/qemu-neo1973/hw/pl181.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pl181.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pl181.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,443 @@
+/* 
+ * Arm PrimeCell PL181 MultiMedia Card Interface
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include "vl.h"
+#include "sd.h"
+
+//#define DEBUG_PL181 1
+
+#ifdef DEBUG_PL181
+#define DPRINTF(fmt, args...) \
+do { printf("pl181: " fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...) do {} while(0)
+#endif
+
+#define PL181_FIFO_LEN 16
+
+typedef struct {
+    SDState *card;
+    uint32_t base;
+    uint32_t clock;
+    uint32_t power;
+    uint32_t cmdarg;
+    uint32_t cmd;
+    uint32_t datatimer;
+    uint32_t datalength;
+    uint32_t respcmd;
+    uint32_t response[4];
+    uint32_t datactrl;
+    uint32_t datacnt;
+    uint32_t status;
+    uint32_t mask[2];
+    uint32_t fifocnt;
+    int fifo_pos;
+    int fifo_len;
+    uint32_t fifo[PL181_FIFO_LEN];
+    qemu_irq irq[2];
+} pl181_state;
+
+#define PL181_CMD_INDEX     0x3f
+#define PL181_CMD_RESPONSE  (1 << 6)
+#define PL181_CMD_LONGRESP  (1 << 7)
+#define PL181_CMD_INTERRUPT (1 << 8)
+#define PL181_CMD_PENDING   (1 << 9)
+#define PL181_CMD_ENABLE    (1 << 10)
+
+#define PL181_DATA_ENABLE             (1 << 0)
+#define PL181_DATA_DIRECTION          (1 << 1)
+#define PL181_DATA_MODE               (1 << 2)
+#define PL181_DATA_DMAENABLE          (1 << 3)
+
+#define PL181_STATUS_CMDCRCFAIL       (1 << 0)
+#define PL181_STATUS_DATACRCFAIL      (1 << 1)
+#define PL181_STATUS_CMDTIMEOUT       (1 << 2)
+#define PL181_STATUS_DATATIMEOUT      (1 << 3)
+#define PL181_STATUS_TXUNDERRUN       (1 << 4)
+#define PL181_STATUS_RXOVERRUN        (1 << 5)
+#define PL181_STATUS_CMDRESPEND       (1 << 6)
+#define PL181_STATUS_CMDSENT          (1 << 7)
+#define PL181_STATUS_DATAEND          (1 << 8)
+#define PL181_STATUS_DATABLOCKEND     (1 << 10)
+#define PL181_STATUS_CMDACTIVE        (1 << 11)
+#define PL181_STATUS_TXACTIVE         (1 << 12)
+#define PL181_STATUS_RXACTIVE         (1 << 13)
+#define PL181_STATUS_TXFIFOHALFEMPTY  (1 << 14)
+#define PL181_STATUS_RXFIFOHALFFULL   (1 << 15)
+#define PL181_STATUS_TXFIFOFULL       (1 << 16)
+#define PL181_STATUS_RXFIFOFULL       (1 << 17)
+#define PL181_STATUS_TXFIFOEMPTY      (1 << 18)
+#define PL181_STATUS_RXFIFOEMPTY      (1 << 19)
+#define PL181_STATUS_TXDATAAVLBL      (1 << 20)
+#define PL181_STATUS_RXDATAAVLBL      (1 << 21)
+
+#define PL181_STATUS_TX_FIFO (PL181_STATUS_TXACTIVE \
+                             |PL181_STATUS_TXFIFOHALFEMPTY \
+                             |PL181_STATUS_TXFIFOFULL \
+                             |PL181_STATUS_TXFIFOEMPTY \
+                             |PL181_STATUS_TXDATAAVLBL)
+#define PL181_STATUS_RX_FIFO (PL181_STATUS_RXACTIVE \
+                             |PL181_STATUS_RXFIFOHALFFULL \
+                             |PL181_STATUS_RXFIFOFULL \
+                             |PL181_STATUS_RXFIFOEMPTY \
+                             |PL181_STATUS_RXDATAAVLBL)
+
+static const unsigned char pl181_id[] =
+{ 0x81, 0x11, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
+
+static void pl181_update(pl181_state *s)
+{
+    int i;
+    for (i = 0; i < 2; i++) {
+        qemu_set_irq(s->irq[i], (s->status & s->mask[i]) != 0);
+    }
+}
+
+static void pl181_fifo_push(pl181_state *s, uint32_t value)
+{
+    int n;
+
+    if (s->fifo_len == PL181_FIFO_LEN) {
+        fprintf(stderr, "pl181: FIFO overflow\n");
+        return;
+    }
+    n = (s->fifo_pos + s->fifo_len) & (PL181_FIFO_LEN - 1);
+    s->fifo_len++;
+    s->fifo[n] = value;
+    DPRINTF("FIFO push %08x\n", (int)value);
+}
+
+static uint32_t pl181_fifo_pop(pl181_state *s)
+{
+    uint32_t value;
+
+    if (s->fifo_len == 0) {
+        fprintf(stderr, "pl181: FIFO underflow\n");
+        return 0;
+    }
+    value = s->fifo[s->fifo_pos];
+    s->fifo_len--;
+    s->fifo_pos = (s->fifo_pos + 1) & (PL181_FIFO_LEN - 1);
+    DPRINTF("FIFO pop %08x\n", (int)value);
+    return value;
+}
+
+static void pl181_send_command(pl181_state *s)
+{
+    struct sd_request_s request;
+    uint8_t response[16];
+    int rlen;
+
+    request.cmd = s->cmd & PL181_CMD_INDEX;
+    request.arg = s->cmdarg;
+    DPRINTF("Command %d %08x\n", request.cmd, request.arg);
+    rlen = sd_do_command(s->card, &request, response);
+    if (rlen < 0)
+        goto error;
+    if (s->cmd & PL181_CMD_RESPONSE) {
+#define RWORD(n) ((response[n] << 24) | (response[n + 1] << 16) \
+                  | (response[n + 2] << 8) | response[n + 3])
+        if (rlen == 0 || (rlen == 4 && (s->cmd & PL181_CMD_LONGRESP)))
+            goto error;
+        if (rlen != 4 && rlen != 16)
+            goto error;
+        s->response[0] = RWORD(0);
+        if (rlen == 4) {
+            s->response[1] = s->response[2] = s->response[3] = 0;
+        } else {
+            s->response[1] = RWORD(4);
+            s->response[2] = RWORD(8);
+            s->response[3] = RWORD(12) & ~1;
+        }
+        DPRINTF("Response recieved\n");
+        s->status |= PL181_STATUS_CMDRESPEND;
+#undef RWORD
+    } else {
+        DPRINTF("Command sent\n");
+        s->status |= PL181_STATUS_CMDSENT;
+    }
+    return;
+
+error:
+    DPRINTF("Timeout\n");
+    s->status |= PL181_STATUS_CMDTIMEOUT;
+}
+
+/* Transfer data between teh card and the FIFO.  This is complicated by
+   the FIFO holding 32-bit words and the card taking data in single byte
+   chunks.  FIFO bytes are transferred in little-endian order.  */
+   
+static void pl181_fifo_run(pl181_state *s)
+{
+    uint32_t bits;
+    uint32_t value;
+    int n;
+    int limit;
+    int is_read;
+
+    is_read = (s->datactrl & PL181_DATA_DIRECTION) != 0;
+    if (s->datacnt != 0 && (!is_read || sd_data_ready(s->card))) {
+        limit = is_read ? PL181_FIFO_LEN : 0;
+        n = 0;
+        value = 0;
+        while (s->datacnt && s->fifo_len != limit) {
+            if (is_read) {
+                value |= (uint32_t)sd_read_data(s->card) << (n * 8);
+                n++;
+                if (n == 4) {
+                    pl181_fifo_push(s, value);
+                    value = 0;
+                    n = 0;
+                }
+            } else {
+                if (n == 0) {
+                    value = pl181_fifo_pop(s);
+                    n = 4;
+                }
+                sd_write_data(s->card, value & 0xff);
+                value >>= 8;
+                n--;
+            }
+            s->datacnt--;
+        }
+        if (n && is_read) {
+            pl181_fifo_push(s, value);
+        }
+    }
+    s->status &= ~(PL181_STATUS_RX_FIFO | PL181_STATUS_TX_FIFO);
+    if (s->datacnt == 0) {
+        s->status |= PL181_STATUS_DATAEND;
+        /* HACK: */
+        s->status |= PL181_STATUS_DATABLOCKEND;
+        DPRINTF("Transfer Complete\n");
+    }
+    if (s->datacnt == 0 && s->fifocnt == 0) {
+        s->datactrl &= ~PL181_DATA_ENABLE;
+        DPRINTF("Data engine idle\n");
+    } else {
+        /* Update FIFO bits.  */
+        bits = PL181_STATUS_TXACTIVE | PL181_STATUS_RXACTIVE;
+        if (s->fifo_len == 0) {
+            bits |= PL181_STATUS_TXFIFOEMPTY;
+            bits |= PL181_STATUS_RXFIFOEMPTY;
+        } else {
+            bits |= PL181_STATUS_TXDATAAVLBL;
+            bits |= PL181_STATUS_RXDATAAVLBL;
+        }
+        if (s->fifo_len == 16) {
+            bits |= PL181_STATUS_TXFIFOFULL;
+            bits |= PL181_STATUS_RXFIFOFULL;
+        }
+        if (s->fifo_len <= 8) {
+            bits |= PL181_STATUS_TXFIFOHALFEMPTY;
+        }
+        if (s->fifo_len >= 8) {
+            bits |= PL181_STATUS_RXFIFOHALFFULL;
+        }
+        if (s->datactrl & PL181_DATA_DIRECTION) {
+            bits &= PL181_STATUS_RX_FIFO;
+        } else {
+            bits &= PL181_STATUS_TX_FIFO;
+        }
+        s->status |= bits;
+    }
+}
+
+static uint32_t pl181_read(void *opaque, target_phys_addr_t offset)
+{
+    pl181_state *s = (pl181_state *)opaque;
+
+    offset -= s->base;
+    if (offset >= 0xfe0 && offset < 0x1000) {
+        return pl181_id[(offset - 0xfe0) >> 2];
+    }
+    switch (offset) {
+    case 0x00: /* Power */
+        return s->power;
+    case 0x04: /* Clock */
+        return s->clock;
+    case 0x08: /* Argument */
+        return s->cmdarg;
+    case 0x0c: /* Command */
+        return s->cmd;
+    case 0x10: /* RespCmd */
+        return s->respcmd;
+    case 0x14: /* Response0 */
+        return s->response[0];
+    case 0x18: /* Response1 */
+        return s->response[1];
+    case 0x1c: /* Response2 */
+        return s->response[2];
+    case 0x20: /* Response3 */
+        return s->response[3];
+    case 0x24: /* DataTimer */
+        return s->datatimer;
+    case 0x28: /* DataLength */
+        return s->datalength;
+    case 0x2c: /* DataCtrl */
+        return s->datactrl;
+    case 0x30: /* DataCnt */
+        return s->datacnt;
+    case 0x34: /* Status */
+        return s->status;
+    case 0x3c: /* Mask0 */
+        return s->mask[0];
+    case 0x40: /* Mask1 */
+        return s->mask[1];
+    case 0x48: /* FifoCnt */
+        return s->fifocnt;
+    case 0x80: case 0x84: case 0x88: case 0x8c: /* FifoData */
+    case 0x90: case 0x94: case 0x98: case 0x9c:
+    case 0xa0: case 0xa4: case 0xa8: case 0xac:
+    case 0xb0: case 0xb4: case 0xb8: case 0xbc:
+        if (s->fifocnt == 0) {
+            fprintf(stderr, "pl181: Unexpected FIFO read\n");
+            return 0;
+        } else {
+            uint32_t value;
+            s->fifocnt--;
+            value = pl181_fifo_pop(s);
+            pl181_fifo_run(s);
+            pl181_update(s);
+            return value;
+        }
+    default:
+        cpu_abort (cpu_single_env, "pl181_read: Bad offset %x\n", offset);
+        return 0;
+    }
+}
+
+static void pl181_write(void *opaque, target_phys_addr_t offset,
+                          uint32_t value)
+{
+    pl181_state *s = (pl181_state *)opaque;
+
+    offset -= s->base;
+    switch (offset) {
+    case 0x00: /* Power */
+        s->power = value & 0xff;
+        break;
+    case 0x04: /* Clock */
+        s->clock = value & 0xff;
+        break;
+    case 0x08: /* Argument */
+        s->cmdarg = value;
+        break;
+    case 0x0c: /* Command */
+        s->cmd = value;
+        if (s->cmd & PL181_CMD_ENABLE) {
+            if (s->cmd & PL181_CMD_INTERRUPT) {
+                fprintf(stderr, "pl181: Interrupt mode not implemented\n");
+                abort();
+            } if (s->cmd & PL181_CMD_PENDING) {
+                fprintf(stderr, "pl181: Pending commands not implemented\n");
+                abort();
+            } else {
+                pl181_send_command(s);
+                pl181_fifo_run(s);
+            }
+            /* The command has completed one way or the other.  */
+            s->cmd &= ~PL181_CMD_ENABLE;
+        }
+        break;
+    case 0x24: /* DataTimer */
+        s->datatimer = value;
+        break;
+    case 0x28: /* DataLength */
+        s->datalength = value & 0xffff;
+        break;
+    case 0x2c: /* DataCtrl */
+        s->datactrl = value & 0xff;
+        if (value & PL181_DATA_ENABLE) {
+            s->datacnt = s->datalength;
+            s->fifocnt = (s->datalength + 3) >> 2;
+            pl181_fifo_run(s);
+        }
+        break;
+    case 0x38: /* Clear */
+        s->status &= ~(value & 0x7ff);
+        break;
+    case 0x3c: /* Mask0 */
+        s->mask[0] = value;
+        break;
+    case 0x40: /* Mask1 */
+        s->mask[1] = value;
+        break;
+    case 0x80: case 0x84: case 0x88: case 0x8c: /* FifoData */
+    case 0x90: case 0x94: case 0x98: case 0x9c:
+    case 0xa0: case 0xa4: case 0xa8: case 0xac:
+    case 0xb0: case 0xb4: case 0xb8: case 0xbc:
+        if (s->fifocnt == 0) {
+            fprintf(stderr, "pl181: Unexpected FIFO write\n");
+        } else {
+            s->fifocnt--;
+            pl181_fifo_push(s, value);
+            pl181_fifo_run(s);
+        }
+        break;
+    default:
+        cpu_abort (cpu_single_env, "pl181_write: Bad offset %x\n", offset);
+    }
+    pl181_update(s);
+}
+
+static CPUReadMemoryFunc *pl181_readfn[] = {
+   pl181_read,
+   pl181_read,
+   pl181_read
+};
+
+static CPUWriteMemoryFunc *pl181_writefn[] = {
+   pl181_write,
+   pl181_write,
+   pl181_write
+};
+
+static void pl181_reset(void *opaque)
+{
+    pl181_state *s = (pl181_state *)opaque;
+
+    s->power = 0;
+    s->cmdarg = 0;
+    s->cmd = 0;
+    s->datatimer = 0;
+    s->datalength = 0;
+    s->respcmd = 0;
+    s->response[0] = 0;
+    s->response[1] = 0;
+    s->response[2] = 0;
+    s->response[3] = 0;
+    s->datatimer = 0;
+    s->datalength = 0;
+    s->datactrl = 0;
+    s->datacnt = 0;
+    s->status = 0;
+    s->mask[0] = 0;
+    s->mask[1] = 0;
+    s->fifocnt = 0;
+}
+
+void pl181_init(uint32_t base, BlockDriverState *bd,
+                qemu_irq irq0, qemu_irq irq1)
+{
+    int iomemtype;
+    pl181_state *s;
+
+    s = (pl181_state *)qemu_mallocz(sizeof(pl181_state));
+    iomemtype = cpu_register_io_memory(0, pl181_readfn,
+                                       pl181_writefn, s);
+    cpu_register_physical_memory(base, 0x00000fff, iomemtype);
+    s->base = base;
+    s->card = sd_init(bd);
+    s->irq[0] = irq0;
+    s->irq[1] = irq1;
+    qemu_register_reset(pl181_reset, s);
+    pl181_reset(s);
+    /* ??? Save/restore.  */
+}

Modified: trunk/src/host/qemu-neo1973/hw/pl190.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pl190.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pl190.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -17,7 +17,6 @@
 #define PL190_NUM_PRIO 17
 
 typedef struct {
-    arm_pic_handler handler;
     uint32_t base;
     DisplayState *ds;
     uint32_t level;
@@ -33,9 +32,8 @@
     /* Current priority level.  */
     int priority;
     int prev_prio[PL190_NUM_PRIO];
-    void *parent;
-    int irq;
-    int fiq;
+    qemu_irq irq;
+    qemu_irq fiq;
 } pl190_state;
 
 static const unsigned char pl190_id[] =
@@ -53,9 +51,9 @@
     int set;
 
     set = (level & s->prio_mask[s->priority]) != 0;
-    pic_set_irq_new(s->parent, s->irq, set);
+    qemu_set_irq(s->irq, set);
     set = ((s->level | s->soft_level) & s->fiq_select) != 0;
-    pic_set_irq_new(s->parent, s->fiq, set);
+    qemu_set_irq(s->fiq, set);
 }
 
 static void pl190_set_irq(void *opaque, int irq, int level)
@@ -232,21 +230,21 @@
   pl190_update_vectors(s);
 }
 
-void *pl190_init(uint32_t base, void *parent, int irq, int fiq)
+qemu_irq *pl190_init(uint32_t base, qemu_irq irq, qemu_irq fiq)
 {
     pl190_state *s;
+    qemu_irq *qi;
     int iomemtype;
 
     s = (pl190_state *)qemu_mallocz(sizeof(pl190_state));
     iomemtype = cpu_register_io_memory(0, pl190_readfn,
                                        pl190_writefn, s);
     cpu_register_physical_memory(base, 0x00000fff, iomemtype);
-    s->handler = pl190_set_irq;
+    qi = qemu_allocate_irqs(pl190_set_irq, s, 32);
     s->base = base;
-    s->parent = parent;
     s->irq = irq;
     s->fiq = fiq;
     pl190_reset(s);
     /* ??? Save/restore.  */
-    return s;
+    return qi;
 }

Modified: trunk/src/host/qemu-neo1973/hw/ppc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/ppc.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /*
- * QEMU generic PPC hardware System Emulator
+ * QEMU generic PowerPC hardware System Emulator
  * 
- * Copyright (c) 2003-2004 Jocelyn Mayer
+ * Copyright (c) 2003-2007 Jocelyn Mayer
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -24,10 +24,387 @@
 #include "vl.h"
 #include "m48t59.h"
 
+//#define PPC_DEBUG_IRQ
+//#define PPC_DEBUG_TB
+
+extern FILE *logfile;
+extern int loglevel;
+
+void ppc_set_irq (CPUState *env, int n_IRQ, int level)
+{
+    if (level) {
+        env->pending_interrupts |= 1 << n_IRQ;
+        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    } else {
+        env->pending_interrupts &= ~(1 << n_IRQ);
+        if (env->pending_interrupts == 0)
+            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+#if defined(PPC_DEBUG_IRQ)
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: %p n_IRQ %d level %d => pending %08x req %08x\n",
+                __func__, env, n_IRQ, level,
+                env->pending_interrupts, env->interrupt_request);
+    }
+#endif
+}
+
+/* PowerPC 6xx / 7xx internal IRQ controller */
+static void ppc6xx_set_irq (void *opaque, int pin, int level)
+{
+    CPUState *env = opaque;
+    int cur_level;
+
+#if defined(PPC_DEBUG_IRQ)
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
+                env, pin, level);
+    }
+#endif
+    cur_level = (env->irq_input_state >> pin) & 1;
+    /* Don't generate spurious events */
+    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        switch (pin) {
+        case PPC6xx_INPUT_INT:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the external IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
+            break;
+        case PPC6xx_INPUT_SMI:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the SMI IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_SMI, level);
+            break;
+        case PPC6xx_INPUT_MCP:
+            /* Negative edge sensitive */
+            /* XXX: TODO: actual reaction may depends on HID0 status
+             *            603/604/740/750: check HID0[EMCP]
+             */
+            if (cur_level == 1 && level == 0) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: raise machine check state\n",
+                            __func__);
+                }
+#endif
+                ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
+            }
+            break;
+        case PPC6xx_INPUT_CKSTP_IN:
+            /* Level sensitive - active low */
+            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
+            if (level) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: stop the CPU\n", __func__);
+                }
+#endif
+                env->halted = 1;
+            } else {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: restart the CPU\n", __func__);
+                }
+#endif
+                env->halted = 0;
+            }
+            break;
+        case PPC6xx_INPUT_HRESET:
+            /* Level sensitive - active low */
+            if (level) {
+#if 0 // XXX: TOFIX
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: reset the CPU\n", __func__);
+                }
+#endif
+                cpu_reset(env);
+#endif
+            }
+            break;
+        case PPC6xx_INPUT_SRESET:
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the RESET IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
+            break;
+        default:
+            /* Unknown pin - do nothing */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
+            }
+#endif
+            return;
+        }
+        if (level)
+            env->irq_input_state |= 1 << pin;
+        else
+            env->irq_input_state &= ~(1 << pin);
+    }
+}
+
+void ppc6xx_irq_init (CPUState *env)
+{
+    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env, 6);
+}
+
+/* PowerPC 970 internal IRQ controller */
+static void ppc970_set_irq (void *opaque, int pin, int level)
+{
+    CPUState *env = opaque;
+    int cur_level;
+
+#if defined(PPC_DEBUG_IRQ)
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
+                env, pin, level);
+    }
+#endif
+    cur_level = (env->irq_input_state >> pin) & 1;
+    /* Don't generate spurious events */
+    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        switch (pin) {
+        case PPC970_INPUT_INT:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the external IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
+            break;
+        case PPC970_INPUT_THINT:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the SMI IRQ state to %d\n", __func__,
+                        level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_THERM, level);
+            break;
+        case PPC970_INPUT_MCP:
+            /* Negative edge sensitive */
+            /* XXX: TODO: actual reaction may depends on HID0 status
+             *            603/604/740/750: check HID0[EMCP]
+             */
+            if (cur_level == 1 && level == 0) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: raise machine check state\n",
+                            __func__);
+                }
+#endif
+                ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
+            }
+            break;
+        case PPC970_INPUT_CKSTP:
+            /* Level sensitive - active low */
+            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
+            if (level) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: stop the CPU\n", __func__);
+                }
+#endif
+                env->halted = 1;
+            } else {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: restart the CPU\n", __func__);
+                }
+#endif
+                env->halted = 0;
+            }
+            break;
+        case PPC970_INPUT_HRESET:
+            /* Level sensitive - active low */
+            if (level) {
+#if 0 // XXX: TOFIX
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: reset the CPU\n", __func__);
+                }
+#endif
+                cpu_reset(env);
+#endif
+            }
+            break;
+        case PPC970_INPUT_SRESET:
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the RESET IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
+            break;
+        case PPC970_INPUT_TBEN:
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the TBEN state to %d\n", __func__,
+                        level);
+            }
+#endif
+            /* XXX: TODO */
+            break;
+        default:
+            /* Unknown pin - do nothing */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
+            }
+#endif
+            return;
+        }
+        if (level)
+            env->irq_input_state |= 1 << pin;
+        else
+            env->irq_input_state &= ~(1 << pin);
+    }
+}
+
+void ppc970_irq_init (CPUState *env)
+{
+    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env, 7);
+}
+
+/* PowerPC 405 internal IRQ controller */
+static void ppc405_set_irq (void *opaque, int pin, int level)
+{
+    CPUState *env = opaque;
+    int cur_level;
+
+#if defined(PPC_DEBUG_IRQ)
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
+                env, pin, level);
+    }
+#endif
+    cur_level = (env->irq_input_state >> pin) & 1;
+    /* Don't generate spurious events */
+    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        switch (pin) {
+        case PPC405_INPUT_RESET_SYS:
+            if (level) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: reset the PowerPC system\n",
+                            __func__);
+                }
+#endif
+                ppc40x_system_reset(env);
+            }
+            break;
+        case PPC405_INPUT_RESET_CHIP:
+            if (level) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: reset the PowerPC chip\n", __func__);
+                }
+#endif
+                ppc40x_chip_reset(env);
+            }
+            break;
+            /* No break here */
+        case PPC405_INPUT_RESET_CORE:
+            /* XXX: TODO: update DBSR[MRR] */
+            if (level) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: reset the PowerPC core\n", __func__);
+                }
+#endif
+                ppc40x_core_reset(env);
+            }
+            break;
+        case PPC405_INPUT_CINT:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the critical IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            /* XXX: TOFIX */
+            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
+            break;
+        case PPC405_INPUT_INT:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the external IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
+            break;
+        case PPC405_INPUT_HALT:
+            /* Level sensitive - active low */
+            if (level) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: stop the CPU\n", __func__);
+                }
+#endif
+                env->halted = 1;
+            } else {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: restart the CPU\n", __func__);
+                }
+#endif
+                env->halted = 0;
+            }
+            break;
+        case PPC405_INPUT_DEBUG:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the external IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, EXCP_40x_DEBUG, level);
+            break;
+        default:
+            /* Unknown pin - do nothing */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
+            }
+#endif
+            return;
+        }
+        if (level)
+            env->irq_input_state |= 1 << pin;
+        else
+            env->irq_input_state &= ~(1 << pin);
+    }
+}
+
+void ppc405_irq_init (CPUState *env)
+{
+    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc405_set_irq, env, 7);
+}
+
 /*****************************************************************************/
-/* PPC time base and decrementer emulation */
-//#define DEBUG_TB
-
+/* PowerPC time base and decrementer emulation */
 struct ppc_tb_t {
     /* Time base management */
     int64_t  tb_offset;    /* Compensation               */
@@ -35,13 +412,14 @@
     /* Decrementer management */
     uint64_t decr_next;    /* Tick for next decr interrupt  */
     struct QEMUTimer *decr_timer;
+    void *opaque;
 };
 
 static inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env)
 {
     /* TB time in tb periods */
     return muldiv64(qemu_get_clock(vm_clock) + tb_env->tb_offset,
-		    tb_env->tb_freq, ticks_per_sec);
+                    tb_env->tb_freq, ticks_per_sec);
 }
 
 uint32_t cpu_ppc_load_tbl (CPUState *env)
@@ -50,16 +428,18 @@
     uint64_t tb;
 
     tb = cpu_ppc_get_tb(tb_env);
-#ifdef DEBUG_TB
+#ifdef PPC_DEBUG_TB
     {
-         static int last_time;
-	 int now;
-	 now = time(NULL);
-	 if (last_time != now) {
-	     last_time = now;
-	     printf("%s: tb=0x%016lx %d %08lx\n",
-                    __func__, tb, now, tb_env->tb_offset);
-	 }
+        static int last_time;
+        int now;
+        now = time(NULL);
+        if (last_time != now) {
+            last_time = now;
+            if (loglevel != 0) {
+                fprintf(logfile, "%s: tb=0x%016lx %d %08lx\n",
+                        __func__, tb, now, tb_env->tb_offset);
+            }
+        }
     }
 #endif
 
@@ -72,9 +452,12 @@
     uint64_t tb;
 
     tb = cpu_ppc_get_tb(tb_env);
-#ifdef DEBUG_TB
-    printf("%s: tb=0x%016lx\n", __func__, tb);
+#if defined(PPC_DEBUG_TB)
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
+    }
 #endif
+
     return tb >> 32;
 }
 
@@ -82,8 +465,11 @@
 {
     tb_env->tb_offset = muldiv64(value, ticks_per_sec, tb_env->tb_freq)
         - qemu_get_clock(vm_clock);
-#ifdef DEBUG_TB
-    printf("%s: tb=0x%016lx offset=%08x\n", __func__, value);
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: tb=0x%016lx offset=%08lx\n", __func__, value,
+                tb_env->tb_offset);
+    }
 #endif
 }
 
@@ -114,9 +500,12 @@
         decr = muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
     else
         decr = -muldiv64(-diff, tb_env->tb_freq, ticks_per_sec);
-#if defined(DEBUG_TB)
-    printf("%s: 0x%08x\n", __func__, decr);
+#if defined(PPC_DEBUG_TB)
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: 0x%08x\n", __func__, decr);
+    }
 #endif
+
     return decr;
 }
 
@@ -126,10 +515,12 @@
 static inline void cpu_ppc_decr_excp (CPUState *env)
 {
     /* Raise it */
-#ifdef DEBUG_TB
-    printf("raise decrementer exception\n");
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "raise decrementer exception\n");
+    }
 #endif
-    cpu_interrupt(env, CPU_INTERRUPT_TIMER);
+    ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
 }
 
 static void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
@@ -138,15 +529,17 @@
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t now, next;
 
-#ifdef DEBUG_TB
-    printf("%s: 0x%08x => 0x%08x\n", __func__, decr, value);
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: 0x%08x => 0x%08x\n", __func__, decr, value);
+    }
 #endif
     now = qemu_get_clock(vm_clock);
     next = now + muldiv64(value, ticks_per_sec, tb_env->tb_freq);
     if (is_excp)
         next += tb_env->decr_next - now;
     if (next == now)
-	next++;
+        next++;
     tb_env->decr_next = next;
     /* Adjust timer */
     qemu_mod_timer(tb_env->decr_timer, next);
@@ -154,7 +547,7 @@
      * raise an exception.
      */
     if ((value & 0x80000000) && !(decr & 0x80000000))
-	cpu_ppc_decr_excp(env);
+        cpu_ppc_decr_excp(env);
 }
 
 void cpu_ppc_store_decr (CPUState *env, uint32_t value)
@@ -167,8 +560,21 @@
     _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
 }
 
+static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
+{
+    CPUState *env = opaque;
+    ppc_tb_t *tb_env = env->tb_env;
+
+    tb_env->tb_freq = freq;
+    /* There is a bug in Linux 2.4 kernels:
+     * if a decrementer exception is pending when it enables msr_ee at startup,
+     * it's not ready to handle it...
+     */
+    _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
+}
+
 /* Set up (once) timebase frequency (in Hz) */
-ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq)
+clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq)
 {
     ppc_tb_t *tb_env;
 
@@ -176,21 +582,414 @@
     if (tb_env == NULL)
         return NULL;
     env->tb_env = tb_env;
-    if (tb_env->tb_freq == 0 || 1) {
-	tb_env->tb_freq = freq;
-	/* Create new timer */
-	tb_env->decr_timer =
-            qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
-	/* There is a bug in  2.4 kernels:
-	 * if a decrementer exception is pending when it enables msr_ee,
-	 * it's not ready to handle it...
-	 */
-	_cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
+    /* Create new timer */
+    tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
+    cpu_ppc_set_tb_clk(env, freq);
+
+    return &cpu_ppc_set_tb_clk;
+}
+
+/* Specific helpers for POWER & PowerPC 601 RTC */
+clk_setup_cb cpu_ppc601_rtc_init (CPUState *env)
+{
+    return cpu_ppc_tb_init(env, 7812500);
+}
+
+void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
+__attribute__ (( alias ("cpu_ppc_store_tbu") ));
+
+uint32_t cpu_ppc601_load_rtcu (CPUState *env)
+__attribute__ (( alias ("cpu_ppc_load_tbu") ));
+
+void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
+{
+    cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
+}
+
+uint32_t cpu_ppc601_load_rtcl (CPUState *env)
+{
+    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
+}
+
+/*****************************************************************************/
+/* Embedded PowerPC timers */
+
+/* PIT, FIT & WDT */
+typedef struct ppcemb_timer_t ppcemb_timer_t;
+struct ppcemb_timer_t {
+    uint64_t pit_reload;  /* PIT auto-reload value        */
+    uint64_t fit_next;    /* Tick for next FIT interrupt  */
+    struct QEMUTimer *fit_timer;
+    uint64_t wdt_next;    /* Tick for next WDT interrupt  */
+    struct QEMUTimer *wdt_timer;
+};
+   
+/* Fixed interval timer */
+static void cpu_4xx_fit_cb (void *opaque)
+{
+    CPUState *env;
+    ppc_tb_t *tb_env;
+    ppcemb_timer_t *ppcemb_timer;
+    uint64_t now, next;
+
+    env = opaque;
+    tb_env = env->tb_env;
+    ppcemb_timer = tb_env->opaque;
+    now = qemu_get_clock(vm_clock);
+    switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
+    case 0:
+        next = 1 << 9;
+        break;
+    case 1:
+        next = 1 << 13;
+        break;
+    case 2:
+        next = 1 << 17;
+        break;
+    case 3:
+        next = 1 << 21;
+        break;
+    default:
+        /* Cannot occur, but makes gcc happy */
+        return;
     }
+    next = now + muldiv64(next, ticks_per_sec, tb_env->tb_freq);
+    if (next == now)
+        next++;
+    qemu_mod_timer(ppcemb_timer->fit_timer, next);
+    env->spr[SPR_40x_TSR] |= 1 << 26;
+    if ((env->spr[SPR_40x_TCR] >> 23) & 0x1)
+        ppc_set_irq(env, PPC_INTERRUPT_FIT, 1);
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: ir %d TCR " ADDRX " TSR " ADDRX "\n", __func__,
+                (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
+                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
+    }
+#endif
+}
 
-    return tb_env;
+/* Programmable interval timer */
+static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp)
+{
+    ppcemb_timer_t *ppcemb_timer;
+    uint64_t now, next;
+
+    ppcemb_timer = tb_env->opaque;
+    if (ppcemb_timer->pit_reload <= 1 ||
+        !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
+        (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
+        /* Stop PIT */
+#ifdef PPC_DEBUG_TB
+        if (loglevel != 0) {
+            fprintf(logfile, "%s: stop PIT\n", __func__);
+        }
+#endif
+        qemu_del_timer(tb_env->decr_timer);
+    } else {
+#ifdef PPC_DEBUG_TB
+        if (loglevel != 0) {
+            fprintf(logfile, "%s: start PIT 0x" REGX "\n",
+                    __func__, ppcemb_timer->pit_reload);
+        }
+#endif
+        now = qemu_get_clock(vm_clock);
+        next = now + muldiv64(ppcemb_timer->pit_reload,
+                              ticks_per_sec, tb_env->tb_freq);
+        if (is_excp)
+            next += tb_env->decr_next - now;
+        if (next == now)
+            next++;
+        qemu_mod_timer(tb_env->decr_timer, next);
+        tb_env->decr_next = next;
+    }
 }
 
+static void cpu_4xx_pit_cb (void *opaque)
+{
+    CPUState *env;
+    ppc_tb_t *tb_env;
+    ppcemb_timer_t *ppcemb_timer;
+
+    env = opaque;
+    tb_env = env->tb_env;
+    ppcemb_timer = tb_env->opaque;
+    env->spr[SPR_40x_TSR] |= 1 << 27;
+    if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
+        ppc_set_irq(env, PPC_INTERRUPT_PIT, 1);
+    start_stop_pit(env, tb_env, 1);
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: ar %d ir %d TCR " ADDRX " TSR " ADDRX " "
+                "%016" PRIx64 "\n", __func__,
+                (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
+                (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
+                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
+                ppcemb_timer->pit_reload);
+    }
+#endif
+}
+
+/* Watchdog timer */
+static void cpu_4xx_wdt_cb (void *opaque)
+{
+    CPUState *env;
+    ppc_tb_t *tb_env;
+    ppcemb_timer_t *ppcemb_timer;
+    uint64_t now, next;
+
+    env = opaque;
+    tb_env = env->tb_env;
+    ppcemb_timer = tb_env->opaque;
+    now = qemu_get_clock(vm_clock);
+    switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
+    case 0:
+        next = 1 << 17;
+        break;
+    case 1:
+        next = 1 << 21;
+        break;
+    case 2:
+        next = 1 << 25;
+        break;
+    case 3:
+        next = 1 << 29;
+        break;
+    default:
+        /* Cannot occur, but makes gcc happy */
+        return;
+    }
+    next = now + muldiv64(next, ticks_per_sec, tb_env->tb_freq);
+    if (next == now)
+        next++;
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: TCR " ADDRX " TSR " ADDRX "\n", __func__,
+                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
+    }
+#endif
+    switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
+    case 0x0:
+    case 0x1:
+        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
+        ppcemb_timer->wdt_next = next;
+        env->spr[SPR_40x_TSR] |= 1 << 31;
+        break;
+    case 0x2:
+        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
+        ppcemb_timer->wdt_next = next;
+        env->spr[SPR_40x_TSR] |= 1 << 30;
+        if ((env->spr[SPR_40x_TCR] >> 27) & 0x1)
+            ppc_set_irq(env, PPC_INTERRUPT_WDT, 1);
+        break;
+    case 0x3:
+        env->spr[SPR_40x_TSR] &= ~0x30000000;
+        env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000;
+        switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) {
+        case 0x0:
+            /* No reset */
+            break;
+        case 0x1: /* Core reset */
+            ppc40x_core_reset(env);
+            break;
+        case 0x2: /* Chip reset */
+            ppc40x_chip_reset(env);
+            break;
+        case 0x3: /* System reset */
+            ppc40x_system_reset(env);
+            break;
+        }
+    }
+}
+
+void store_40x_pit (CPUState *env, target_ulong val)
+{
+    ppc_tb_t *tb_env;
+    ppcemb_timer_t *ppcemb_timer;
+
+    tb_env = env->tb_env;
+    ppcemb_timer = tb_env->opaque;
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s %p %p\n", __func__, tb_env, ppcemb_timer);
+    }
+#endif
+    ppcemb_timer->pit_reload = val;
+    start_stop_pit(env, tb_env, 0);
+}
+
+target_ulong load_40x_pit (CPUState *env)
+{
+    return cpu_ppc_load_decr(env);
+}
+
+void store_booke_tsr (CPUState *env, target_ulong val)
+{
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: val=" ADDRX "\n", __func__, val);
+    }
+#endif
+    env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);
+    if (val & 0x80000000)
+        ppc_set_irq(env, PPC_INTERRUPT_PIT, 0);
+}
+
+void store_booke_tcr (CPUState *env, target_ulong val)
+{
+    ppc_tb_t *tb_env;
+
+    tb_env = env->tb_env;
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: val=" ADDRX "\n", __func__, val);
+    }
+#endif
+    env->spr[SPR_40x_TCR] = val & 0xFFC00000;
+    start_stop_pit(env, tb_env, 1);
+    cpu_4xx_wdt_cb(env);
+}
+
+static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq)
+{
+    CPUState *env = opaque;
+    ppc_tb_t *tb_env = env->tb_env;
+
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s set new frequency to %u\n", __func__, freq);
+    }
+#endif
+    tb_env->tb_freq = freq;
+    /* XXX: we should also update all timers */
+}
+
+clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
+{
+    ppc_tb_t *tb_env;
+    ppcemb_timer_t *ppcemb_timer;
+
+    tb_env = qemu_mallocz(sizeof(ppc_tb_t));
+    if (tb_env == NULL) {
+        return NULL;
+    }
+    env->tb_env = tb_env;
+    ppcemb_timer = qemu_mallocz(sizeof(ppcemb_timer_t));
+    tb_env->tb_freq = freq;
+    tb_env->opaque = ppcemb_timer;
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s %p %p %p\n", __func__, tb_env, ppcemb_timer,
+                &ppc_emb_set_tb_clk);
+    }
+#endif
+    if (ppcemb_timer != NULL) {
+        /* We use decr timer for PIT */
+        tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_4xx_pit_cb, env);
+        ppcemb_timer->fit_timer =
+            qemu_new_timer(vm_clock, &cpu_4xx_fit_cb, env);
+        ppcemb_timer->wdt_timer =
+            qemu_new_timer(vm_clock, &cpu_4xx_wdt_cb, env);
+    }
+
+    return &ppc_emb_set_tb_clk;
+}
+
+/*****************************************************************************/
+/* Embedded PowerPC Device Control Registers */
+typedef struct ppc_dcrn_t ppc_dcrn_t;
+struct ppc_dcrn_t {
+    dcr_read_cb dcr_read;
+    dcr_write_cb dcr_write;
+    void *opaque;
+};
+
+#define DCRN_NB 1024
+struct ppc_dcr_t {
+    ppc_dcrn_t dcrn[DCRN_NB];
+    int (*read_error)(int dcrn);
+    int (*write_error)(int dcrn);
+};
+
+int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
+{
+    ppc_dcrn_t *dcr;
+
+    if (dcrn < 0 || dcrn >= DCRN_NB)
+        goto error;
+    dcr = &dcr_env->dcrn[dcrn];
+    if (dcr->dcr_read == NULL)
+        goto error;
+    *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
+
+    return 0;
+
+ error:
+    if (dcr_env->read_error != NULL)
+        return (*dcr_env->read_error)(dcrn);
+
+    return -1;
+}
+
+int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
+{
+    ppc_dcrn_t *dcr;
+
+    if (dcrn < 0 || dcrn >= DCRN_NB)
+        goto error;
+    dcr = &dcr_env->dcrn[dcrn];
+    if (dcr->dcr_write == NULL)
+        goto error;
+    (*dcr->dcr_write)(dcr->opaque, dcrn, val);
+
+    return 0;
+
+ error:
+    if (dcr_env->write_error != NULL)
+        return (*dcr_env->write_error)(dcrn);
+
+    return -1;
+}
+
+int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
+                      dcr_read_cb dcr_read, dcr_write_cb dcr_write)
+{
+    ppc_dcr_t *dcr_env;
+    ppc_dcrn_t *dcr;
+
+    dcr_env = env->dcr_env;
+    if (dcr_env == NULL)
+        return -1;
+    if (dcrn < 0 || dcrn >= DCRN_NB)
+        return -1;
+    dcr = &dcr_env->dcrn[dcrn];
+    if (dcr->opaque != NULL ||
+        dcr->dcr_read != NULL ||
+        dcr->dcr_write != NULL)
+        return -1;
+    dcr->opaque = opaque;
+    dcr->dcr_read = dcr_read;
+    dcr->dcr_write = dcr_write;
+
+    return 0;
+}
+
+int ppc_dcr_init (CPUState *env, int (*read_error)(int dcrn),
+                  int (*write_error)(int dcrn))
+{
+    ppc_dcr_t *dcr_env;
+
+    dcr_env = qemu_mallocz(sizeof(ppc_dcr_t));
+    if (dcr_env == NULL)
+        return -1;
+    dcr_env->read_error = read_error;
+    dcr_env->write_error = write_error;
+    env->dcr_env = dcr_env;
+
+    return 0;
+}
+
+
 #if 0
 /*****************************************************************************/
 /* Handle system reset (for now, just stop emulation) */
@@ -264,6 +1063,7 @@
     tmp |= m48t59_read(nvram, addr + 1) << 16;
     tmp |= m48t59_read(nvram, addr + 2) << 8;
     tmp |= m48t59_read(nvram, addr + 3);
+
     return tmp;
 }
 
@@ -316,10 +1116,10 @@
     odd = count & 1;
     count &= ~1;
     for (i = 0; i != count; i++) {
-	crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
+        crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
     }
     if (odd) {
-	crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
+        crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
     }
 
     return crc;

Added: trunk/src/host/qemu-neo1973/hw/ppc405.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc405.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/ppc405.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,122 @@
+/*
+ * QEMU PowerPC 405 shared definitions
+ * 
+ * Copyright (c) 2007 Jocelyn Mayer
+ * 
+ * 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.
+ */
+
+#if !defined(PPC_405_H)
+#define PPC_405_H
+
+/* Bootinfo as set-up by u-boot */
+typedef struct ppc4xx_bd_info_t ppc4xx_bd_info_t;
+struct ppc4xx_bd_info_t {
+    uint32_t bi_memstart;
+    uint32_t bi_memsize;
+    uint32_t bi_flashstart;
+    uint32_t bi_flashsize;
+    uint32_t bi_flashoffset; /* 0x10 */
+    uint32_t bi_sramstart;
+    uint32_t bi_sramsize;
+    uint32_t bi_bootflags;
+    uint32_t bi_ipaddr; /* 0x20 */
+    uint8_t  bi_enetaddr[6];
+    uint16_t bi_ethspeed;
+    uint32_t bi_intfreq;
+    uint32_t bi_busfreq; /* 0x30 */
+    uint32_t bi_baudrate;
+    uint8_t  bi_s_version[4];
+    uint8_t  bi_r_version[32];
+    uint32_t bi_procfreq;
+    uint32_t bi_plb_busfreq;
+    uint32_t bi_pci_busfreq;
+    uint8_t  bi_pci_enetaddr[6];
+    uint32_t bi_pci_enetaddr2[6];
+    uint32_t bi_opbfreq;
+    uint32_t bi_iic_fast[2];
+};
+
+/* PowerPC 405 core */
+CPUState *ppc405_init (const unsigned char *cpu_model,
+                       clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
+                       uint32_t sysclk);
+ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd);
+
+/* */
+typedef struct ppc4xx_mmio_t ppc4xx_mmio_t;
+int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio,
+                          target_phys_addr_t offset, uint32_t len,
+                          CPUReadMemoryFunc **mem_read,
+                          CPUWriteMemoryFunc **mem_write, void *opaque);
+ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base);
+/* PowerPC 4xx peripheral local bus arbitrer */
+void ppc4xx_plb_init (CPUState *env);
+/* PLB to OPB bridge */
+void ppc4xx_pob_init (CPUState *env);
+/* OPB arbitrer */
+void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                       target_phys_addr_t offset);
+/* PowerPC 4xx universal interrupt controller */
+enum {
+    PPCUIC_OUTPUT_INT = 0,
+    PPCUIC_OUTPUT_CINT = 1,
+    PPCUIC_OUTPUT_NB,
+};
+qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
+                       uint32_t dcr_base, int has_ssr, int has_vr);
+/* SDRAM controller */
+void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
+                        target_ulong *ram_bases, target_ulong *ram_sizes,
+                        int do_init);
+/* Peripheral controller */
+void ppc405_ebc_init (CPUState *env);
+/* DMA controller */
+void ppc405_dma_init (CPUState *env, qemu_irq irqs[4]);
+/* GPIO */
+void ppc405_gpio_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                       target_phys_addr_t offset);
+/* Serial ports */
+void ppc405_serial_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                         target_phys_addr_t offset, qemu_irq irq,
+                         CharDriverState *chr);
+/* On Chip Memory */
+void ppc405_ocm_init (CPUState *env, unsigned long offset);
+/* I2C controller */
+void ppc405_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                      target_phys_addr_t offset, qemu_irq irq);
+/* General purpose timers */
+void ppc4xx_gpt_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                      target_phys_addr_t offset, qemu_irq irq[5]);
+/* Memory access layer */
+void ppc405_mal_init (CPUState *env, qemu_irq irqs[4]);
+/* PowerPC 405 microcontrollers */
+CPUState *ppc405cr_init (target_ulong ram_bases[4], target_ulong ram_sizes[4],
+                         uint32_t sysclk, qemu_irq **picp,
+                         ram_addr_t *offsetp, int do_init);
+CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2],
+                         uint32_t sysclk, qemu_irq **picp,
+                         ram_addr_t *offsetp, int do_init);
+/* IBM STBxxx microcontrollers */
+CPUState *ppc_stb025_init (target_ulong ram_bases[2],
+                           target_ulong ram_sizes[2],
+                           uint32_t sysclk, qemu_irq **picp,
+                           ram_addr_t *offsetp);
+
+#endif /* !defined(PPC_405_H) */

Added: trunk/src/host/qemu-neo1973/hw/ppc405_boards.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc405_boards.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/ppc405_boards.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,630 @@
+/*
+ * QEMU PowerPC 405 evaluation boards emulation
+ * 
+ * Copyright (c) 2007 Jocelyn Mayer
+ * 
+ * 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"
+#include "ppc405.h"
+
+extern int loglevel;
+extern FILE *logfile;
+
+#define BIOS_FILENAME "ppc405_rom.bin"
+#undef BIOS_SIZE
+#define BIOS_SIZE (2048 * 1024)
+
+#define KERNEL_LOAD_ADDR 0x00000000
+#define INITRD_LOAD_ADDR 0x01800000
+
+#define USE_FLASH_BIOS
+
+#define DEBUG_BOARD_INIT
+
+/*****************************************************************************/
+/* PPC405EP reference board (IBM) */
+/* Standalone board with:
+ * - PowerPC 405EP CPU
+ * - SDRAM (0x00000000)
+ * - Flash (0xFFF80000)
+ * - SRAM  (0xFFF00000)
+ * - NVRAM (0xF0000000)
+ * - FPGA  (0xF0300000)
+ */
+typedef struct ref405ep_fpga_t ref405ep_fpga_t;
+struct ref405ep_fpga_t {
+    uint32_t base;
+    uint8_t reg0;
+    uint8_t reg1;
+};
+
+static uint32_t ref405ep_fpga_readb (void *opaque, target_phys_addr_t addr)
+{
+    ref405ep_fpga_t *fpga;
+    uint32_t ret;
+
+    fpga = opaque;
+    addr -= fpga->base;
+    switch (addr) {
+    case 0x0:
+        ret = fpga->reg0;
+        break;
+    case 0x1:
+        ret = fpga->reg1;
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void ref405ep_fpga_writeb (void *opaque,
+                                  target_phys_addr_t addr, uint32_t value)
+{
+    ref405ep_fpga_t *fpga;
+
+    fpga = opaque;
+    addr -= fpga->base;
+    switch (addr) {
+    case 0x0:
+        /* Read only */
+        break;
+    case 0x1:
+        fpga->reg1 = value;
+        break;
+    default:
+        break;
+    }
+}
+
+static uint32_t ref405ep_fpga_readw (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t ret;
+
+    ret = ref405ep_fpga_readb(opaque, addr) << 8;
+    ret |= ref405ep_fpga_readb(opaque, addr + 1);
+
+    return ret;
+}
+
+static void ref405ep_fpga_writew (void *opaque,
+                                  target_phys_addr_t addr, uint32_t value)
+{
+    ref405ep_fpga_writeb(opaque, addr, (value >> 8) & 0xFF);
+    ref405ep_fpga_writeb(opaque, addr + 1, value & 0xFF);
+}
+
+static uint32_t ref405ep_fpga_readl (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t ret;
+
+    ret = ref405ep_fpga_readb(opaque, addr) << 24;
+    ret |= ref405ep_fpga_readb(opaque, addr + 1) << 16;
+    ret |= ref405ep_fpga_readb(opaque, addr + 2) << 8;
+    ret |= ref405ep_fpga_readb(opaque, addr + 3);
+
+    return ret;
+}
+
+static void ref405ep_fpga_writel (void *opaque,
+                                  target_phys_addr_t addr, uint32_t value)
+{
+    ref405ep_fpga_writel(opaque, addr, (value >> 24) & 0xFF);
+    ref405ep_fpga_writel(opaque, addr + 1, (value >> 16) & 0xFF);
+    ref405ep_fpga_writel(opaque, addr + 2, (value >> 8) & 0xFF);
+    ref405ep_fpga_writeb(opaque, addr + 3, value & 0xFF);
+}
+
+static CPUReadMemoryFunc *ref405ep_fpga_read[] = {
+    &ref405ep_fpga_readb,
+    &ref405ep_fpga_readw,
+    &ref405ep_fpga_readl,
+};
+
+static CPUWriteMemoryFunc *ref405ep_fpga_write[] = {
+    &ref405ep_fpga_writeb,
+    &ref405ep_fpga_writew,
+    &ref405ep_fpga_writel,
+};
+
+static void ref405ep_fpga_reset (void *opaque)
+{
+    ref405ep_fpga_t *fpga;
+
+    fpga = opaque;
+    fpga->reg0 = 0x00;
+    fpga->reg1 = 0x0F;
+}
+
+static void ref405ep_fpga_init (uint32_t base)
+{
+    ref405ep_fpga_t *fpga;
+    int fpga_memory;
+
+    fpga = qemu_mallocz(sizeof(ref405ep_fpga_t));
+    if (fpga != NULL) {
+        fpga->base = base;
+        fpga_memory = cpu_register_io_memory(0, ref405ep_fpga_read,
+                                             ref405ep_fpga_write, fpga);
+        cpu_register_physical_memory(base, 0x00000100, fpga_memory);
+        ref405ep_fpga_reset(fpga);
+        qemu_register_reset(&ref405ep_fpga_reset, fpga);
+    }
+}
+
+static void ref405ep_init (int ram_size, int vga_ram_size, int boot_device,
+                           DisplayState *ds, const char **fd_filename, 
+                           int snapshot,
+                           const char *kernel_filename, 
+                           const char *kernel_cmdline,
+                           const char *initrd_filename,
+                           const char *cpu_model)
+{
+    char buf[1024];
+    ppc4xx_bd_info_t bd;
+    CPUPPCState *env;
+    qemu_irq *pic;
+    ram_addr_t sram_offset, bios_offset, bdloc;
+    target_ulong ram_bases[2], ram_sizes[2];
+    target_ulong sram_size, bios_size;
+    //int phy_addr = 0;
+    //static int phy_addr = 1;
+    target_ulong kernel_base, kernel_size, initrd_base, initrd_size;
+    int linux_boot;
+    int fl_idx, fl_sectors, len;
+
+    /* XXX: fix this */
+    ram_bases[0] = 0x00000000;
+    ram_sizes[0] = 0x08000000;
+    ram_bases[1] = 0x00000000;
+    ram_sizes[1] = 0x00000000;
+    ram_size = 128 * 1024 * 1024;
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register cpu\n", __func__);
+#endif
+    env = ppc405ep_init(ram_bases, ram_sizes, 33333333, &pic, &sram_offset,
+                        kernel_filename == NULL ? 0 : 1);
+    /* allocate SRAM */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register SRAM at offset %08lx\n", __func__, sram_offset);
+#endif
+    sram_size = 512 * 1024;
+    cpu_register_physical_memory(0xFFF00000, sram_size,
+                                 sram_offset | IO_MEM_RAM);
+    /* allocate and load BIOS */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register BIOS\n", __func__);
+#endif
+    bios_offset = sram_offset + sram_size;
+    fl_idx = 0;
+#ifdef USE_FLASH_BIOS
+    if (pflash_table[fl_idx] != NULL) {
+        bios_size = bdrv_getlength(pflash_table[fl_idx]);
+        fl_sectors = (bios_size + 65535) >> 16;
+#ifdef DEBUG_BOARD_INIT
+        printf("Register parallel flash %d size " ADDRX " at offset %08lx "
+               " addr " ADDRX " '%s' %d\n",
+               fl_idx, bios_size, bios_offset, -bios_size,
+               bdrv_get_device_name(pflash_table[fl_idx]), fl_sectors);
+#endif
+        pflash_register(-(bios_size), bios_offset, pflash_table[fl_idx],
+                        65536, fl_sectors, 2,
+                        0x0001, 0x22DA, 0x0000, 0x0000);
+        fl_idx++;
+    } else
+#endif
+    {
+#ifdef DEBUG_BOARD_INIT
+        printf("Load BIOS from file\n");
+#endif
+        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+        bios_size = load_image(buf, phys_ram_base + bios_offset);
+        if (bios_size < 0 || bios_size > BIOS_SIZE) {
+            fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n", buf);
+            exit(1);
+        }
+        bios_size = (bios_size + 0xfff) & ~0xfff;
+        cpu_register_physical_memory((uint32_t)(-bios_size), 
+                                     bios_size, bios_offset | IO_MEM_ROM);
+    }
+    bios_offset += bios_size;
+    /* Register FPGA */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register FPGA\n", __func__);
+#endif
+    ref405ep_fpga_init(0xF0300000);
+    /* Register NVRAM */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register NVRAM\n", __func__);
+#endif
+    m48t59_init(NULL, 0xF0000000, 0, 8192, 8);
+    /* Load kernel */
+    linux_boot = (kernel_filename != NULL);
+    if (linux_boot) {
+#ifdef DEBUG_BOARD_INIT
+        printf("%s: load kernel\n", __func__);
+#endif
+        memset(&bd, 0, sizeof(bd));
+        bd.bi_memstart = 0x00000000;
+        bd.bi_memsize = ram_size;
+        bd.bi_flashstart = -(bios_size);
+        bd.bi_flashsize = -bios_size;
+        bd.bi_flashoffset = 0;
+        bd.bi_sramstart = 0xFFF00000;
+        bd.bi_sramsize = sram_size;
+        bd.bi_bootflags = 0;
+        bd.bi_intfreq = 133333333;
+        bd.bi_busfreq = 33333333;
+        bd.bi_baudrate = 115200;
+        bd.bi_s_version[0] = 'Q';
+        bd.bi_s_version[1] = 'M';
+        bd.bi_s_version[2] = 'U';
+        bd.bi_s_version[3] = '\0';
+        bd.bi_r_version[0] = 'Q';
+        bd.bi_r_version[1] = 'E';
+        bd.bi_r_version[2] = 'M';
+        bd.bi_r_version[3] = 'U';
+        bd.bi_r_version[4] = '\0';
+        bd.bi_procfreq = 133333333;
+        bd.bi_plb_busfreq = 33333333;
+        bd.bi_pci_busfreq = 33333333;
+        bd.bi_opbfreq = 33333333;
+        bdloc = ppc405_set_bootinfo(env, &bd);
+        env->gpr[3] = bdloc;
+        kernel_base = KERNEL_LOAD_ADDR;
+        /* now we can load the kernel */
+        kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n", 
+                    kernel_filename);
+            exit(1);
+        }
+        printf("Load kernel size " TARGET_FMT_ld " at " TARGET_FMT_lx
+               " %02x %02x %02x %02x\n", kernel_size, kernel_base,
+               *(char *)(phys_ram_base + kernel_base),
+               *(char *)(phys_ram_base + kernel_base + 1),
+               *(char *)(phys_ram_base + kernel_base + 2),
+               *(char *)(phys_ram_base + kernel_base + 3));
+        /* load initrd */
+        if (initrd_filename) {
+            initrd_base = INITRD_LOAD_ADDR;
+            initrd_size = load_image(initrd_filename,
+                                     phys_ram_base + initrd_base);
+            if (initrd_size < 0) {
+                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 
+                        initrd_filename);
+                exit(1);
+            }
+        } else {
+            initrd_base = 0;
+            initrd_size = 0;
+        }
+        env->gpr[4] = initrd_base;
+        env->gpr[5] = initrd_size;
+        boot_device = 'm';
+        if (kernel_cmdline != NULL) {
+            len = strlen(kernel_cmdline);
+            bdloc -= ((len + 255) & ~255);
+            memcpy(phys_ram_base + bdloc, kernel_cmdline, len + 1);
+            env->gpr[6] = bdloc;
+            env->gpr[7] = bdloc + len;
+        } else {
+            env->gpr[6] = 0;
+            env->gpr[7] = 0;
+        }
+        env->nip = KERNEL_LOAD_ADDR;
+    } else {
+        kernel_base = 0;
+        kernel_size = 0;
+        initrd_base = 0;
+        initrd_size = 0;
+        bdloc = 0;
+    }
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: Done\n", __func__);
+#endif
+    printf("bdloc %016lx %s\n",
+           (unsigned long)bdloc, (char *)(phys_ram_base + bdloc));
+}
+
+QEMUMachine ref405ep_machine = {
+    "ref405ep",
+    "ref405ep",
+    ref405ep_init,
+};
+
+/*****************************************************************************/
+/* AMCC Taihu evaluation board */
+/* - PowerPC 405EP processor
+ * - SDRAM               128 MB at 0x00000000
+ * - Boot flash          2 MB   at 0xFFE00000
+ * - Application flash   32 MB  at 0xFC000000
+ * - 2 serial ports
+ * - 2 ethernet PHY
+ * - 1 USB 1.1 device    0x50000000
+ * - 1 LCD display       0x50100000
+ * - 1 CPLD              0x50100000
+ * - 1 I2C EEPROM
+ * - 1 I2C thermal sensor
+ * - a set of LEDs
+ * - bit-bang SPI port using GPIOs
+ * - 1 EBC interface connector 0 0x50200000
+ * - 1 cardbus controller + expansion slot.
+ * - 1 PCI expansion slot.
+ */
+typedef struct taihu_cpld_t taihu_cpld_t;
+struct taihu_cpld_t {
+    uint32_t base;
+    uint8_t reg0;
+    uint8_t reg1;
+};
+
+static uint32_t taihu_cpld_readb (void *opaque, target_phys_addr_t addr)
+{
+    taihu_cpld_t *cpld;
+    uint32_t ret;
+
+    cpld = opaque;
+    addr -= cpld->base;
+    switch (addr) {
+    case 0x0:
+        ret = cpld->reg0;
+        break;
+    case 0x1:
+        ret = cpld->reg1;
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void taihu_cpld_writeb (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
+{
+    taihu_cpld_t *cpld;
+
+    cpld = opaque;
+    addr -= cpld->base;
+    switch (addr) {
+    case 0x0:
+        /* Read only */
+        break;
+    case 0x1:
+        cpld->reg1 = value;
+        break;
+    default:
+        break;
+    }
+}
+
+static uint32_t taihu_cpld_readw (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t ret;
+
+    ret = taihu_cpld_readb(opaque, addr) << 8;
+    ret |= taihu_cpld_readb(opaque, addr + 1);
+
+    return ret;
+}
+
+static void taihu_cpld_writew (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
+{
+    taihu_cpld_writeb(opaque, addr, (value >> 8) & 0xFF);
+    taihu_cpld_writeb(opaque, addr + 1, value & 0xFF);
+}
+
+static uint32_t taihu_cpld_readl (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t ret;
+
+    ret = taihu_cpld_readb(opaque, addr) << 24;
+    ret |= taihu_cpld_readb(opaque, addr + 1) << 16;
+    ret |= taihu_cpld_readb(opaque, addr + 2) << 8;
+    ret |= taihu_cpld_readb(opaque, addr + 3);
+
+    return ret;
+}
+
+static void taihu_cpld_writel (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
+{
+    taihu_cpld_writel(opaque, addr, (value >> 24) & 0xFF);
+    taihu_cpld_writel(opaque, addr + 1, (value >> 16) & 0xFF);
+    taihu_cpld_writel(opaque, addr + 2, (value >> 8) & 0xFF);
+    taihu_cpld_writeb(opaque, addr + 3, value & 0xFF);
+}
+
+static CPUReadMemoryFunc *taihu_cpld_read[] = {
+    &taihu_cpld_readb,
+    &taihu_cpld_readw,
+    &taihu_cpld_readl,
+};
+
+static CPUWriteMemoryFunc *taihu_cpld_write[] = {
+    &taihu_cpld_writeb,
+    &taihu_cpld_writew,
+    &taihu_cpld_writel,
+};
+
+static void taihu_cpld_reset (void *opaque)
+{
+    taihu_cpld_t *cpld;
+
+    cpld = opaque;
+    cpld->reg0 = 0x01;
+    cpld->reg1 = 0x80;
+}
+
+static void taihu_cpld_init (uint32_t base)
+{
+    taihu_cpld_t *cpld;
+    int cpld_memory;
+
+    cpld = qemu_mallocz(sizeof(taihu_cpld_t));
+    if (cpld != NULL) {
+        cpld->base = base;
+        cpld_memory = cpu_register_io_memory(0, taihu_cpld_read,
+                                             taihu_cpld_write, cpld);
+        cpu_register_physical_memory(base, 0x00000100, cpld_memory);
+        taihu_cpld_reset(cpld);
+        qemu_register_reset(&taihu_cpld_reset, cpld);
+    }
+}
+
+static void taihu_405ep_init(int ram_size, int vga_ram_size, int boot_device,
+                             DisplayState *ds, const char **fd_filename, 
+                             int snapshot,
+                             const char *kernel_filename, 
+                             const char *kernel_cmdline,
+                             const char *initrd_filename,
+                             const char *cpu_model)
+{
+    char buf[1024];
+    CPUPPCState *env;
+    qemu_irq *pic;
+    ram_addr_t bios_offset;
+    target_ulong ram_bases[2], ram_sizes[2];
+    target_ulong bios_size;
+    target_ulong kernel_base, kernel_size, initrd_base, initrd_size;
+    int linux_boot;
+    int fl_idx, fl_sectors;
+    
+    /* RAM is soldered to the board so the size cannot be changed */
+    ram_bases[0] = 0x00000000;
+    ram_sizes[0] = 0x04000000;
+    ram_bases[1] = 0x04000000;
+    ram_sizes[1] = 0x04000000;
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register cpu\n", __func__);
+#endif
+    env = ppc405ep_init(ram_bases, ram_sizes, 33333333, &pic, &bios_offset,
+                        kernel_filename == NULL ? 0 : 1);
+    /* allocate and load BIOS */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register BIOS\n", __func__);
+#endif
+    fl_idx = 0;
+#if defined(USE_FLASH_BIOS)
+    if (pflash_table[fl_idx] != NULL) {
+        bios_size = bdrv_getlength(pflash_table[fl_idx]);
+        /* XXX: should check that size is 2MB */
+        //        bios_size = 2 * 1024 * 1024;
+        fl_sectors = (bios_size + 65535) >> 16;
+#ifdef DEBUG_BOARD_INIT
+        printf("Register parallel flash %d size " ADDRX " at offset %08lx "
+               " addr " ADDRX " '%s' %d\n",
+               fl_idx, bios_size, bios_offset, -bios_size,
+               bdrv_get_device_name(pflash_table[fl_idx]), fl_sectors);
+#endif
+        pflash_register(-(bios_size), bios_offset, pflash_table[fl_idx],
+                        65536, fl_sectors, 4,
+                        0x0001, 0x22DA, 0x0000, 0x0000);
+        fl_idx++;
+    } else
+#endif
+    {
+#ifdef DEBUG_BOARD_INIT
+        printf("Load BIOS from file\n");
+#endif
+        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+        bios_size = load_image(buf, phys_ram_base + bios_offset);
+        if (bios_size < 0 || bios_size > BIOS_SIZE) {
+            fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n", buf);
+            exit(1);
+        }
+        bios_size = (bios_size + 0xfff) & ~0xfff;
+        cpu_register_physical_memory((uint32_t)(-bios_size), 
+                                     bios_size, bios_offset | IO_MEM_ROM);
+    }
+    bios_offset += bios_size;
+    /* Register Linux flash */
+    if (pflash_table[fl_idx] != NULL) {
+        bios_size = bdrv_getlength(pflash_table[fl_idx]);
+        /* XXX: should check that size is 32MB */
+        bios_size = 32 * 1024 * 1024;
+        fl_sectors = (bios_size + 65535) >> 16;
+#ifdef DEBUG_BOARD_INIT
+        printf("Register parallel flash %d size " ADDRX " at offset %08lx "
+               " addr " ADDRX " '%s'\n",
+               fl_idx, bios_size, bios_offset, (target_ulong)0xfc000000,
+               bdrv_get_device_name(pflash_table[fl_idx]));
+#endif
+        pflash_register(0xfc000000, bios_offset, pflash_table[fl_idx],
+                        65536, fl_sectors, 4,
+                        0x0001, 0x22DA, 0x0000, 0x0000);
+        fl_idx++;
+    }
+    /* Register CLPD & LCD display */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register CPLD\n", __func__);
+#endif
+    taihu_cpld_init(0x50100000);
+    /* Load kernel */
+    linux_boot = (kernel_filename != NULL);
+    if (linux_boot) {
+#ifdef DEBUG_BOARD_INIT
+        printf("%s: load kernel\n", __func__);
+#endif
+        kernel_base = KERNEL_LOAD_ADDR;
+        /* now we can load the kernel */
+        kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n", 
+                    kernel_filename);
+            exit(1);
+        }
+        /* load initrd */
+        if (initrd_filename) {
+            initrd_base = INITRD_LOAD_ADDR;
+            initrd_size = load_image(initrd_filename,
+                                     phys_ram_base + initrd_base);
+            if (initrd_size < 0) {
+                fprintf(stderr,
+                        "qemu: could not load initial ram disk '%s'\n", 
+                        initrd_filename);
+                exit(1);
+            }
+        } else {
+            initrd_base = 0;
+            initrd_size = 0;
+        }
+        boot_device = 'm';
+    } else {
+        kernel_base = 0;
+        kernel_size = 0;
+        initrd_base = 0;
+        initrd_size = 0;
+    }
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: Done\n", __func__);
+#endif
+}
+
+QEMUMachine taihu_machine = {
+    "taihu",
+    "taihu",
+    taihu_405ep_init,
+};

Added: trunk/src/host/qemu-neo1973/hw/ppc405_uc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc405_uc.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/ppc405_uc.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,3452 @@
+/*
+ * QEMU PowerPC 405 embedded processors emulation
+ * 
+ * Copyright (c) 2007 Jocelyn Mayer
+ * 
+ * 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"
+#include "ppc405.h"
+
+extern int loglevel;
+extern FILE *logfile;
+
+//#define DEBUG_MMIO
+#define DEBUG_OPBA
+#define DEBUG_SDRAM
+#define DEBUG_GPIO
+#define DEBUG_SERIAL
+#define DEBUG_OCM
+//#define DEBUG_I2C
+#define DEBUG_GPT
+#define DEBUG_MAL
+#define DEBUG_UIC
+#define DEBUG_CLOCKS
+//#define DEBUG_UNASSIGNED
+
+/*****************************************************************************/
+/* Generic PowerPC 405 processor instanciation */
+CPUState *ppc405_init (const unsigned char *cpu_model,
+                       clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
+                       uint32_t sysclk)
+{
+    CPUState *env;
+    ppc_def_t *def;
+
+    /* init CPUs */
+    env = cpu_init();
+    qemu_register_reset(&cpu_ppc_reset, env);
+    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
+    ppc_find_by_name(cpu_model, &def);
+    if (def == NULL) {
+        cpu_abort(env, "Unable to find PowerPC %s CPU definition\n",
+                  cpu_model);
+    }
+    cpu_ppc_register(env, def);
+    cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
+    cpu_clk->opaque = env;
+    /* Set time-base frequency to sysclk */
+    tb_clk->cb = ppc_emb_timers_init(env, sysclk);
+    tb_clk->opaque = env;
+    ppc_dcr_init(env, NULL, NULL);
+
+    return env;
+}
+
+ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd)
+{
+    ram_addr_t bdloc;
+    int i, n;
+
+    /* We put the bd structure at the top of memory */
+    bdloc = bd->bi_memsize - sizeof(struct ppc4xx_bd_info_t);
+    stl_raw(phys_ram_base + bdloc + 0x00, bd->bi_memstart);
+    stl_raw(phys_ram_base + bdloc + 0x04, bd->bi_memsize);
+    stl_raw(phys_ram_base + bdloc + 0x08, bd->bi_flashstart);
+    stl_raw(phys_ram_base + bdloc + 0x0C, bd->bi_flashsize);
+    stl_raw(phys_ram_base + bdloc + 0x10, bd->bi_flashoffset);
+    stl_raw(phys_ram_base + bdloc + 0x14, bd->bi_sramstart);
+    stl_raw(phys_ram_base + bdloc + 0x18, bd->bi_sramsize);
+    stl_raw(phys_ram_base + bdloc + 0x1C, bd->bi_bootflags);
+    stl_raw(phys_ram_base + bdloc + 0x20, bd->bi_ipaddr);
+    for (i = 0; i < 6; i++)
+        stb_raw(phys_ram_base + bdloc + 0x24 + i, bd->bi_enetaddr[i]);
+    stw_raw(phys_ram_base + bdloc + 0x2A, bd->bi_ethspeed);
+    stl_raw(phys_ram_base + bdloc + 0x2C, bd->bi_intfreq);
+    stl_raw(phys_ram_base + bdloc + 0x30, bd->bi_busfreq);
+    stl_raw(phys_ram_base + bdloc + 0x34, bd->bi_baudrate);
+    for (i = 0; i < 4; i++)
+        stb_raw(phys_ram_base + bdloc + 0x38 + i, bd->bi_s_version[i]);
+    for (i = 0; i < 32; i++)
+        stb_raw(phys_ram_base + bdloc + 0x3C + i, bd->bi_s_version[i]);
+    stl_raw(phys_ram_base + bdloc + 0x5C, bd->bi_plb_busfreq);
+    stl_raw(phys_ram_base + bdloc + 0x60, bd->bi_pci_busfreq);
+    for (i = 0; i < 6; i++)
+        stb_raw(phys_ram_base + bdloc + 0x64 + i, bd->bi_pci_enetaddr[i]);
+    n = 0x6A;
+    if (env->spr[SPR_PVR] == CPU_PPC_405EP) {
+        for (i = 0; i < 6; i++)
+            stb_raw(phys_ram_base + bdloc + n++, bd->bi_pci_enetaddr2[i]);
+    }
+    stl_raw(phys_ram_base + bdloc + n, bd->bi_opbfreq);
+    n += 4;
+    for (i = 0; i < 2; i++) {
+        stl_raw(phys_ram_base + bdloc + n, bd->bi_iic_fast[i]);
+        n += 4;
+    }
+
+    return bdloc;
+}
+
+/*****************************************************************************/
+/* Shared peripherals */
+
+/*****************************************************************************/
+/* Fake device used to map multiple devices in a single memory page */
+#define MMIO_AREA_BITS 8
+#define MMIO_AREA_LEN (1 << MMIO_AREA_BITS)
+#define MMIO_AREA_NB (1 << (TARGET_PAGE_BITS - MMIO_AREA_BITS))
+#define MMIO_IDX(addr) (((addr) >> MMIO_AREA_BITS) & (MMIO_AREA_NB - 1))
+struct ppc4xx_mmio_t {
+    target_phys_addr_t base;
+    CPUReadMemoryFunc **mem_read[MMIO_AREA_NB];
+    CPUWriteMemoryFunc **mem_write[MMIO_AREA_NB];
+    void *opaque[MMIO_AREA_NB];
+};
+
+static uint32_t unassigned_mmio_readb (void *opaque, target_phys_addr_t addr)
+{
+#ifdef DEBUG_UNASSIGNED
+    ppc4xx_mmio_t *mmio;
+
+    mmio = opaque;
+    printf("Unassigned mmio read 0x" PADDRX " base " PADDRX "\n",
+           addr, mmio->base);
+#endif
+
+    return 0;
+}
+
+static void unassigned_mmio_writeb (void *opaque,
+                                   target_phys_addr_t addr, uint32_t val)
+{
+#ifdef DEBUG_UNASSIGNED
+    ppc4xx_mmio_t *mmio;
+
+    mmio = opaque;
+    printf("Unassigned mmio write 0x" PADDRX " = 0x%x base " PADDRX "\n",
+           addr, val, mmio->base);
+#endif
+}
+
+static CPUReadMemoryFunc *unassigned_mmio_read[3] = {
+    unassigned_mmio_readb,
+    unassigned_mmio_readb,
+    unassigned_mmio_readb,
+};
+
+static CPUWriteMemoryFunc *unassigned_mmio_write[3] = {
+    unassigned_mmio_writeb,
+    unassigned_mmio_writeb,
+    unassigned_mmio_writeb,
+};
+
+static uint32_t mmio_readlen (ppc4xx_mmio_t *mmio,
+                              target_phys_addr_t addr, int len)
+{
+    CPUReadMemoryFunc **mem_read;
+    uint32_t ret;
+    int idx;
+
+    idx = MMIO_IDX(addr - mmio->base);
+#if defined(DEBUG_MMIO)
+    printf("%s: mmio %p len %d addr " PADDRX " idx %d\n", __func__,
+           mmio, len, addr, idx);
+#endif
+    mem_read = mmio->mem_read[idx];
+    ret = (*mem_read[len])(mmio->opaque[idx], addr - mmio->base);
+
+    return ret;
+}
+
+static void mmio_writelen (ppc4xx_mmio_t *mmio,
+                           target_phys_addr_t addr, uint32_t value, int len)
+{
+    CPUWriteMemoryFunc **mem_write;
+    int idx;
+
+    idx = MMIO_IDX(addr - mmio->base);
+#if defined(DEBUG_MMIO)
+    printf("%s: mmio %p len %d addr " PADDRX " idx %d value %08x\n", __func__,
+           mmio, len, addr, idx, value);
+#endif
+    mem_write = mmio->mem_write[idx];
+    (*mem_write[len])(mmio->opaque[idx], addr - mmio->base, value);
+}
+
+static uint32_t mmio_readb (void *opaque, target_phys_addr_t addr)
+{
+#if defined(DEBUG_MMIO)
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+
+    return mmio_readlen(opaque, addr, 0);
+}
+
+static void mmio_writeb (void *opaque,
+                         target_phys_addr_t addr, uint32_t value)
+{
+#if defined(DEBUG_MMIO)
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    mmio_writelen(opaque, addr, value, 0);
+}
+
+static uint32_t mmio_readw (void *opaque, target_phys_addr_t addr)
+{
+#if defined(DEBUG_MMIO)
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+
+    return mmio_readlen(opaque, addr, 1);
+}
+
+static void mmio_writew (void *opaque,
+                         target_phys_addr_t addr, uint32_t value)
+{
+#if defined(DEBUG_MMIO)
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    mmio_writelen(opaque, addr, value, 1);
+}
+
+static uint32_t mmio_readl (void *opaque, target_phys_addr_t addr)
+{
+#if defined(DEBUG_MMIO)
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+
+    return mmio_readlen(opaque, addr, 2);
+}
+
+static void mmio_writel (void *opaque,
+                         target_phys_addr_t addr, uint32_t value)
+{
+#if defined(DEBUG_MMIO)
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    mmio_writelen(opaque, addr, value, 2);
+}
+
+static CPUReadMemoryFunc *mmio_read[] = {
+    &mmio_readb,
+    &mmio_readw,
+    &mmio_readl,
+};
+
+static CPUWriteMemoryFunc *mmio_write[] = {
+    &mmio_writeb,
+    &mmio_writew,
+    &mmio_writel,
+};
+
+int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio,
+                          target_phys_addr_t offset, uint32_t len,
+                          CPUReadMemoryFunc **mem_read,
+                          CPUWriteMemoryFunc **mem_write, void *opaque)
+{
+    uint32_t end;
+    int idx, eidx;
+
+    if ((offset + len) > TARGET_PAGE_SIZE)
+        return -1;
+    idx = MMIO_IDX(offset);
+    end = offset + len - 1;
+    eidx = MMIO_IDX(end);
+#if defined(DEBUG_MMIO)
+    printf("%s: offset %08x len %08x %08x %d %d\n", __func__, offset, len,
+           end, idx, eidx);
+#endif
+    for (; idx <= eidx; idx++) {
+        mmio->mem_read[idx] = mem_read;
+        mmio->mem_write[idx] = mem_write;
+        mmio->opaque[idx] = opaque;
+    }
+
+    return 0;
+}
+
+ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base)
+{
+    ppc4xx_mmio_t *mmio;
+    int mmio_memory;
+
+    mmio = qemu_mallocz(sizeof(ppc4xx_mmio_t));
+    if (mmio != NULL) {
+        mmio->base = base;
+        mmio_memory = cpu_register_io_memory(0, mmio_read, mmio_write, mmio);
+#if defined(DEBUG_MMIO)
+        printf("%s: %p base %08x len %08x %d\n", __func__,
+               mmio, base, TARGET_PAGE_SIZE, mmio_memory);
+#endif
+        cpu_register_physical_memory(base, TARGET_PAGE_SIZE, mmio_memory);
+        ppc4xx_mmio_register(env, mmio, 0, TARGET_PAGE_SIZE,
+                             unassigned_mmio_read, unassigned_mmio_write,
+                             mmio);
+    }
+
+    return mmio;
+}
+
+/*****************************************************************************/
+/* Peripheral local bus arbitrer */
+enum {
+    PLB0_BESR = 0x084,
+    PLB0_BEAR = 0x086,
+    PLB0_ACR  = 0x087,
+};
+
+typedef struct ppc4xx_plb_t ppc4xx_plb_t;
+struct ppc4xx_plb_t {
+    uint32_t acr;
+    uint32_t bear;
+    uint32_t besr;
+};
+
+static target_ulong dcr_read_plb (void *opaque, int dcrn)
+{
+    ppc4xx_plb_t *plb;
+    target_ulong ret;
+
+    plb = opaque;
+    switch (dcrn) {
+    case PLB0_ACR:
+        ret = plb->acr;
+        break;
+    case PLB0_BEAR:
+        ret = plb->bear;
+        break;
+    case PLB0_BESR:
+        ret = plb->besr;
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_plb (void *opaque, int dcrn, target_ulong val)
+{
+    ppc4xx_plb_t *plb;
+
+    plb = opaque;
+    switch (dcrn) {
+    case PLB0_ACR:
+        /* We don't care about the actual parameters written as
+         * we don't manage any priorities on the bus
+         */
+        plb->acr = val & 0xF8000000;
+        break;
+    case PLB0_BEAR:
+        /* Read only */
+        break;
+    case PLB0_BESR:
+        /* Write-clear */
+        plb->besr &= ~val;
+        break;
+    }
+}
+
+static void ppc4xx_plb_reset (void *opaque)
+{
+    ppc4xx_plb_t *plb;
+
+    plb = opaque;
+    plb->acr = 0x00000000;
+    plb->bear = 0x00000000;
+    plb->besr = 0x00000000;
+}
+
+void ppc4xx_plb_init (CPUState *env)
+{
+    ppc4xx_plb_t *plb;
+
+    plb = qemu_mallocz(sizeof(ppc4xx_plb_t));
+    if (plb != NULL) {
+        ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
+        ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
+        ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
+        ppc4xx_plb_reset(plb);
+        qemu_register_reset(ppc4xx_plb_reset, plb);
+    }
+}
+
+/*****************************************************************************/
+/* PLB to OPB bridge */
+enum {
+    POB0_BESR0 = 0x0A0,
+    POB0_BESR1 = 0x0A2,
+    POB0_BEAR  = 0x0A4,
+};
+
+typedef struct ppc4xx_pob_t ppc4xx_pob_t;
+struct ppc4xx_pob_t {
+    uint32_t bear;
+    uint32_t besr[2];
+};
+
+static target_ulong dcr_read_pob (void *opaque, int dcrn)
+{
+    ppc4xx_pob_t *pob;
+    target_ulong ret;
+
+    pob = opaque;
+    switch (dcrn) {
+    case POB0_BEAR:
+        ret = pob->bear;
+        break;
+    case POB0_BESR0:
+    case POB0_BESR1:
+        ret = pob->besr[dcrn - POB0_BESR0];
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_pob (void *opaque, int dcrn, target_ulong val)
+{
+    ppc4xx_pob_t *pob;
+
+    pob = opaque;
+    switch (dcrn) {
+    case POB0_BEAR:
+        /* Read only */
+        break;
+    case POB0_BESR0:
+    case POB0_BESR1:
+        /* Write-clear */
+        pob->besr[dcrn - POB0_BESR0] &= ~val;
+        break;
+    }
+}
+
+static void ppc4xx_pob_reset (void *opaque)
+{
+    ppc4xx_pob_t *pob;
+
+    pob = opaque;
+    /* No error */
+    pob->bear = 0x00000000;
+    pob->besr[0] = 0x0000000;
+    pob->besr[1] = 0x0000000;
+}
+
+void ppc4xx_pob_init (CPUState *env)
+{
+    ppc4xx_pob_t *pob;
+
+    pob = qemu_mallocz(sizeof(ppc4xx_pob_t));
+    if (pob != NULL) {
+        ppc_dcr_register(env, POB0_BEAR, pob, &dcr_read_pob, &dcr_write_pob);
+        ppc_dcr_register(env, POB0_BESR0, pob, &dcr_read_pob, &dcr_write_pob);
+        ppc_dcr_register(env, POB0_BESR1, pob, &dcr_read_pob, &dcr_write_pob);
+        qemu_register_reset(ppc4xx_pob_reset, pob);
+        ppc4xx_pob_reset(env);
+    }
+}
+
+/*****************************************************************************/
+/* OPB arbitrer */
+typedef struct ppc4xx_opba_t ppc4xx_opba_t;
+struct ppc4xx_opba_t {
+    target_phys_addr_t base;
+    uint8_t cr;
+    uint8_t pr;
+};
+
+static uint32_t opba_readb (void *opaque, target_phys_addr_t addr)
+{
+    ppc4xx_opba_t *opba;
+    uint32_t ret;
+
+#ifdef DEBUG_OPBA
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+    opba = opaque;
+    switch (addr - opba->base) {
+    case 0x00:
+        ret = opba->cr;
+        break;
+    case 0x01:
+        ret = opba->pr;
+        break;
+    default:
+        ret = 0x00;
+        break;
+    }
+
+    return ret;
+}
+
+static void opba_writeb (void *opaque,
+                         target_phys_addr_t addr, uint32_t value)
+{
+    ppc4xx_opba_t *opba;
+
+#ifdef DEBUG_OPBA
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    opba = opaque;
+    switch (addr - opba->base) {
+    case 0x00:
+        opba->cr = value & 0xF8;
+        break;
+    case 0x01:
+        opba->pr = value & 0xFF;
+        break;
+    default:
+        break;
+    }
+}
+
+static uint32_t opba_readw (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_OPBA
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+    ret = opba_readb(opaque, addr) << 8;
+    ret |= opba_readb(opaque, addr + 1);
+
+    return ret;
+}
+
+static void opba_writew (void *opaque,
+                         target_phys_addr_t addr, uint32_t value)
+{
+#ifdef DEBUG_OPBA
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    opba_writeb(opaque, addr, value >> 8);
+    opba_writeb(opaque, addr + 1, value);
+}
+
+static uint32_t opba_readl (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_OPBA
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+    ret = opba_readb(opaque, addr) << 24;
+    ret |= opba_readb(opaque, addr + 1) << 16;
+
+    return ret;
+}
+
+static void opba_writel (void *opaque,
+                         target_phys_addr_t addr, uint32_t value)
+{
+#ifdef DEBUG_OPBA
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    opba_writeb(opaque, addr, value >> 24);
+    opba_writeb(opaque, addr + 1, value >> 16);
+}
+
+static CPUReadMemoryFunc *opba_read[] = {
+    &opba_readb,
+    &opba_readw,
+    &opba_readl,
+};
+
+static CPUWriteMemoryFunc *opba_write[] = {
+    &opba_writeb,
+    &opba_writew,
+    &opba_writel,
+};
+
+static void ppc4xx_opba_reset (void *opaque)
+{
+    ppc4xx_opba_t *opba;
+
+    opba = opaque;
+    opba->cr = 0x00; /* No dynamic priorities - park disabled */
+    opba->pr = 0x11;
+}
+
+void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                       target_phys_addr_t offset)
+{
+    ppc4xx_opba_t *opba;
+
+    opba = qemu_mallocz(sizeof(ppc4xx_opba_t));
+    if (opba != NULL) {
+        opba->base = offset;
+#ifdef DEBUG_OPBA
+        printf("%s: offset=" PADDRX "\n", __func__, offset);
+#endif
+        ppc4xx_mmio_register(env, mmio, offset, 0x002,
+                             opba_read, opba_write, opba);
+        qemu_register_reset(ppc4xx_opba_reset, opba);
+        ppc4xx_opba_reset(opba);
+    }
+}
+
+/*****************************************************************************/
+/* "Universal" Interrupt controller */
+enum {
+    DCR_UICSR  = 0x000,
+    DCR_UICSRS = 0x001,
+    DCR_UICER  = 0x002,
+    DCR_UICCR  = 0x003,
+    DCR_UICPR  = 0x004,
+    DCR_UICTR  = 0x005,
+    DCR_UICMSR = 0x006,
+    DCR_UICVR  = 0x007,
+    DCR_UICVCR = 0x008,
+    DCR_UICMAX = 0x009,
+};
+
+#define UIC_MAX_IRQ 32
+typedef struct ppcuic_t ppcuic_t;
+struct ppcuic_t {
+    uint32_t dcr_base;
+    int use_vectors;
+    uint32_t uicsr;  /* Status register */
+    uint32_t uicer;  /* Enable register */
+    uint32_t uiccr;  /* Critical register */
+    uint32_t uicpr;  /* Polarity register */
+    uint32_t uictr;  /* Triggering register */
+    uint32_t uicvcr; /* Vector configuration register */
+    uint32_t uicvr;
+    qemu_irq *irqs;
+};
+
+static void ppcuic_trigger_irq (ppcuic_t *uic)
+{
+    uint32_t ir, cr;
+    int start, end, inc, i;
+
+    /* Trigger interrupt if any is pending */
+    ir = uic->uicsr & uic->uicer & (~uic->uiccr);
+    cr = uic->uicsr & uic->uicer & uic->uiccr;
+#ifdef DEBUG_UIC
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: uicsr %08x uicer %08x uiccr %08x\n"
+                "   %08x ir %08x cr %08x\n", __func__,
+                uic->uicsr, uic->uicer, uic->uiccr,
+                uic->uicsr & uic->uicer, ir, cr);
+    }
+#endif
+    if (ir != 0x0000000) {
+#ifdef DEBUG_UIC
+        if (loglevel & CPU_LOG_INT) {
+            fprintf(logfile, "Raise UIC interrupt\n");
+        }
+#endif
+        qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_INT]);
+    } else {
+#ifdef DEBUG_UIC
+        if (loglevel & CPU_LOG_INT) {
+            fprintf(logfile, "Lower UIC interrupt\n");
+        }
+#endif
+        qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_INT]);
+    }
+    /* Trigger critical interrupt if any is pending and update vector */
+    if (cr != 0x0000000) {
+        qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_CINT]);
+        if (uic->use_vectors) {
+            /* Compute critical IRQ vector */
+            if (uic->uicvcr & 1) {
+                start = 31;
+                end = 0;
+                inc = -1;
+            } else {
+                start = 0;
+                end = 31;
+                inc = 1;
+            }
+            uic->uicvr = uic->uicvcr & 0xFFFFFFFC;
+            for (i = start; i <= end; i += inc) {
+                if (cr & (1 << i)) {
+                    uic->uicvr += (i - start) * 512 * inc;
+                    break;
+                }
+            }
+        }
+#ifdef DEBUG_UIC
+        if (loglevel & CPU_LOG_INT) {
+            fprintf(logfile, "Raise UIC critical interrupt - vector %08x\n",
+                    uic->uicvr);
+        }
+#endif
+    } else {
+#ifdef DEBUG_UIC
+        if (loglevel & CPU_LOG_INT) {
+            fprintf(logfile, "Lower UIC critical interrupt\n");
+        }
+#endif
+        qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_CINT]);
+        uic->uicvr = 0x00000000;
+    }
+}
+
+static void ppcuic_set_irq (void *opaque, int irq_num, int level)
+{
+    ppcuic_t *uic;
+    uint32_t mask, sr;
+
+    uic = opaque;
+    mask = 1 << irq_num;
+#ifdef DEBUG_UIC
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: irq %d level %d uicsr %08x mask %08x => %08x "
+                "%08x\n", __func__, irq_num, level,
+                uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
+    }
+#endif
+    if (irq_num < 0 || irq_num > 31)
+        return;
+    sr = uic->uicsr;
+    if (!(uic->uicpr & mask)) {
+        /* Negatively asserted IRQ */
+        level = level == 0 ? 1 : 0;
+    }
+    /* Update status register */
+    if (uic->uictr & mask) {
+        /* Edge sensitive interrupt */
+        if (level == 1)
+            uic->uicsr |= mask;
+    } else {
+        /* Level sensitive interrupt */
+        if (level == 1)
+            uic->uicsr |= mask;
+        else
+            uic->uicsr &= ~mask;
+    }
+#ifdef DEBUG_UIC
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: irq %d level %d sr %08x => %08x\n", __func__,
+                irq_num, level, uic->uicsr, sr);
+    }
+#endif
+    if (sr != uic->uicsr)
+        ppcuic_trigger_irq(uic);
+}
+
+static target_ulong dcr_read_uic (void *opaque, int dcrn)
+{
+    ppcuic_t *uic;
+    target_ulong ret;
+
+    uic = opaque;
+    dcrn -= uic->dcr_base;
+    switch (dcrn) {
+    case DCR_UICSR:
+    case DCR_UICSRS:
+        ret = uic->uicsr;
+        break;
+    case DCR_UICER:
+        ret = uic->uicer;
+        break;
+    case DCR_UICCR:
+        ret = uic->uiccr;
+        break;
+    case DCR_UICPR:
+        ret = uic->uicpr;
+        break;
+    case DCR_UICTR:
+        ret = uic->uictr;
+        break;
+    case DCR_UICMSR:
+        ret = uic->uicsr & uic->uicer;
+        break;
+    case DCR_UICVR:
+        if (!uic->use_vectors)
+            goto no_read;
+        ret = uic->uicvr;
+        break;
+    case DCR_UICVCR:
+        if (!uic->use_vectors)
+            goto no_read;
+        ret = uic->uicvcr;
+        break;
+    default:
+    no_read:
+        ret = 0x00000000;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_uic (void *opaque, int dcrn, target_ulong val)
+{
+    ppcuic_t *uic;
+
+    uic = opaque;
+    dcrn -= uic->dcr_base;
+#ifdef DEBUG_UIC
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: dcr %d val " ADDRX "\n", __func__, dcrn, val);
+    }
+#endif
+    switch (dcrn) {
+    case DCR_UICSR:
+        uic->uicsr &= ~val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICSRS:
+        uic->uicsr |= val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICER:
+        uic->uicer = val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICCR:
+        uic->uiccr = val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICPR:
+        uic->uicpr = val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICTR:
+        uic->uictr = val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICMSR:
+        break;
+    case DCR_UICVR:
+        break;
+    case DCR_UICVCR:
+        uic->uicvcr = val & 0xFFFFFFFD;
+        ppcuic_trigger_irq(uic);
+        break;
+    }
+}
+
+static void ppcuic_reset (void *opaque)
+{
+    ppcuic_t *uic;
+
+    uic = opaque;
+    uic->uiccr = 0x00000000;
+    uic->uicer = 0x00000000;
+    uic->uicpr = 0x00000000;
+    uic->uicsr = 0x00000000;
+    uic->uictr = 0x00000000;
+    if (uic->use_vectors) {
+        uic->uicvcr = 0x00000000;
+        uic->uicvr = 0x0000000;
+    }
+}
+
+qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
+                       uint32_t dcr_base, int has_ssr, int has_vr)
+{
+    ppcuic_t *uic;
+    int i;
+
+    uic = qemu_mallocz(sizeof(ppcuic_t));
+    if (uic != NULL) {
+        uic->dcr_base = dcr_base;
+        uic->irqs = irqs;
+        if (has_vr)
+            uic->use_vectors = 1;
+        for (i = 0; i < DCR_UICMAX; i++) {
+            ppc_dcr_register(env, dcr_base + i, uic,
+                             &dcr_read_uic, &dcr_write_uic);
+        }
+        qemu_register_reset(ppcuic_reset, uic);
+        ppcuic_reset(uic);
+    }
+
+    return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
+}
+
+/*****************************************************************************/
+/* Code decompression controller */
+/* XXX: TODO */
+
+/*****************************************************************************/
+/* SDRAM controller */
+typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
+struct ppc4xx_sdram_t {
+    uint32_t addr;
+    int nbanks;
+    target_ulong ram_bases[4];
+    target_ulong ram_sizes[4];
+    uint32_t besr0;
+    uint32_t besr1;
+    uint32_t bear;
+    uint32_t cfg;
+    uint32_t status;
+    uint32_t rtr;
+    uint32_t pmit;
+    uint32_t bcr[4];
+    uint32_t tr;
+    uint32_t ecccfg;
+    uint32_t eccesr;
+    qemu_irq irq;
+};
+
+enum {
+    SDRAM0_CFGADDR = 0x010,
+    SDRAM0_CFGDATA = 0x011,
+};
+
+static uint32_t sdram_bcr (target_ulong ram_base, target_ulong ram_size)
+{
+    uint32_t bcr;
+
+    switch (ram_size) {
+    case (4 * 1024 * 1024):
+        bcr = 0x00000000;
+        break;
+    case (8 * 1024 * 1024):
+        bcr = 0x00020000;
+        break;
+    case (16 * 1024 * 1024):
+        bcr = 0x00040000;
+        break;
+    case (32 * 1024 * 1024):
+        bcr = 0x00060000;
+        break;
+    case (64 * 1024 * 1024):
+        bcr = 0x00080000;
+        break;
+    case (128 * 1024 * 1024):
+        bcr = 0x000A0000;
+        break;
+    case (256 * 1024 * 1024):
+        bcr = 0x000C0000;
+        break;
+    default:
+        printf("%s: invalid RAM size " TARGET_FMT_ld "\n", __func__, ram_size);
+        return 0x00000000;
+    }
+    bcr |= ram_base & 0xFF800000;
+    bcr |= 1;
+
+    return bcr;
+}
+
+static inline target_ulong sdram_base (uint32_t bcr)
+{
+    return bcr & 0xFF800000;
+}
+
+static target_ulong sdram_size (uint32_t bcr)
+{
+    target_ulong size;
+    int sh;
+
+    sh = (bcr >> 17) & 0x7;
+    if (sh == 7)
+        size = -1;
+    else
+        size = (4 * 1024 * 1024) << sh;
+
+    return size;
+}
+
+static void sdram_set_bcr (uint32_t *bcrp, uint32_t bcr, int enabled)
+{
+    if (*bcrp & 0x00000001) {
+        /* Unmap RAM */
+#ifdef DEBUG_SDRAM
+        printf("%s: unmap RAM area " ADDRX " " ADDRX "\n", __func__,
+               sdram_base(*bcrp), sdram_size(*bcrp));
+#endif
+        cpu_register_physical_memory(sdram_base(*bcrp), sdram_size(*bcrp),
+                                     IO_MEM_UNASSIGNED);
+    }
+    *bcrp = bcr & 0xFFDEE001;
+    if (enabled && (bcr & 0x00000001)) {
+#ifdef DEBUG_SDRAM
+        printf("%s: Map RAM area " ADDRX " " ADDRX "\n", __func__,
+               sdram_base(bcr), sdram_size(bcr));
+#endif
+        cpu_register_physical_memory(sdram_base(bcr), sdram_size(bcr),
+                                     sdram_base(bcr) | IO_MEM_RAM);
+    }
+}
+
+static void sdram_map_bcr (ppc4xx_sdram_t *sdram)
+{
+    int i;
+
+    for (i = 0; i < sdram->nbanks; i++) {
+        if (sdram->ram_sizes[i] != 0) {
+            sdram_set_bcr(&sdram->bcr[i],
+                          sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
+                          1);
+        } else {
+            sdram_set_bcr(&sdram->bcr[i], 0x00000000, 0);
+        }
+    }
+}
+
+static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram)
+{
+    int i;
+
+    for (i = 0; i < sdram->nbanks; i++) {
+#ifdef DEBUG_SDRAM
+        printf("%s: Unmap RAM area " ADDRX " " ADDRX "\n", __func__,
+               sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
+#endif
+        cpu_register_physical_memory(sdram_base(sdram->bcr[i]),
+                                     sdram_size(sdram->bcr[i]),
+                                     IO_MEM_UNASSIGNED);
+    }
+}
+
+static target_ulong dcr_read_sdram (void *opaque, int dcrn)
+{
+    ppc4xx_sdram_t *sdram;
+    target_ulong ret;
+
+    sdram = opaque;
+    switch (dcrn) {
+    case SDRAM0_CFGADDR:
+        ret = sdram->addr;
+        break;
+    case SDRAM0_CFGDATA:
+        switch (sdram->addr) {
+        case 0x00: /* SDRAM_BESR0 */
+            ret = sdram->besr0;
+            break;
+        case 0x08: /* SDRAM_BESR1 */
+            ret = sdram->besr1;
+            break;
+        case 0x10: /* SDRAM_BEAR */
+            ret = sdram->bear;
+            break;
+        case 0x20: /* SDRAM_CFG */
+            ret = sdram->cfg;
+            break;
+        case 0x24: /* SDRAM_STATUS */
+            ret = sdram->status;
+            break;
+        case 0x30: /* SDRAM_RTR */
+            ret = sdram->rtr;
+            break;
+        case 0x34: /* SDRAM_PMIT */
+            ret = sdram->pmit;
+            break;
+        case 0x40: /* SDRAM_B0CR */
+            ret = sdram->bcr[0];
+            break;
+        case 0x44: /* SDRAM_B1CR */
+            ret = sdram->bcr[1];
+            break;
+        case 0x48: /* SDRAM_B2CR */
+            ret = sdram->bcr[2];
+            break;
+        case 0x4C: /* SDRAM_B3CR */
+            ret = sdram->bcr[3];
+            break;
+        case 0x80: /* SDRAM_TR */
+            ret = -1; /* ? */
+            break;
+        case 0x94: /* SDRAM_ECCCFG */
+            ret = sdram->ecccfg;
+            break;
+        case 0x98: /* SDRAM_ECCESR */
+            ret = sdram->eccesr;
+            break;
+        default: /* Error */
+            ret = -1;
+            break;
+        }
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0x00000000;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_sdram (void *opaque, int dcrn, target_ulong val)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = opaque;
+    switch (dcrn) {
+    case SDRAM0_CFGADDR:
+        sdram->addr = val;
+        break;
+    case SDRAM0_CFGDATA:
+        switch (sdram->addr) {
+        case 0x00: /* SDRAM_BESR0 */
+            sdram->besr0 &= ~val;
+            break;
+        case 0x08: /* SDRAM_BESR1 */
+            sdram->besr1 &= ~val;
+            break;
+        case 0x10: /* SDRAM_BEAR */
+            sdram->bear = val;
+            break;
+        case 0x20: /* SDRAM_CFG */
+            val &= 0xFFE00000;
+            if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
+#ifdef DEBUG_SDRAM
+                printf("%s: enable SDRAM controller\n", __func__);
+#endif
+                /* validate all RAM mappings */
+                sdram_map_bcr(sdram);
+                sdram->status &= ~0x80000000;
+            } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
+#ifdef DEBUG_SDRAM
+                printf("%s: disable SDRAM controller\n", __func__);
+#endif
+                /* invalidate all RAM mappings */
+                sdram_unmap_bcr(sdram);
+                sdram->status |= 0x80000000;
+            }
+            if (!(sdram->cfg & 0x40000000) && (val & 0x40000000))
+                sdram->status |= 0x40000000;
+            else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000))
+                sdram->status &= ~0x40000000;
+            sdram->cfg = val;
+            break;
+        case 0x24: /* SDRAM_STATUS */
+            /* Read-only register */
+            break;
+        case 0x30: /* SDRAM_RTR */
+            sdram->rtr = val & 0x3FF80000;
+            break;
+        case 0x34: /* SDRAM_PMIT */
+            sdram->pmit = (val & 0xF8000000) | 0x07C00000;
+            break;
+        case 0x40: /* SDRAM_B0CR */
+            sdram_set_bcr(&sdram->bcr[0], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x44: /* SDRAM_B1CR */
+            sdram_set_bcr(&sdram->bcr[1], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x48: /* SDRAM_B2CR */
+            sdram_set_bcr(&sdram->bcr[2], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x4C: /* SDRAM_B3CR */
+            sdram_set_bcr(&sdram->bcr[3], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x80: /* SDRAM_TR */
+            sdram->tr = val & 0x018FC01F;
+            break;
+        case 0x94: /* SDRAM_ECCCFG */
+            sdram->ecccfg = val & 0x00F00000;
+            break;
+        case 0x98: /* SDRAM_ECCESR */
+            val &= 0xFFF0F000;
+            if (sdram->eccesr == 0 && val != 0)
+                qemu_irq_raise(sdram->irq);
+            else if (sdram->eccesr != 0 && val == 0)
+                qemu_irq_lower(sdram->irq);
+            sdram->eccesr = val;
+            break;
+        default: /* Error */
+            break;
+        }
+        break;
+    }
+}
+
+static void sdram_reset (void *opaque)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = opaque;
+    sdram->addr = 0x00000000;
+    sdram->bear = 0x00000000;
+    sdram->besr0 = 0x00000000; /* No error */
+    sdram->besr1 = 0x00000000; /* No error */
+    sdram->cfg = 0x00000000;
+    sdram->ecccfg = 0x00000000; /* No ECC */
+    sdram->eccesr = 0x00000000; /* No error */
+    sdram->pmit = 0x07C00000;
+    sdram->rtr = 0x05F00000;
+    sdram->tr = 0x00854009;
+    /* We pre-initialize RAM banks */
+    sdram->status = 0x00000000;
+    sdram->cfg = 0x00800000;
+    sdram_unmap_bcr(sdram);
+}
+
+void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
+                        target_ulong *ram_bases, target_ulong *ram_sizes,
+                        int do_init)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = qemu_mallocz(sizeof(ppc4xx_sdram_t));
+    if (sdram != NULL) {
+        sdram->irq = irq;
+        sdram->nbanks = nbanks;
+        memset(sdram->ram_bases, 0, 4 * sizeof(target_ulong));
+        memcpy(sdram->ram_bases, ram_bases, nbanks * sizeof(target_ulong));
+        memset(sdram->ram_sizes, 0, 4 * sizeof(target_ulong));
+        memcpy(sdram->ram_sizes, ram_sizes, nbanks * sizeof(target_ulong));
+        sdram_reset(sdram);
+        qemu_register_reset(&sdram_reset, sdram);
+        ppc_dcr_register(env, SDRAM0_CFGADDR,
+                         sdram, &dcr_read_sdram, &dcr_write_sdram);
+        ppc_dcr_register(env, SDRAM0_CFGDATA,
+                         sdram, &dcr_read_sdram, &dcr_write_sdram);
+        if (do_init)
+            sdram_map_bcr(sdram);
+    }
+}
+
+/*****************************************************************************/
+/* Peripheral controller */
+typedef struct ppc4xx_ebc_t ppc4xx_ebc_t;
+struct ppc4xx_ebc_t {
+    uint32_t addr;
+    uint32_t bcr[8];
+    uint32_t bap[8];
+    uint32_t bear;
+    uint32_t besr0;
+    uint32_t besr1;
+    uint32_t cfg;
+};
+
+enum {
+    EBC0_CFGADDR = 0x012,
+    EBC0_CFGDATA = 0x013,
+};
+
+static target_ulong dcr_read_ebc (void *opaque, int dcrn)
+{
+    ppc4xx_ebc_t *ebc;
+    target_ulong ret;
+
+    ebc = opaque;
+    switch (dcrn) {
+    case EBC0_CFGADDR:
+        ret = ebc->addr;
+        break;
+    case EBC0_CFGDATA:
+        switch (ebc->addr) {
+        case 0x00: /* B0CR */
+            ret = ebc->bcr[0];
+            break;
+        case 0x01: /* B1CR */
+            ret = ebc->bcr[1];
+            break;
+        case 0x02: /* B2CR */
+            ret = ebc->bcr[2];
+            break;
+        case 0x03: /* B3CR */
+            ret = ebc->bcr[3];
+            break;
+        case 0x04: /* B4CR */
+            ret = ebc->bcr[4];
+            break;
+        case 0x05: /* B5CR */
+            ret = ebc->bcr[5];
+            break;
+        case 0x06: /* B6CR */
+            ret = ebc->bcr[6];
+            break;
+        case 0x07: /* B7CR */
+            ret = ebc->bcr[7];
+            break;
+        case 0x10: /* B0AP */
+            ret = ebc->bap[0];
+            break;
+        case 0x11: /* B1AP */
+            ret = ebc->bap[1];
+            break;
+        case 0x12: /* B2AP */
+            ret = ebc->bap[2];
+            break;
+        case 0x13: /* B3AP */
+            ret = ebc->bap[3];
+            break;
+        case 0x14: /* B4AP */
+            ret = ebc->bap[4];
+            break;
+        case 0x15: /* B5AP */
+            ret = ebc->bap[5];
+            break;
+        case 0x16: /* B6AP */
+            ret = ebc->bap[6];
+            break;
+        case 0x17: /* B7AP */
+            ret = ebc->bap[7];
+            break;
+        case 0x20: /* BEAR */
+            ret = ebc->bear;
+            break;
+        case 0x21: /* BESR0 */
+            ret = ebc->besr0;
+            break;
+        case 0x22: /* BESR1 */
+            ret = ebc->besr1;
+            break;
+        case 0x23: /* CFG */
+            ret = ebc->cfg;
+            break;
+        default:
+            ret = 0x00000000;
+            break;
+        }
+    default:
+        ret = 0x00000000;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_ebc (void *opaque, int dcrn, target_ulong val)
+{
+    ppc4xx_ebc_t *ebc;
+
+    ebc = opaque;
+    switch (dcrn) {
+    case EBC0_CFGADDR:
+        ebc->addr = val;
+        break;
+    case EBC0_CFGDATA:
+        switch (ebc->addr) {
+        case 0x00: /* B0CR */
+            break;
+        case 0x01: /* B1CR */
+            break;
+        case 0x02: /* B2CR */
+            break;
+        case 0x03: /* B3CR */
+            break;
+        case 0x04: /* B4CR */
+            break;
+        case 0x05: /* B5CR */
+            break;
+        case 0x06: /* B6CR */
+            break;
+        case 0x07: /* B7CR */
+            break;
+        case 0x10: /* B0AP */
+            break;
+        case 0x11: /* B1AP */
+            break;
+        case 0x12: /* B2AP */
+            break;
+        case 0x13: /* B3AP */
+            break;
+        case 0x14: /* B4AP */
+            break;
+        case 0x15: /* B5AP */
+            break;
+        case 0x16: /* B6AP */
+            break;
+        case 0x17: /* B7AP */
+            break;
+        case 0x20: /* BEAR */
+            break;
+        case 0x21: /* BESR0 */
+            break;
+        case 0x22: /* BESR1 */
+            break;
+        case 0x23: /* CFG */
+            break;
+        default:
+            break;
+        }
+        break;
+    default:
+        break;
+    }
+}
+
+static void ebc_reset (void *opaque)
+{
+    ppc4xx_ebc_t *ebc;
+    int i;
+
+    ebc = opaque;
+    ebc->addr = 0x00000000;
+    ebc->bap[0] = 0x7F8FFE80;
+    ebc->bcr[0] = 0xFFE28000;
+    for (i = 0; i < 8; i++) {
+        ebc->bap[i] = 0x00000000;
+        ebc->bcr[i] = 0x00000000;
+    }
+    ebc->besr0 = 0x00000000;
+    ebc->besr1 = 0x00000000;
+    ebc->cfg = 0x80400000;
+}
+
+void ppc405_ebc_init (CPUState *env)
+{
+    ppc4xx_ebc_t *ebc;
+
+    ebc = qemu_mallocz(sizeof(ppc4xx_ebc_t));
+    if (ebc != NULL) {
+        ebc_reset(ebc);
+        qemu_register_reset(&ebc_reset, ebc);
+        ppc_dcr_register(env, EBC0_CFGADDR,
+                         ebc, &dcr_read_ebc, &dcr_write_ebc);
+        ppc_dcr_register(env, EBC0_CFGDATA,
+                         ebc, &dcr_read_ebc, &dcr_write_ebc);
+    }
+}
+
+/*****************************************************************************/
+/* DMA controller */
+enum {
+    DMA0_CR0 = 0x100,
+    DMA0_CT0 = 0x101,
+    DMA0_DA0 = 0x102,
+    DMA0_SA0 = 0x103,
+    DMA0_SG0 = 0x104,
+    DMA0_CR1 = 0x108,
+    DMA0_CT1 = 0x109,
+    DMA0_DA1 = 0x10A,
+    DMA0_SA1 = 0x10B,
+    DMA0_SG1 = 0x10C,
+    DMA0_CR2 = 0x110,
+    DMA0_CT2 = 0x111,
+    DMA0_DA2 = 0x112,
+    DMA0_SA2 = 0x113,
+    DMA0_SG2 = 0x114,
+    DMA0_CR3 = 0x118,
+    DMA0_CT3 = 0x119,
+    DMA0_DA3 = 0x11A,
+    DMA0_SA3 = 0x11B,
+    DMA0_SG3 = 0x11C,
+    DMA0_SR  = 0x120,
+    DMA0_SGC = 0x123,
+    DMA0_SLP = 0x125,
+    DMA0_POL = 0x126,
+};
+
+typedef struct ppc405_dma_t ppc405_dma_t;
+struct ppc405_dma_t {
+    qemu_irq irqs[4];
+    uint32_t cr[4];
+    uint32_t ct[4];
+    uint32_t da[4];
+    uint32_t sa[4];
+    uint32_t sg[4];
+    uint32_t sr;
+    uint32_t sgc;
+    uint32_t slp;
+    uint32_t pol;
+};
+
+static target_ulong dcr_read_dma (void *opaque, int dcrn)
+{
+    ppc405_dma_t *dma;
+
+    dma = opaque;
+
+    return 0;
+}
+
+static void dcr_write_dma (void *opaque, int dcrn, target_ulong val)
+{
+    ppc405_dma_t *dma;
+
+    dma = opaque;
+}
+
+static void ppc405_dma_reset (void *opaque)
+{
+    ppc405_dma_t *dma;
+    int i;
+
+    dma = opaque;
+    for (i = 0; i < 4; i++) {
+        dma->cr[i] = 0x00000000;
+        dma->ct[i] = 0x00000000;
+        dma->da[i] = 0x00000000;
+        dma->sa[i] = 0x00000000;
+        dma->sg[i] = 0x00000000;
+    }
+    dma->sr = 0x00000000;
+    dma->sgc = 0x00000000;
+    dma->slp = 0x7C000000;
+    dma->pol = 0x00000000;
+}
+
+void ppc405_dma_init (CPUState *env, qemu_irq irqs[4])
+{
+    ppc405_dma_t *dma;
+
+    dma = qemu_mallocz(sizeof(ppc405_dma_t));
+    if (dma != NULL) {
+        memcpy(dma->irqs, irqs, 4 * sizeof(qemu_irq));
+        ppc405_dma_reset(dma);
+        qemu_register_reset(&ppc405_dma_reset, dma);
+        ppc_dcr_register(env, DMA0_CR0,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_CT0,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_DA0,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SA0,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SG0,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_CR1,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_CT1,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_DA1,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SA1,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SG1,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_CR2,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_CT2,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_DA2,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SA2,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SG2,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_CR3,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_CT3,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_DA3,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SA3,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SG3,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SR,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SGC,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SLP,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_POL,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+    }
+}
+
+/*****************************************************************************/
+/* GPIO */
+typedef struct ppc405_gpio_t ppc405_gpio_t;
+struct ppc405_gpio_t {
+    target_phys_addr_t base;
+    uint32_t or;
+    uint32_t tcr;
+    uint32_t osrh;
+    uint32_t osrl;
+    uint32_t tsrh;
+    uint32_t tsrl;
+    uint32_t odr;
+    uint32_t ir;
+    uint32_t rr1;
+    uint32_t isr1h;
+    uint32_t isr1l;
+};
+
+static uint32_t ppc405_gpio_readb (void *opaque, target_phys_addr_t addr)
+{
+    ppc405_gpio_t *gpio;
+
+    gpio = opaque;
+#ifdef DEBUG_GPIO
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+
+    return 0;
+}
+
+static void ppc405_gpio_writeb (void *opaque,
+                                target_phys_addr_t addr, uint32_t value)
+{
+    ppc405_gpio_t *gpio;
+
+    gpio = opaque;
+#ifdef DEBUG_GPIO
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+}
+
+static uint32_t ppc405_gpio_readw (void *opaque, target_phys_addr_t addr)
+{
+    ppc405_gpio_t *gpio;
+
+    gpio = opaque;
+#ifdef DEBUG_GPIO
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+
+    return 0;
+}
+
+static void ppc405_gpio_writew (void *opaque,
+                                target_phys_addr_t addr, uint32_t value)
+{
+    ppc405_gpio_t *gpio;
+
+    gpio = opaque;
+#ifdef DEBUG_GPIO
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+}
+
+static uint32_t ppc405_gpio_readl (void *opaque, target_phys_addr_t addr)
+{
+    ppc405_gpio_t *gpio;
+
+    gpio = opaque;
+#ifdef DEBUG_GPIO
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+
+    return 0;
+}
+
+static void ppc405_gpio_writel (void *opaque,
+                                target_phys_addr_t addr, uint32_t value)
+{
+    ppc405_gpio_t *gpio;
+
+    gpio = opaque;
+#ifdef DEBUG_GPIO
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+}
+
+static CPUReadMemoryFunc *ppc405_gpio_read[] = {
+    &ppc405_gpio_readb,
+    &ppc405_gpio_readw,
+    &ppc405_gpio_readl,
+};
+
+static CPUWriteMemoryFunc *ppc405_gpio_write[] = {
+    &ppc405_gpio_writeb,
+    &ppc405_gpio_writew,
+    &ppc405_gpio_writel,
+};
+
+static void ppc405_gpio_reset (void *opaque)
+{
+    ppc405_gpio_t *gpio;
+
+    gpio = opaque;
+}
+
+void ppc405_gpio_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                       target_phys_addr_t offset)
+{
+    ppc405_gpio_t *gpio;
+
+    gpio = qemu_mallocz(sizeof(ppc405_gpio_t));
+    if (gpio != NULL) {
+        gpio->base = offset;
+        ppc405_gpio_reset(gpio);
+        qemu_register_reset(&ppc405_gpio_reset, gpio);
+#ifdef DEBUG_GPIO
+        printf("%s: offset=" PADDRX "\n", __func__, offset);
+#endif
+        ppc4xx_mmio_register(env, mmio, offset, 0x038,
+                             ppc405_gpio_read, ppc405_gpio_write, gpio);
+    }
+}
+
+/*****************************************************************************/
+/* Serial ports */
+static CPUReadMemoryFunc *serial_mm_read[] = {
+    &serial_mm_readb,
+    &serial_mm_readw,
+    &serial_mm_readl,
+};
+
+static CPUWriteMemoryFunc *serial_mm_write[] = {
+    &serial_mm_writeb,
+    &serial_mm_writew,
+    &serial_mm_writel,
+};
+
+void ppc405_serial_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                         target_phys_addr_t offset, qemu_irq irq,
+                         CharDriverState *chr)
+{
+    void *serial;
+
+#ifdef DEBUG_SERIAL
+    printf("%s: offset=" PADDRX "\n", __func__, offset);
+#endif
+    serial = serial_mm_init(offset, 0, irq, chr, 0);
+    ppc4xx_mmio_register(env, mmio, offset, 0x008,
+                         serial_mm_read, serial_mm_write, serial);
+}
+
+/*****************************************************************************/
+/* On Chip Memory */
+enum {
+    OCM0_ISARC   = 0x018,
+    OCM0_ISACNTL = 0x019,
+    OCM0_DSARC   = 0x01A,
+    OCM0_DSACNTL = 0x01B,
+};
+
+typedef struct ppc405_ocm_t ppc405_ocm_t;
+struct ppc405_ocm_t {
+    target_ulong offset;
+    uint32_t isarc;
+    uint32_t isacntl;
+    uint32_t dsarc;
+    uint32_t dsacntl;
+};
+
+static void ocm_update_mappings (ppc405_ocm_t *ocm,
+                                 uint32_t isarc, uint32_t isacntl,
+                                 uint32_t dsarc, uint32_t dsacntl)
+{
+#ifdef DEBUG_OCM
+    printf("OCM update ISA %08x %08x (%08x %08x) DSA %08x %08x (%08x %08x)\n",
+           isarc, isacntl, dsarc, dsacntl,
+           ocm->isarc, ocm->isacntl, ocm->dsarc, ocm->dsacntl);
+#endif
+    if (ocm->isarc != isarc ||
+        (ocm->isacntl & 0x80000000) != (isacntl & 0x80000000)) {
+        if (ocm->isacntl & 0x80000000) {
+            /* Unmap previously assigned memory region */
+            printf("OCM unmap ISA %08x\n", ocm->isarc);
+            cpu_register_physical_memory(ocm->isarc, 0x04000000,
+                                         IO_MEM_UNASSIGNED);
+        }
+        if (isacntl & 0x80000000) {
+            /* Map new instruction memory region */
+#ifdef DEBUG_OCM
+            printf("OCM map ISA %08x\n", isarc);
+#endif
+            cpu_register_physical_memory(isarc, 0x04000000,
+                                         ocm->offset | IO_MEM_RAM);
+        }
+    }
+    if (ocm->dsarc != dsarc ||
+        (ocm->dsacntl & 0x80000000) != (dsacntl & 0x80000000)) {
+        if (ocm->dsacntl & 0x80000000) {
+            /* Beware not to unmap the region we just mapped */
+            if (!(isacntl & 0x80000000) || ocm->dsarc != isarc) {
+                /* Unmap previously assigned memory region */
+#ifdef DEBUG_OCM
+                printf("OCM unmap DSA %08x\n", ocm->dsarc);
+#endif
+                cpu_register_physical_memory(ocm->dsarc, 0x04000000,
+                                             IO_MEM_UNASSIGNED);
+            }
+        }
+        if (dsacntl & 0x80000000) {
+            /* Beware not to remap the region we just mapped */
+            if (!(isacntl & 0x80000000) || dsarc != isarc) {
+                /* Map new data memory region */
+#ifdef DEBUG_OCM
+                printf("OCM map DSA %08x\n", dsarc);
+#endif
+                cpu_register_physical_memory(dsarc, 0x04000000,
+                                             ocm->offset | IO_MEM_RAM);
+            }
+        }
+    }
+}
+
+static target_ulong dcr_read_ocm (void *opaque, int dcrn)
+{
+    ppc405_ocm_t *ocm;
+    target_ulong ret;
+
+    ocm = opaque;
+    switch (dcrn) {
+    case OCM0_ISARC:
+        ret = ocm->isarc;
+        break;
+    case OCM0_ISACNTL:
+        ret = ocm->isacntl;
+        break;
+    case OCM0_DSARC:
+        ret = ocm->dsarc;
+        break;
+    case OCM0_DSACNTL:
+        ret = ocm->dsacntl;
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_ocm (void *opaque, int dcrn, target_ulong val)
+{
+    ppc405_ocm_t *ocm;
+    uint32_t isarc, dsarc, isacntl, dsacntl;
+
+    ocm = opaque;
+    isarc = ocm->isarc;
+    dsarc = ocm->dsarc;
+    isacntl = ocm->isacntl;
+    dsacntl = ocm->dsacntl;
+    switch (dcrn) {
+    case OCM0_ISARC:
+        isarc = val & 0xFC000000;
+        break;
+    case OCM0_ISACNTL:
+        isacntl = val & 0xC0000000;
+        break;
+    case OCM0_DSARC:
+        isarc = val & 0xFC000000;
+        break;
+    case OCM0_DSACNTL:
+        isacntl = val & 0xC0000000;
+        break;
+    }
+    ocm_update_mappings(ocm, isarc, isacntl, dsarc, dsacntl);
+    ocm->isarc = isarc;
+    ocm->dsarc = dsarc;
+    ocm->isacntl = isacntl;
+    ocm->dsacntl = dsacntl;
+}
+
+static void ocm_reset (void *opaque)
+{
+    ppc405_ocm_t *ocm;
+    uint32_t isarc, dsarc, isacntl, dsacntl;
+
+    ocm = opaque;
+    isarc = 0x00000000;
+    isacntl = 0x00000000;
+    dsarc = 0x00000000;
+    dsacntl = 0x00000000;
+    ocm_update_mappings(ocm, isarc, isacntl, dsarc, dsacntl);
+    ocm->isarc = isarc;
+    ocm->dsarc = dsarc;
+    ocm->isacntl = isacntl;
+    ocm->dsacntl = dsacntl;
+}
+
+void ppc405_ocm_init (CPUState *env, unsigned long offset)
+{
+    ppc405_ocm_t *ocm;
+
+    ocm = qemu_mallocz(sizeof(ppc405_ocm_t));
+    if (ocm != NULL) {
+        ocm->offset = offset;
+        ocm_reset(ocm);
+        qemu_register_reset(&ocm_reset, ocm);
+        ppc_dcr_register(env, OCM0_ISARC,
+                         ocm, &dcr_read_ocm, &dcr_write_ocm);
+        ppc_dcr_register(env, OCM0_ISACNTL,
+                         ocm, &dcr_read_ocm, &dcr_write_ocm);
+        ppc_dcr_register(env, OCM0_DSARC,
+                         ocm, &dcr_read_ocm, &dcr_write_ocm);
+        ppc_dcr_register(env, OCM0_DSACNTL,
+                         ocm, &dcr_read_ocm, &dcr_write_ocm);
+    }
+}
+
+/*****************************************************************************/
+/* I2C controller */
+typedef struct ppc4xx_i2c_t ppc4xx_i2c_t;
+struct ppc4xx_i2c_t {
+    target_phys_addr_t base;
+    qemu_irq irq;
+    uint8_t mdata;
+    uint8_t lmadr;
+    uint8_t hmadr;
+    uint8_t cntl;
+    uint8_t mdcntl;
+    uint8_t sts;
+    uint8_t extsts;
+    uint8_t sdata;
+    uint8_t lsadr;
+    uint8_t hsadr;
+    uint8_t clkdiv;
+    uint8_t intrmsk;
+    uint8_t xfrcnt;
+    uint8_t xtcntlss;
+    uint8_t directcntl;
+};
+
+static uint32_t ppc4xx_i2c_readb (void *opaque, target_phys_addr_t addr)
+{
+    ppc4xx_i2c_t *i2c;
+    uint32_t ret;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+    i2c = opaque;
+    switch (addr - i2c->base) {
+    case 0x00:
+        //        i2c_readbyte(&i2c->mdata);
+        ret = i2c->mdata;
+        break;
+    case 0x02:
+        ret = i2c->sdata;
+        break;
+    case 0x04:
+        ret = i2c->lmadr;
+        break;
+    case 0x05:
+        ret = i2c->hmadr;
+        break;
+    case 0x06:
+        ret = i2c->cntl;
+        break;
+    case 0x07:
+        ret = i2c->mdcntl;
+        break;
+    case 0x08:
+        ret = i2c->sts;
+        break;
+    case 0x09:
+        ret = i2c->extsts;
+        break;
+    case 0x0A:
+        ret = i2c->lsadr;
+        break;
+    case 0x0B:
+        ret = i2c->hsadr;
+        break;
+    case 0x0C:
+        ret = i2c->clkdiv;
+        break;
+    case 0x0D:
+        ret = i2c->intrmsk;
+        break;
+    case 0x0E:
+        ret = i2c->xfrcnt;
+        break;
+    case 0x0F:
+        ret = i2c->xtcntlss;
+        break;
+    case 0x10:
+        ret = i2c->directcntl;
+        break;
+    default:
+        ret = 0x00;
+        break;
+    }
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX " %02x\n", __func__, addr, ret);
+#endif
+
+    return ret;
+}
+
+static void ppc4xx_i2c_writeb (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
+{
+    ppc4xx_i2c_t *i2c;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    i2c = opaque;
+    switch (addr - i2c->base) {
+    case 0x00:
+        i2c->mdata = value;
+        //        i2c_sendbyte(&i2c->mdata);
+        break;
+    case 0x02:
+        i2c->sdata = value;
+        break;
+    case 0x04:
+        i2c->lmadr = value;
+        break;
+    case 0x05:
+        i2c->hmadr = value;
+        break;
+    case 0x06:
+        i2c->cntl = value;
+        break;
+    case 0x07:
+        i2c->mdcntl = value & 0xDF;
+        break;
+    case 0x08:
+        i2c->sts &= ~(value & 0x0A);
+        break;
+    case 0x09:
+        i2c->extsts &= ~(value & 0x8F);
+        break;
+    case 0x0A:
+        i2c->lsadr = value;
+        break;
+    case 0x0B:
+        i2c->hsadr = value;
+        break;
+    case 0x0C:
+        i2c->clkdiv = value;
+        break;
+    case 0x0D:
+        i2c->intrmsk = value;
+        break;
+    case 0x0E:
+        i2c->xfrcnt = value & 0x77;
+        break;
+    case 0x0F:
+        i2c->xtcntlss = value;
+        break;
+    case 0x10:
+        i2c->directcntl = value & 0x7;
+        break;
+    }
+}
+
+static uint32_t ppc4xx_i2c_readw (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+    ret = ppc4xx_i2c_readb(opaque, addr) << 8;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 1);
+
+    return ret;
+}
+
+static void ppc4xx_i2c_writew (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    ppc4xx_i2c_writeb(opaque, addr, value >> 8);
+    ppc4xx_i2c_writeb(opaque, addr + 1, value);
+}
+
+static uint32_t ppc4xx_i2c_readl (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+    ret = ppc4xx_i2c_readb(opaque, addr) << 24;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 3);
+
+    return ret;
+}
+
+static void ppc4xx_i2c_writel (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    ppc4xx_i2c_writeb(opaque, addr, value >> 24);
+    ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16);
+    ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8);
+    ppc4xx_i2c_writeb(opaque, addr + 3, value);
+}
+
+static CPUReadMemoryFunc *i2c_read[] = {
+    &ppc4xx_i2c_readb,
+    &ppc4xx_i2c_readw,
+    &ppc4xx_i2c_readl,
+};
+
+static CPUWriteMemoryFunc *i2c_write[] = {
+    &ppc4xx_i2c_writeb,
+    &ppc4xx_i2c_writew,
+    &ppc4xx_i2c_writel,
+};
+
+static void ppc4xx_i2c_reset (void *opaque)
+{
+    ppc4xx_i2c_t *i2c;
+
+    i2c = opaque;
+    i2c->mdata = 0x00;
+    i2c->sdata = 0x00;
+    i2c->cntl = 0x00;
+    i2c->mdcntl = 0x00;
+    i2c->sts = 0x00;
+    i2c->extsts = 0x00;
+    i2c->clkdiv = 0x00;
+    i2c->xfrcnt = 0x00;
+    i2c->directcntl = 0x0F;
+}
+
+void ppc405_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                      target_phys_addr_t offset, qemu_irq irq)
+{
+    ppc4xx_i2c_t *i2c;
+
+    i2c = qemu_mallocz(sizeof(ppc4xx_i2c_t));
+    if (i2c != NULL) {
+        i2c->base = offset;
+        i2c->irq = irq;
+        ppc4xx_i2c_reset(i2c);
+#ifdef DEBUG_I2C
+        printf("%s: offset=" PADDRX "\n", __func__, offset);
+#endif
+        ppc4xx_mmio_register(env, mmio, offset, 0x011,
+                             i2c_read, i2c_write, i2c);
+        qemu_register_reset(ppc4xx_i2c_reset, i2c);
+    }
+}
+
+/*****************************************************************************/
+/* General purpose timers */
+typedef struct ppc4xx_gpt_t ppc4xx_gpt_t;
+struct ppc4xx_gpt_t {
+    target_phys_addr_t base;
+    int64_t tb_offset;
+    uint32_t tb_freq;
+    struct QEMUTimer *timer;
+    qemu_irq irqs[5];
+    uint32_t oe;
+    uint32_t ol;
+    uint32_t im;
+    uint32_t is;
+    uint32_t ie;
+    uint32_t comp[5];
+    uint32_t mask[5];
+};
+
+static uint32_t ppc4xx_gpt_readb (void *opaque, target_phys_addr_t addr)
+{
+#ifdef DEBUG_GPT
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+    /* XXX: generate a bus fault */
+    return -1;
+}
+
+static void ppc4xx_gpt_writeb (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    /* XXX: generate a bus fault */
+}
+
+static uint32_t ppc4xx_gpt_readw (void *opaque, target_phys_addr_t addr)
+{
+#ifdef DEBUG_GPT
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+    /* XXX: generate a bus fault */
+    return -1;
+}
+
+static void ppc4xx_gpt_writew (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    /* XXX: generate a bus fault */
+}
+
+static int ppc4xx_gpt_compare (ppc4xx_gpt_t *gpt, int n)
+{
+    /* XXX: TODO */
+    return 0;
+}
+
+static void ppc4xx_gpt_set_output (ppc4xx_gpt_t *gpt, int n, int level)
+{
+    /* XXX: TODO */
+}
+
+static void ppc4xx_gpt_set_outputs (ppc4xx_gpt_t *gpt)
+{
+    uint32_t mask;
+    int i;
+
+    mask = 0x80000000;
+    for (i = 0; i < 5; i++) {
+        if (gpt->oe & mask) {
+            /* Output is enabled */
+            if (ppc4xx_gpt_compare(gpt, i)) {
+                /* Comparison is OK */
+                ppc4xx_gpt_set_output(gpt, i, gpt->ol & mask);
+            } else {
+                /* Comparison is KO */
+                ppc4xx_gpt_set_output(gpt, i, gpt->ol & mask ? 0 : 1);
+            }
+        }
+        mask = mask >> 1;
+    }
+        
+}
+
+static void ppc4xx_gpt_set_irqs (ppc4xx_gpt_t *gpt)
+{
+    uint32_t mask;
+    int i;
+
+    mask = 0x00008000;
+    for (i = 0; i < 5; i++) {
+        if (gpt->is & gpt->im & mask)
+            qemu_irq_raise(gpt->irqs[i]);
+        else
+            qemu_irq_lower(gpt->irqs[i]);
+        mask = mask >> 1;
+    }
+        
+}
+
+static void ppc4xx_gpt_compute_timer (ppc4xx_gpt_t *gpt)
+{
+    /* XXX: TODO */
+}
+
+static uint32_t ppc4xx_gpt_readl (void *opaque, target_phys_addr_t addr)
+{
+    ppc4xx_gpt_t *gpt;
+    uint32_t ret;
+    int idx;
+
+#ifdef DEBUG_GPT
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+    gpt = opaque;
+    switch (addr - gpt->base) {
+    case 0x00:
+        /* Time base counter */
+        ret = muldiv64(qemu_get_clock(vm_clock) + gpt->tb_offset,
+                       gpt->tb_freq, ticks_per_sec);
+        break;
+    case 0x10:
+        /* Output enable */
+        ret = gpt->oe;
+        break;
+    case 0x14:
+        /* Output level */
+        ret = gpt->ol;
+        break;
+    case 0x18:
+        /* Interrupt mask */
+        ret = gpt->im;
+        break;
+    case 0x1C:
+    case 0x20:
+        /* Interrupt status */
+        ret = gpt->is;
+        break;
+    case 0x24:
+        /* Interrupt enable */
+        ret = gpt->ie;
+        break;
+    case 0x80 ... 0x90:
+        /* Compare timer */
+        idx = ((addr - gpt->base) - 0x80) >> 2;
+        ret = gpt->comp[idx];
+        break;
+    case 0xC0 ... 0xD0:
+        /* Compare mask */
+        idx = ((addr - gpt->base) - 0xC0) >> 2;
+        ret = gpt->mask[idx];
+        break;
+    default:
+        ret = -1;
+        break;
+    }
+
+    return ret;
+}
+
+static void ppc4xx_gpt_writel (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
+{
+    ppc4xx_gpt_t *gpt;
+    int idx;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    gpt = opaque;
+    switch (addr - gpt->base) {
+    case 0x00:
+        /* Time base counter */
+        gpt->tb_offset = muldiv64(value, ticks_per_sec, gpt->tb_freq)
+            - qemu_get_clock(vm_clock);
+        ppc4xx_gpt_compute_timer(gpt);
+        break;
+    case 0x10:
+        /* Output enable */
+        gpt->oe = value & 0xF8000000;
+        ppc4xx_gpt_set_outputs(gpt);
+        break;
+    case 0x14:
+        /* Output level */
+        gpt->ol = value & 0xF8000000;
+        ppc4xx_gpt_set_outputs(gpt);
+        break;
+    case 0x18:
+        /* Interrupt mask */
+        gpt->im = value & 0x0000F800;
+        break;
+    case 0x1C:
+        /* Interrupt status set */
+        gpt->is |= value & 0x0000F800;
+        ppc4xx_gpt_set_irqs(gpt);
+        break;
+    case 0x20:
+        /* Interrupt status clear */
+        gpt->is &= ~(value & 0x0000F800);
+        ppc4xx_gpt_set_irqs(gpt);
+        break;
+    case 0x24:
+        /* Interrupt enable */
+        gpt->ie = value & 0x0000F800;
+        ppc4xx_gpt_set_irqs(gpt);
+        break;
+    case 0x80 ... 0x90:
+        /* Compare timer */
+        idx = ((addr - gpt->base) - 0x80) >> 2;
+        gpt->comp[idx] = value & 0xF8000000;
+        ppc4xx_gpt_compute_timer(gpt);
+        break;
+    case 0xC0 ... 0xD0:
+        /* Compare mask */
+        idx = ((addr - gpt->base) - 0xC0) >> 2;
+        gpt->mask[idx] = value & 0xF8000000;
+        ppc4xx_gpt_compute_timer(gpt);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc *gpt_read[] = {
+    &ppc4xx_gpt_readb,
+    &ppc4xx_gpt_readw,
+    &ppc4xx_gpt_readl,
+};
+
+static CPUWriteMemoryFunc *gpt_write[] = {
+    &ppc4xx_gpt_writeb,
+    &ppc4xx_gpt_writew,
+    &ppc4xx_gpt_writel,
+};
+
+static void ppc4xx_gpt_cb (void *opaque)
+{
+    ppc4xx_gpt_t *gpt;
+
+    gpt = opaque;
+    ppc4xx_gpt_set_irqs(gpt);
+    ppc4xx_gpt_set_outputs(gpt);
+    ppc4xx_gpt_compute_timer(gpt);
+}
+
+static void ppc4xx_gpt_reset (void *opaque)
+{
+    ppc4xx_gpt_t *gpt;
+    int i;
+
+    gpt = opaque;
+    qemu_del_timer(gpt->timer);
+    gpt->oe = 0x00000000;
+    gpt->ol = 0x00000000;
+    gpt->im = 0x00000000;
+    gpt->is = 0x00000000;
+    gpt->ie = 0x00000000;
+    for (i = 0; i < 5; i++) {
+        gpt->comp[i] = 0x00000000;
+        gpt->mask[i] = 0x00000000;
+    }
+}
+
+void ppc4xx_gpt_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                      target_phys_addr_t offset, qemu_irq irqs[5])
+{
+    ppc4xx_gpt_t *gpt;
+    int i;
+
+    gpt = qemu_mallocz(sizeof(ppc4xx_gpt_t));
+    if (gpt != NULL) {
+        gpt->base = offset;
+        for (i = 0; i < 5; i++)
+            gpt->irqs[i] = irqs[i];
+        gpt->timer = qemu_new_timer(vm_clock, &ppc4xx_gpt_cb, gpt);
+        ppc4xx_gpt_reset(gpt);
+#ifdef DEBUG_GPT
+        printf("%s: offset=" PADDRX "\n", __func__, offset);
+#endif
+        ppc4xx_mmio_register(env, mmio, offset, 0x0D4,
+                             gpt_read, gpt_write, gpt);
+        qemu_register_reset(ppc4xx_gpt_reset, gpt);
+    }
+}
+
+/*****************************************************************************/
+/* MAL */
+enum {
+    MAL0_CFG      = 0x180,
+    MAL0_ESR      = 0x181,
+    MAL0_IER      = 0x182,
+    MAL0_TXCASR   = 0x184,
+    MAL0_TXCARR   = 0x185,
+    MAL0_TXEOBISR = 0x186,
+    MAL0_TXDEIR   = 0x187,
+    MAL0_RXCASR   = 0x190,
+    MAL0_RXCARR   = 0x191,
+    MAL0_RXEOBISR = 0x192,
+    MAL0_RXDEIR   = 0x193,
+    MAL0_TXCTP0R  = 0x1A0,
+    MAL0_TXCTP1R  = 0x1A1,
+    MAL0_TXCTP2R  = 0x1A2,
+    MAL0_TXCTP3R  = 0x1A3,
+    MAL0_RXCTP0R  = 0x1C0,
+    MAL0_RXCTP1R  = 0x1C1,
+    MAL0_RCBS0    = 0x1E0,
+    MAL0_RCBS1    = 0x1E1,
+};
+
+typedef struct ppc40x_mal_t ppc40x_mal_t;
+struct ppc40x_mal_t {
+    qemu_irq irqs[4];
+    uint32_t cfg;
+    uint32_t esr;
+    uint32_t ier;
+    uint32_t txcasr;
+    uint32_t txcarr;
+    uint32_t txeobisr;
+    uint32_t txdeir;
+    uint32_t rxcasr;
+    uint32_t rxcarr;
+    uint32_t rxeobisr;
+    uint32_t rxdeir;
+    uint32_t txctpr[4];
+    uint32_t rxctpr[2];
+    uint32_t rcbs[2];
+};
+
+static void ppc40x_mal_reset (void *opaque);
+
+static target_ulong dcr_read_mal (void *opaque, int dcrn)
+{
+    ppc40x_mal_t *mal;
+    target_ulong ret;
+
+    mal = opaque;
+    switch (dcrn) {
+    case MAL0_CFG:
+        ret = mal->cfg;
+        break;
+    case MAL0_ESR:
+        ret = mal->esr;
+        break;
+    case MAL0_IER:
+        ret = mal->ier;
+        break;
+    case MAL0_TXCASR:
+        ret = mal->txcasr;
+        break;
+    case MAL0_TXCARR:
+        ret = mal->txcarr;
+        break;
+    case MAL0_TXEOBISR:
+        ret = mal->txeobisr;
+        break;
+    case MAL0_TXDEIR:
+        ret = mal->txdeir;
+        break;
+    case MAL0_RXCASR:
+        ret = mal->rxcasr;
+        break;
+    case MAL0_RXCARR:
+        ret = mal->rxcarr;
+        break;
+    case MAL0_RXEOBISR:
+        ret = mal->rxeobisr;
+        break;
+    case MAL0_RXDEIR:
+        ret = mal->rxdeir;
+        break;
+    case MAL0_TXCTP0R:
+        ret = mal->txctpr[0];
+        break;
+    case MAL0_TXCTP1R:
+        ret = mal->txctpr[1];
+        break;
+    case MAL0_TXCTP2R:
+        ret = mal->txctpr[2];
+        break;
+    case MAL0_TXCTP3R:
+        ret = mal->txctpr[3];
+        break;
+    case MAL0_RXCTP0R:
+        ret = mal->rxctpr[0];
+        break;
+    case MAL0_RXCTP1R:
+        ret = mal->rxctpr[1];
+        break;
+    case MAL0_RCBS0:
+        ret = mal->rcbs[0];
+        break;
+    case MAL0_RCBS1:
+        ret = mal->rcbs[1];
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_mal (void *opaque, int dcrn, target_ulong val)
+{
+    ppc40x_mal_t *mal;
+    int idx;
+
+    mal = opaque;
+    switch (dcrn) {
+    case MAL0_CFG:
+        if (val & 0x80000000)
+            ppc40x_mal_reset(mal);
+        mal->cfg = val & 0x00FFC087;
+        break;
+    case MAL0_ESR:
+        /* Read/clear */
+        mal->esr &= ~val;
+        break;
+    case MAL0_IER:
+        mal->ier = val & 0x0000001F;
+        break;
+    case MAL0_TXCASR:
+        mal->txcasr = val & 0xF0000000;
+        break;
+    case MAL0_TXCARR:
+        mal->txcarr = val & 0xF0000000;
+        break;
+    case MAL0_TXEOBISR:
+        /* Read/clear */
+        mal->txeobisr &= ~val;
+        break;
+    case MAL0_TXDEIR:
+        /* Read/clear */
+        mal->txdeir &= ~val;
+        break;
+    case MAL0_RXCASR:
+        mal->rxcasr = val & 0xC0000000;
+        break;
+    case MAL0_RXCARR:
+        mal->rxcarr = val & 0xC0000000;
+        break;
+    case MAL0_RXEOBISR:
+        /* Read/clear */
+        mal->rxeobisr &= ~val;
+        break;
+    case MAL0_RXDEIR:
+        /* Read/clear */
+        mal->rxdeir &= ~val;
+        break;
+    case MAL0_TXCTP0R:
+        idx = 0;
+        goto update_tx_ptr;
+    case MAL0_TXCTP1R:
+        idx = 1;
+        goto update_tx_ptr;
+    case MAL0_TXCTP2R:
+        idx = 2;
+        goto update_tx_ptr;
+    case MAL0_TXCTP3R:
+        idx = 3;
+    update_tx_ptr:
+        mal->txctpr[idx] = val;
+        break;
+    case MAL0_RXCTP0R:
+        idx = 0;
+        goto update_rx_ptr;
+    case MAL0_RXCTP1R:
+        idx = 1;
+    update_rx_ptr:
+        mal->rxctpr[idx] = val;
+        break;
+    case MAL0_RCBS0:
+        idx = 0;
+        goto update_rx_size;
+    case MAL0_RCBS1:
+        idx = 1;
+    update_rx_size:
+        mal->rcbs[idx] = val & 0x000000FF;
+        break;
+    }
+}
+
+static void ppc40x_mal_reset (void *opaque)
+{
+    ppc40x_mal_t *mal;
+
+    mal = opaque;
+    mal->cfg = 0x0007C000;
+    mal->esr = 0x00000000;
+    mal->ier = 0x00000000;
+    mal->rxcasr = 0x00000000;
+    mal->rxdeir = 0x00000000;
+    mal->rxeobisr = 0x00000000;
+    mal->txcasr = 0x00000000;
+    mal->txdeir = 0x00000000;
+    mal->txeobisr = 0x00000000;
+}
+
+void ppc405_mal_init (CPUState *env, qemu_irq irqs[4])
+{
+    ppc40x_mal_t *mal;
+    int i;
+
+    mal = qemu_mallocz(sizeof(ppc40x_mal_t));
+    if (mal != NULL) {
+        for (i = 0; i < 4; i++)
+            mal->irqs[i] = irqs[i];
+        ppc40x_mal_reset(mal);
+        qemu_register_reset(&ppc40x_mal_reset, mal);
+        ppc_dcr_register(env, MAL0_CFG,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_ESR,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_IER,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_TXCASR,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_TXCARR,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_TXEOBISR,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_TXDEIR,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_RXCASR,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_RXCARR,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_RXEOBISR,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_RXDEIR,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_TXCTP0R,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_TXCTP1R,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_TXCTP2R,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_TXCTP3R,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_RXCTP0R,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_RXCTP1R,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_RCBS0,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_RCBS1,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+    }
+}
+
+/*****************************************************************************/
+/* SPR */
+void ppc40x_core_reset (CPUState *env)
+{
+    target_ulong dbsr;
+
+    printf("Reset PowerPC core\n");
+    cpu_ppc_reset(env);
+    dbsr = env->spr[SPR_40x_DBSR];
+    dbsr &= ~0x00000300;
+    dbsr |= 0x00000100;
+    env->spr[SPR_40x_DBSR] = dbsr;
+    cpu_loop_exit();
+}
+
+void ppc40x_chip_reset (CPUState *env)
+{
+    target_ulong dbsr;
+
+    printf("Reset PowerPC chip\n");
+    cpu_ppc_reset(env);
+    /* XXX: TODO reset all internal peripherals */
+    dbsr = env->spr[SPR_40x_DBSR];
+    db