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

[Xen-changelog] [xen-unstable] [qemu] Update ioemu to qemu 0.8.2.



# HG changeset patch
# User chris@xxxxxxxxxxxxxxxxxxxxxxxx
# Node ID 08a11694b109f7c1938494fe64d001e8864a1bbe
# Parent  fd59667e5365483e59c034542f3091f9cc7dc091
[qemu] Update ioemu to qemu 0.8.2.

Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxxx>
---
 tools/ioemu/Changelog               |   19 
 tools/ioemu/Makefile                |   31 
 tools/ioemu/Makefile.target         |   54 -
 tools/ioemu/TODO                    |    2 
 tools/ioemu/VERSION                 |    2 
 tools/ioemu/audio/alsaaudio.c       |   23 
 tools/ioemu/audio/audio.c           |  448 ++++++++-
 tools/ioemu/audio/audio.h           |   46 
 tools/ioemu/audio/audio_int.h       |   42 
 tools/ioemu/audio/audio_template.h  |   33 
 tools/ioemu/audio/coreaudio.c       |   16 
 tools/ioemu/audio/dsound_template.h |   20 
 tools/ioemu/audio/dsoundaudio.c     |    8 
 tools/ioemu/audio/fmodaudio.c       |   10 
 tools/ioemu/audio/noaudio.c         |   40 
 tools/ioemu/audio/ossaudio.c        |   44 
 tools/ioemu/audio/rate_template.h   |    2 
 tools/ioemu/audio/sdlaudio.c        |   10 
 tools/ioemu/audio/wavaudio.c        |    4 
 tools/ioemu/audio/wavcapture.c      |  164 +++
 tools/ioemu/block-cow.c             |    7 
 tools/ioemu/block-qcow.c            |    7 
 tools/ioemu/block-vmdk.c            |    7 
 tools/ioemu/block-vpc.c             |    2 
 tools/ioemu/block-vvfat.c           |    1 
 tools/ioemu/block.c                 |   61 +
 tools/ioemu/block_int.h             |    1 
 tools/ioemu/cocoa.m                 |   60 -
 tools/ioemu/configure               |   45 
 tools/ioemu/console.c               |  170 ++-
 tools/ioemu/cpu-all.h               |  102 +-
 tools/ioemu/cpu-defs.h              |    2 
 tools/ioemu/cpu-exec.c              |   49 
 tools/ioemu/disas.c                 |    4 
 tools/ioemu/dyngen-exec.h           |   27 
 tools/ioemu/dyngen.c                |   92 +
 tools/ioemu/dyngen.h                |    8 
 tools/ioemu/elf.h                   |    2 
 tools/ioemu/exec-all.h              |    2 
 tools/ioemu/exec.c                  |   33 
 tools/ioemu/fpu/softfloat-native.c  |   13 
 tools/ioemu/gdbstub.c               |  131 +-
 tools/ioemu/hw/acpi-dsdt.dsl        |  559 +++++++++++
 tools/ioemu/hw/acpi-dsdt.hex        |  278 +++++
 tools/ioemu/hw/acpi.c               |  615 ++++++++++++
 tools/ioemu/hw/adlib.c              |    4 
 tools/ioemu/hw/apb_pci.c            |  232 ++++
 tools/ioemu/hw/apic.c               |    4 
 tools/ioemu/hw/cdrom.c              |  156 +++
 tools/ioemu/hw/cuda.c               |    2 
 tools/ioemu/hw/es1370.c             |   10 
 tools/ioemu/hw/esp.c                |  538 +++-------
 tools/ioemu/hw/grackle_pci.c        |  156 +++
 tools/ioemu/hw/i8259.c              |    2 
 tools/ioemu/hw/ide.c                |  134 --
 tools/ioemu/hw/lsi53c895a.c         | 1571 +++++++++++++++++++++++++++++++
 tools/ioemu/hw/m48t59.c             |   10 
 tools/ioemu/hw/mips_r4k.c           |    6 
 tools/ioemu/hw/ne2000.c             |    2 
 tools/ioemu/hw/pc.c                 |   59 -
 tools/ioemu/hw/pci.c                | 1489 +----------------------------
 tools/ioemu/hw/pci_host.h           |   93 +
 tools/ioemu/hw/pcnet.c              | 1789 ++++++++++++++++++++++++++++++++++++
 tools/ioemu/hw/pcspk.c              |    4 
 tools/ioemu/hw/pflash_cfi02.c       |  624 ++++++++++++
 tools/ioemu/hw/piix4acpi.c          |    4 
 tools/ioemu/hw/piix_pci.c           |  435 ++++++++
 tools/ioemu/hw/pl050.c              |    2 
 tools/ioemu/hw/ppc_chrp.c           |   20 
 tools/ioemu/hw/ppc_prep.c           |    4 
 tools/ioemu/hw/prep_pci.c           |  167 +++
 tools/ioemu/hw/rtl8139.c            | 1494 +++++++++++++++++++++---------
 tools/ioemu/hw/sb16.c               |   94 +
 tools/ioemu/hw/scsi-disk.c          |  478 +++++++++
 tools/ioemu/hw/sh7750.c             |    2 
 tools/ioemu/hw/slavio_intctl.c      |    2 
 tools/ioemu/hw/slavio_timer.c       |    2 
 tools/ioemu/hw/sun4m.c              |   14 
 tools/ioemu/hw/sun4u.c              |   18 
 tools/ioemu/hw/unin_pci.c           |  261 +++++
 tools/ioemu/hw/usb-hid.c            |   14 
 tools/ioemu/hw/usb-hub.c            |   26 
 tools/ioemu/hw/usb-msd.c            |  402 ++++++++
 tools/ioemu/hw/usb-ohci.c           | 1190 +++++++++++++++++++++++
 tools/ioemu/hw/usb-uhci.c           |   22 
 tools/ioemu/hw/usb.h                |   18 
 tools/ioemu/hw/versatile_pci.c      |  119 ++
 tools/ioemu/hw/versatilepb.c        |  216 ++++
 tools/ioemu/hw/vga.c                |  137 +-
 tools/ioemu/hw/vga_int.h            |    9 
 tools/ioemu/hw/vga_template.h       |  234 ++--
 tools/ioemu/kqemu.c                 |   11 
 tools/ioemu/loader.c                |    2 
 tools/ioemu/monitor.c               |  164 ++-
 tools/ioemu/osdep.c                 |   22 
 tools/ioemu/osdep.h                 |    2 
 tools/ioemu/pc-bios/README          |    8 
 tools/ioemu/pc-bios/bios.diff       |   87 +
 tools/ioemu/pc-bios/vgabios.diff    |  825 +++-------------
 tools/ioemu/qemu-doc.texi           |  250 +++--
 tools/ioemu/qemu-img.c              |   33 
 tools/ioemu/sdl.c                   |   27 
 tools/ioemu/tap-win32.c             |    8 
 tools/ioemu/target-i386/exec.h      |    3 
 tools/ioemu/target-i386/helper.c    |   39 
 tools/ioemu/target-i386/helper2.c   |   33 
 tools/ioemu/target-i386/op.c        |   15 
 tools/ioemu/target-i386/translate.c |   93 +
 tools/ioemu/tests/Makefile          |    3 
 tools/ioemu/tests/test-i386.c       |   22 
 tools/ioemu/usb-linux.c             |   44 
 tools/ioemu/vl.c                    | 1284 +++++++++++++++++--------
 tools/ioemu/vl.h                    |  137 ++
 tools/ioemu/vnc.c                   |  258 ++++-
 tools/ioemu/vnchextile.h            |   48 
 ioemu/pc-bios/video.x               |    0 
 116 files changed, 14710 insertions(+), 4273 deletions(-)

diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/Changelog
--- a/tools/ioemu/Changelog     Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/Changelog     Mon Aug 07 18:25:30 2006 +0100
@@ -1,3 +1,22 @@ version 0.8.1:
+version 0.8.2:
+
+  - ACPI support
+  - PC VGA BIOS fixes
+  - switch to OpenBios for SPARC targets (Blue Swirl)
+  - VNC server fixes
+  - MIPS FPU support (Marius Groeger)
+  - Solaris/SPARC host support (Ben Taylor)
+  - PPC breakpoints and single stepping (Jason Wessel)
+  - USB updates (Paul Brook)
+  - UDP/TCP/telnet character devices (Jason Wessel)
+  - Windows sparse file support (Frediano Ziglio)
+  - RTL8139 NIC TCP segmentation offloading (Igor Kovalenko)
+  - PCNET NIC support (Antony T Curtis)
+  - Support for variable frequency host CPUs
+  - Workaround for win32 SMP hosts
+  - Support for AMD Flash memories (Jocelyn Mayer)
+  - Audio capture to WAV files support (malc)
+
 version 0.8.1:
 
   - USB tablet support (Brad Campbell, Anthony Liguori)
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/Makefile
--- a/tools/ioemu/Makefile      Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/Makefile      Mon Aug 07 18:25:30 2006 +0100
@@ -1,11 +1,19 @@ XEN_ROOT=../..
+# Makefile for QEMU.
+
 XEN_ROOT=../..
 include $(XEN_ROOT)/tools/Rules.mk
 
 -include config-host.mak
 
+.PHONY: all clean distclean dvi info install install-doc tar tarbin \
+       speed test test2 html dvi info
+
 CFLAGS+=-Wall -O2 -g -fno-strict-aliasing -I.
 ifdef CONFIG_DARWIN
 CFLAGS+= -mdynamic-no-pic
+endif
+ifeq ($(ARCH),sparc)
+CFLAGS+=-mcpu=ultrasparc
 endif
 LDFLAGS=-g
 LIBS=
@@ -20,11 +28,15 @@ DOCS=
 DOCS=
 endif
 
-all: $(DOCS)
-       for d in $(TARGET_DIRS); do \
-       $(MAKE) -C $$d $@ || exit 1 ; \
-        done
+TOOLS=
 
+all: $(TOOLS) $(DOCS) recurse-all
+
+subdir-%:
+       $(MAKE) -C $(subst subdir-,,$@) all
+
+recurse-all: $(patsubst %,subdir-%, $(TARGET_DIRS))
+        
 qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c 
block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c
        $(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
 
@@ -42,6 +54,7 @@ clean:
 
 distclean: clean
        rm -f config-host.mak config-host.h $(DOCS)
+       rm -f qemu-{doc,tech}.{info,aux,cp,dvi,fn,info,ky,log,pg,toc,tp,vr}
        for d in $(TARGET_DIRS); do \
        rm -rf $$d || exit 1 ; \
         done
@@ -63,7 +76,7 @@ install: all $(if $(BUILD_DOCS),install-
 #      $(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)"
 #      mkdir -p "$(DESTDIR)$(datadir)"
 #      for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
-#                      video.x proll.elf linux_boot.bin; do \
+#                      video.x openbios-sparc32 linux_boot.bin; do \
 #              $(INSTALL) -m 644 $(SRC_PATH)/pc-bios/$$x 
"$(DESTDIR)$(datadir)"; \
 #      done
 ifndef CONFIG_WIN32
@@ -106,6 +119,12 @@ qemu-img.1: qemu-img.texi
        perl -w $(SRC_PATH)/texi2pod.pl $< qemu-img.pod
        pod2man --section=1 --center=" " --release=" " qemu-img.pod > $@
 
+info: qemu-doc.info qemu-tech.info
+
+dvi: qemu-doc.dvi qemu-tech.dvi
+
+html: qemu-doc.html qemu-tech.html
+
 FILE=qemu-$(shell cat VERSION)
 
 # tar release (use 'make -k tar' on a checkouted tree)
@@ -138,7 +157,7 @@ tarbin:
        $(datadir)/vgabios-cirrus.bin \
        $(datadir)/ppc_rom.bin \
        $(datadir)/video.x \
-       $(datadir)/proll.elf \
+       $(datadir)/openbios-sparc32 \
        $(datadir)/linux_boot.bin \
        $(docdir)/qemu-doc.html \
        $(docdir)/qemu-tech.html \
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/Makefile.target
--- a/tools/ioemu/Makefile.target       Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/Makefile.target       Mon Aug 07 18:25:30 2006 +0100
@@ -40,6 +40,11 @@ ifeq ($(TARGET_ARCH),arm)
     TARGET_ARCH2=armeb
   endif
 endif
+ifeq ($(TARGET_ARCH),sh4)
+  ifeq ($(TARGET_WORDS_BIGENDIAN),yes)
+    TARGET_ARCH2=sh4eb
+  endif
+endif
 ifeq ($(TARGET_ARCH),mips)
   ifneq ($(TARGET_WORDS_BIGENDIAN),yes)
     TARGET_ARCH2=mipsel
@@ -114,17 +119,24 @@ endif
 endif
 
 ifeq ($(ARCH),sparc)
-CFLAGS+=-m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
+ifeq ($(CONFIG_SOLARIS),yes)
+CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g2 -ffixed-g3
+LDFLAGS+=-m32
+OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -fno-omit-frame-pointer -ffixed-i0
+else
+CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
 LDFLAGS+=-m32
 OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
 HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat
 # -static is used to avoid g1/g3 usage by the dynamic linker
 LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc.ld -static
 endif
+endif
 
 ifeq ($(ARCH),sparc64)
-CFLAGS+=-m64 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
+CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7
 LDFLAGS+=-m64
+LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc64.ld
 OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
 endif
 
@@ -186,7 +198,12 @@ main.o: CFLAGS+=-p
 main.o: CFLAGS+=-p
 endif
 
-OBJS= elfload.o main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o 
+OBJS= main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o \
+      elfload.o linuxload.o
+ifdef TARGET_HAS_BFLT
+OBJS+= flatload.o
+endif
+
 ifeq ($(TARGET_ARCH), i386)
 OBJS+= vm86.o
 endif
@@ -323,18 +340,23 @@ ifdef CONFIG_ADLIB
 ifdef CONFIG_ADLIB
 SOUND_HW += fmopl.o adlib.o
 endif
+AUDIODRV+= wavcapture.o
+
+# SCSI layer
+VL_OBJS+= scsi-disk.o cdrom.o lsi53c895a.o
 
 # USB layer
-VL_OBJS+= usb.o usb-hub.o usb-uhci.o usb-linux.o usb-hid.o
+VL_OBJS+= usb.o usb-hub.o usb-linux.o usb-hid.o usb-ohci.o usb-msd.o
 
 # PCI network cards
-VL_OBJS+= ne2000.o rtl8139.o
+VL_OBJS+= ne2000.o rtl8139.o pcnet.o
 
 ifeq ($(TARGET_BASE_ARCH), i386)
 # Hardware support
 VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
 VL_OBJS+= fdc.o mc146818rtc.o serial.o pc.o
-VL_OBJS+= cirrus_vga.o mixeng.o parallel.o
+VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o piix_pci.o
+VL_OBJS+= usb-uhci.o
 VL_OBJS+= piix4acpi.o
 VL_OBJS+= xenstore.o
 DEFINES += -DHAS_AUDIO
@@ -343,6 +365,7 @@ VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.
 VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
 VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
 VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o
+VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o
 DEFINES += -DHAS_AUDIO
 endif
 ifeq ($(TARGET_ARCH), mips)
@@ -351,7 +374,7 @@ endif
 endif
 ifeq ($(TARGET_BASE_ARCH), sparc)
 ifeq ($(TARGET_ARCH), sparc64)
-VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o
+VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o apb_pci.o
 VL_OBJS+= fdc.o mc146818rtc.o serial.o m48t59.o
 VL_OBJS+= cirrus_vga.o parallel.o
 else
@@ -362,6 +385,7 @@ ifeq ($(TARGET_BASE_ARCH), arm)
 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
 endif
 ifeq ($(TARGET_BASE_ARCH), sh4)
 VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o
@@ -399,7 +423,7 @@ ifndef CONFIG_DARWIN
 ifndef CONFIG_DARWIN
 ifndef CONFIG_WIN32
 ifndef CONFIG_SOLARIS
-VL_LIBS=-lutil
+VL_LIBS=-lutil -lrt
 endif
 endif
 endif
@@ -410,6 +434,11 @@ endif
 
 ifeq ($(ARCH),ia64)
 VL_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld
+endif
+
+ifeq ($(ARCH),sparc64)
+VL_LDFLAGS+=-m64
+VL_LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc64.ld
 endif
 
 ifdef CONFIG_WIN32
@@ -490,6 +519,13 @@ endif
 endif
 
 loader.o: loader.c elf_ops.h
+
+acpi.o: acpi.c acpi-dsdt.hex
+
+ifdef BUILD_ACPI_TABLES
+$(SRC_PATH)/hw/acpi-dsdt.hex: acpi-dsdt.dsl
+       iasl -tc -p $@ $<
+endif
 
 ifeq ($(TARGET_ARCH), sh4)
 op.o: op.c op_mem.c cpu.h
@@ -501,6 +537,8 @@ tc58128.o: tc58128.c
 tc58128.o: tc58128.c
 endif
 
+$(OBJS) $(LIBOBJS) $(VL_OBJS): config.h ../config-host.h
+
 %.o: %.c
        $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
 
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/TODO
--- a/tools/ioemu/TODO  Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/TODO  Mon Aug 07 18:25:30 2006 +0100
@@ -1,24 +1,20 @@ short term:
 short term:
 ----------
+- cycle counter for all archs
+- cpu_interrupt() win32/SMP fix
 - support variable tsc freq
-- cpu_interrupt() win32/SMP fix
 - USB host async
 - IDE async
 - debug option in 'configure' script + disable -fomit-frame-pointer
 - Precise VGA timings for old games/demos (malc patch)
 - merge PIC spurious interrupt patch
-- merge Solaris patch
 - warning for OS/2: must not use 128 MB memory (merge bochs cmos patch ?)
 - config file (at least for windows/Mac OS X)
-- commit message if execution of code in IO memory
 - update doc: PCI infos.
-- VNC patch + Synaptic patch.
 - basic VGA optimizations
-- physical memory cache (reduce qemu-fast address space size to about 32 MB)
 - better code fetch (different exception handling + CS.limit support)
 - do not resize vga if invalid size.
 - avoid looping if only exceptions
-- cycle counter for all archs
 - TLB code protection support for PPC
 - see openMosix Doc 
 - disable SMC handling for ARM/SPARC/PPC (not finished)
@@ -31,12 +27,10 @@ short term:
 - fix CCOP optimisation
 - fix all remaining thread lock issues (must put TBs in a specific invalid
   state, find a solution for tb_flush()).
-- fix arm fpu rounding (at least for float->integer conversions)
 
 ppc specific:
 ------------
 - TLB invalidate not needed if msr_pr changes
-- SPR_ENCODE() not useful
 - enable shift optimizations ?
 
 linux-user specific:
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/VERSION
--- a/tools/ioemu/VERSION       Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/VERSION       Mon Aug 07 18:25:30 2006 +0100
@@ -1,1 +1,1 @@ 0.8.1
-0.8.1
\ No newline at end of file
+0.8.2
\ No newline at end of file
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/audio/alsaaudio.c
--- a/tools/ioemu/audio/alsaaudio.c     Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/audio/alsaaudio.c     Mon Aug 07 18:25:30 2006 +0100
@@ -61,8 +61,8 @@ static struct {
     .size_in_usec_in = 1,
     .size_in_usec_out = 1,
 #endif
-    .pcm_name_out = "hw:0,0",
-    .pcm_name_in = "hw:0,0",
+    .pcm_name_out = "default",
+    .pcm_name_in = "default",
 #ifdef HIGH_LATENCY
     .buffer_size_in = 400000,
     .period_size_in = 400000 / 4,
@@ -606,7 +606,6 @@ static int alsa_run_out (HWVoiceOut *hw)
                 }
             }
 
-            mixeng_clear (src, written);
             rpos = (rpos + written) % hw->samples;
             samples -= written;
             len -= written;
@@ -663,12 +662,9 @@ static int alsa_init_out (HWVoiceOut *hw
     obt_as.freq = obt.freq;
     obt_as.nchannels = obt.nchannels;
     obt_as.fmt = effective_fmt;
-
-    audio_pcm_init_info (
-        &hw->info,
-        &obt_as,
-        audio_need_to_swap_endian (endianness)
-        );
+    obt_as.endianness = endianness;
+
+    audio_pcm_init_info (&hw->info, &obt_as);
     hw->samples = obt.samples;
 
     alsa->pcm_buf = audio_calloc (AUDIO_FUNC, obt.samples, 1 << 
hw->info.shift);
@@ -752,12 +748,9 @@ static int alsa_init_in (HWVoiceIn *hw, 
     obt_as.freq = obt.freq;
     obt_as.nchannels = obt.nchannels;
     obt_as.fmt = effective_fmt;
-
-    audio_pcm_init_info (
-        &hw->info,
-        &obt_as,
-        audio_need_to_swap_endian (endianness)
-        );
+    obt_as.endianness = endianness;
+
+    audio_pcm_init_info (&hw->info, &obt_as);
     hw->samples = obt.samples;
 
     alsa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << 
hw->info.shift);
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/audio/audio.c
--- a/tools/ioemu/audio/audio.c Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/audio/audio.c Mon Aug 07 18:25:30 2006 +0100
@@ -29,6 +29,7 @@
 /* #define DEBUG_PLIVE */
 /* #define DEBUG_LIVE */
 /* #define DEBUG_OUT */
+/* #define DEBUG_CAPTURE */
 
 #define SW_NAME(sw) (sw)->name ? (sw)->name : "unknown"
 
@@ -137,7 +138,7 @@ int audio_bug (const char *funcname, int
     if (cond) {
         static int shown;
 
-        AUD_log (NULL, "Error a bug that was just triggered in %s\n", 
funcname);
+        AUD_log (NULL, "A bug was just triggered in %s\n", funcname);
         if (!shown) {
             shown = 1;
             AUD_log (NULL, "Save all your work and restart without audio\n");
@@ -509,14 +510,28 @@ static void audio_print_settings (audset
         AUD_log (NULL, "invalid(%d)", as->fmt);
         break;
     }
+
+    AUD_log (NULL, " endianness=");
+    switch (as->endianness) {
+    case 0:
+        AUD_log (NULL, "little");
+        break;
+    case 1:
+        AUD_log (NULL, "big");
+        break;
+    default:
+        AUD_log (NULL, "invalid");
+        break;
+    }
     AUD_log (NULL, "\n");
 }
 
-static int audio_validate_settigs (audsettings_t *as)
+static int audio_validate_settings (audsettings_t *as)
 {
     int invalid;
 
     invalid = as->nchannels != 1 && as->nchannels != 2;
+    invalid |= as->endianness != 0 && as->endianness != 1;
 
     switch (as->fmt) {
     case AUD_FMT_S8:
@@ -530,11 +545,7 @@ static int audio_validate_settigs (audse
     }
 
     invalid |= as->freq <= 0;
-
-    if (invalid) {
-        return -1;
-    }
-    return 0;
+    return invalid ? -1 : 0;
 }
 
 static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as)
@@ -556,14 +567,11 @@ static int audio_pcm_info_eq (struct aud
     return info->freq == as->freq
         && info->nchannels == as->nchannels
         && info->sign == sign
-        && info->bits == bits;
-}
-
-void audio_pcm_init_info (
-    struct audio_pcm_info *info,
-    audsettings_t *as,
-    int swap_endian
-    )
+        && info->bits == bits
+        && info->swap_endianness == (as->endianness != AUDIO_HOST_ENDIANNESS);
+}
+
+void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as)
 {
     int bits = 8, sign = 0;
 
@@ -587,7 +595,7 @@ void audio_pcm_init_info (
     info->shift = (as->nchannels == 2) + (bits == 16);
     info->align = (1 << info->shift) - 1;
     info->bytes_per_second = info->freq << info->shift;
-    info->swap_endian = swap_endian;
+    info->swap_endianness = (as->endianness != AUDIO_HOST_ENDIANNESS);
 }
 
 void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
@@ -609,7 +617,7 @@ void audio_pcm_info_clear_buf (struct au
             int shift = info->nchannels - 1;
             short s = INT16_MAX;
 
-            if (info->swap_endian) {
+            if (info->swap_endianness) {
                 s = bswap16 (s);
             }
 
@@ -618,6 +626,143 @@ void audio_pcm_info_clear_buf (struct au
             }
         }
     }
+}
+
+/*
+ * Capture
+ */
+static void noop_conv (st_sample_t *dst, const void *src,
+                       int samples, volume_t *vol)
+{
+    (void) src;
+    (void) dst;
+    (void) samples;
+    (void) vol;
+}
+
+static CaptureVoiceOut *audio_pcm_capture_find_specific (
+    AudioState *s,
+    audsettings_t *as
+    )
+{
+    CaptureVoiceOut *cap;
+
+    for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
+        if (audio_pcm_info_eq (&cap->hw.info, as)) {
+            return cap;
+        }
+    }
+    return NULL;
+}
+
+static void audio_notify_capture (CaptureVoiceOut *cap, audcnotification_e cmd)
+{
+    struct capture_callback *cb;
+
+#ifdef DEBUG_CAPTURE
+    dolog ("notification %d sent\n", cmd);
+#endif
+    for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
+        cb->ops.notify (cb->opaque, cmd);
+    }
+}
+
+static void audio_capture_maybe_changed (CaptureVoiceOut *cap, int enabled)
+{
+    if (cap->hw.enabled != enabled) {
+        audcnotification_e cmd;
+        cap->hw.enabled = enabled;
+        cmd = enabled ? AUD_CNOTIFY_ENABLE : AUD_CNOTIFY_DISABLE;
+        audio_notify_capture (cap, cmd);
+    }
+}
+
+static void audio_recalc_and_notify_capture (CaptureVoiceOut *cap)
+{
+    HWVoiceOut *hw = &cap->hw;
+    SWVoiceOut *sw;
+    int enabled = 0;
+
+    for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
+        if (sw->active) {
+            enabled = 1;
+            break;
+        }
+    }
+    audio_capture_maybe_changed (cap, enabled);
+}
+
+static void audio_detach_capture (HWVoiceOut *hw)
+{
+    SWVoiceCap *sc = hw->cap_head.lh_first;
+
+    while (sc) {
+        SWVoiceCap *sc1 = sc->entries.le_next;
+        SWVoiceOut *sw = &sc->sw;
+        CaptureVoiceOut *cap = sc->cap;
+        int was_active = sw->active;
+
+        if (sw->rate) {
+            st_rate_stop (sw->rate);
+            sw->rate = NULL;
+        }
+
+        LIST_REMOVE (sw, entries);
+        LIST_REMOVE (sc, entries);
+        qemu_free (sc);
+        if (was_active) {
+            /* We have removed soft voice from the capture:
+               this might have changed the overall status of the capture
+               since this might have been the only active voice */
+            audio_recalc_and_notify_capture (cap);
+        }
+        sc = sc1;
+    }
+}
+
+static int audio_attach_capture (AudioState *s, HWVoiceOut *hw)
+{
+    CaptureVoiceOut *cap;
+
+    audio_detach_capture (hw);
+    for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
+        SWVoiceCap *sc;
+        SWVoiceOut *sw;
+        HWVoiceOut *hw_cap = &cap->hw;
+
+        sc = audio_calloc (AUDIO_FUNC, 1, sizeof (*sc));
+        if (!sc) {
+            dolog ("Could not allocate soft capture voice (%zu bytes)\n",
+                   sizeof (*sc));
+            return -1;
+        }
+
+        sc->cap = cap;
+        sw = &sc->sw;
+        sw->hw = hw_cap;
+        sw->info = hw->info;
+        sw->empty = 1;
+        sw->active = hw->enabled;
+        sw->conv = noop_conv;
+        sw->ratio = ((int64_t) hw_cap->info.freq << 32) / sw->info.freq;
+        sw->rate = st_rate_start (sw->info.freq, hw_cap->info.freq);
+        if (!sw->rate) {
+            dolog ("Could not start rate conversion for `%s'\n", SW_NAME (sw));
+            qemu_free (sw);
+            return -1;
+        }
+        LIST_INSERT_HEAD (&hw_cap->sw_head, sw, entries);
+        LIST_INSERT_HEAD (&hw->cap_head, sc, entries);
+#ifdef DEBUG_CAPTURE
+        asprintf (&sw->name, "for %p %d,%d,%d",
+                  hw, sw->info.freq, sw->info.bits, sw->info.nchannels);
+        dolog ("Added %s active = %d\n", sw->name, sw->active);
+#endif
+        if (sw->active) {
+            audio_capture_maybe_changed (cap, 1);
+        }
+    }
+    return 0;
 }
 
 /*
@@ -796,6 +941,9 @@ int audio_pcm_sw_write (SWVoiceOut *sw, 
     }
 
     if (live == hwsamples) {
+#ifdef DEBUG_OUT
+        dolog ("%s is full %d\n", sw->name, live);
+#endif
         return 0;
     }
 
@@ -914,19 +1062,14 @@ void AUD_set_active_out (SWVoiceOut *sw,
     hw = sw->hw;
     if (sw->active != on) {
         SWVoiceOut *temp_sw;
+        SWVoiceCap *sc;
 
         if (on) {
-            int total;
-
             hw->pending_disable = 0;
             if (!hw->enabled) {
                 hw->enabled = 1;
                 hw->pcm_ops->ctl_out (hw, VOICE_ENABLE);
             }
-
-            if (sw->empty) {
-                total = 0;
-            }
         }
         else {
             if (hw->enabled) {
@@ -940,6 +1083,13 @@ void AUD_set_active_out (SWVoiceOut *sw,
                 hw->pending_disable = nb_active == 1;
             }
         }
+
+        for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
+            sc->sw.active = hw->enabled;
+            if (hw->enabled) {
+                audio_capture_maybe_changed (sc->cap, 1);
+            }
+        }
         sw->active = on;
     }
 }
@@ -997,7 +1147,7 @@ static int audio_get_avail (SWVoiceIn *s
     }
 
     ldebug (
-        "%s: get_avail live %d ret %lld\n",
+        "%s: get_avail live %d ret %" PRId64 "\n",
         SW_NAME (sw),
         live, (((int64_t) live << 32) / sw->ratio) << sw->info.shift
         );
@@ -1023,7 +1173,7 @@ static int audio_get_free (SWVoiceOut *s
     dead = sw->hw->samples - live;
 
 #ifdef DEBUG_OUT
-    dolog ("%s: get_free live %d dead %d ret %lld\n",
+    dolog ("%s: get_free live %d dead %d ret %" PRId64 "\n",
            SW_NAME (sw),
            live, dead, (((int64_t) dead << 32) / sw->ratio) << sw->info.shift);
 #endif
@@ -1031,6 +1181,43 @@ static int audio_get_free (SWVoiceOut *s
     return (((int64_t) dead << 32) / sw->ratio) << sw->info.shift;
 }
 
+static void audio_capture_mix_and_clear (HWVoiceOut *hw, int rpos, int samples)
+{
+    int n;
+
+    if (hw->enabled) {
+        SWVoiceCap *sc;
+
+        for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
+            SWVoiceOut *sw = &sc->sw;
+            int rpos2 = rpos;
+
+            n = samples;
+            while (n) {
+                int till_end_of_hw = hw->samples - rpos2;
+                int to_write = audio_MIN (till_end_of_hw, n);
+                int bytes = to_write << hw->info.shift;
+                int written;
+
+                sw->buf = hw->mix_buf + rpos2;
+                written = audio_pcm_sw_write (sw, NULL, bytes);
+                if (written - bytes) {
+                    dolog ("Could not mix %d bytes into a capture "
+                           "buffer, mixed %d\n",
+                           bytes, written);
+                    break;
+                }
+                n -= to_write;
+                rpos2 = (rpos2 + to_write) % hw->samples;
+            }
+        }
+    }
+
+    n = audio_MIN (samples, hw->samples - rpos);
+    mixeng_clear (hw->mix_buf + rpos, n);
+    mixeng_clear (hw->mix_buf, samples - n);
+}
+
 static void audio_run_out (AudioState *s)
 {
     HWVoiceOut *hw = NULL;
@@ -1038,7 +1225,7 @@ static void audio_run_out (AudioState *s
 
     while ((hw = audio_pcm_hw_find_any_enabled_out (s, hw))) {
         int played;
-        int live, free, nb_live, cleanup_required;
+        int live, free, nb_live, cleanup_required, prev_rpos;
 
         live = audio_pcm_hw_get_live_out2 (hw, &nb_live);
         if (!nb_live) {
@@ -1051,12 +1238,17 @@ static void audio_run_out (AudioState *s
         }
 
         if (hw->pending_disable && !nb_live) {
+            SWVoiceCap *sc;
 #ifdef DEBUG_OUT
             dolog ("Disabling voice\n");
 #endif
             hw->enabled = 0;
             hw->pending_disable = 0;
             hw->pcm_ops->ctl_out (hw, VOICE_DISABLE);
+            for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
+                sc->sw.active = 0;
+                audio_recalc_and_notify_capture (sc->cap);
+            }
             continue;
         }
 
@@ -1072,6 +1264,7 @@ static void audio_run_out (AudioState *s
             continue;
         }
 
+        prev_rpos = hw->rpos;
         played = hw->pcm_ops->run_out (hw);
         if (audio_bug (AUDIO_FUNC, hw->rpos >= hw->samples)) {
             dolog ("hw->rpos=%d hw->samples=%d played=%d\n",
@@ -1085,6 +1278,7 @@ static void audio_run_out (AudioState *s
 
         if (played) {
             hw->ts_helper += played;
+            audio_capture_mix_and_clear (hw, prev_rpos, played);
         }
 
         cleanup_required = 0;
@@ -1115,15 +1309,18 @@ static void audio_run_out (AudioState *s
         }
 
         if (cleanup_required) {
-        restart:
-            for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
+            SWVoiceOut *sw1;
+
+            sw = hw->sw_head.lh_first;
+            while (sw) {
+                sw1 = sw->entries.le_next;
                 if (!sw->active && !sw->callback.fn) {
 #ifdef DEBUG_PLIVE
                     dolog ("Finishing with old voice\n");
 #endif
                     audio_close_out (s, sw);
-                    goto restart; /* play it safe */
                 }
+                sw = sw1;
             }
         }
     }
@@ -1158,12 +1355,60 @@ static void audio_run_in (AudioState *s)
     }
 }
 
+static void audio_run_capture (AudioState *s)
+{
+    CaptureVoiceOut *cap;
+
+    for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
+        int live, rpos, captured;
+        HWVoiceOut *hw = &cap->hw;
+        SWVoiceOut *sw;
+
+        captured = live = audio_pcm_hw_get_live_out (hw);
+        rpos = hw->rpos;
+        while (live) {
+            int left = hw->samples - rpos;
+            int to_capture = audio_MIN (live, left);
+            st_sample_t *src;
+            struct capture_callback *cb;
+
+            src = hw->mix_buf + rpos;
+            hw->clip (cap->buf, src, to_capture);
+            mixeng_clear (src, to_capture);
+
+            for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
+                cb->ops.capture (cb->opaque, cap->buf,
+                                 to_capture << hw->info.shift);
+            }
+            rpos = (rpos + to_capture) % hw->samples;
+            live -= to_capture;
+        }
+        hw->rpos = rpos;
+
+        for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
+            if (!sw->active && sw->empty) {
+                continue;
+            }
+
+            if (audio_bug (AUDIO_FUNC, captured > sw->total_hw_samples_mixed)) 
{
+                dolog ("captured=%d sw->total_hw_samples_mixed=%d\n",
+                       captured, sw->total_hw_samples_mixed);
+                captured = sw->total_hw_samples_mixed;
+            }
+
+            sw->total_hw_samples_mixed -= captured;
+            sw->empty = sw->total_hw_samples_mixed == 0;
+        }
+    }
+}
+
 static void audio_timer (void *opaque)
 {
     AudioState *s = opaque;
 
     audio_run_out (s);
     audio_run_in (s);
+    audio_run_capture (s);
 
     qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);
 }
@@ -1327,8 +1572,19 @@ static void audio_atexit (void)
     HWVoiceIn *hwi = NULL;
 
     while ((hwo = audio_pcm_hw_find_any_enabled_out (s, hwo))) {
+        SWVoiceCap *sc;
+
         hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE);
         hwo->pcm_ops->fini_out (hwo);
+
+        for (sc = hwo->cap_head.lh_first; sc; sc = sc->entries.le_next) {
+            CaptureVoiceOut *cap = sc->cap;
+            struct capture_callback *cb;
+
+            for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
+                cb->ops.destroy (cb->opaque);
+            }
+        }
     }
 
     while ((hwi = audio_pcm_hw_find_any_enabled_in (s, hwi))) {
@@ -1383,6 +1639,7 @@ AudioState *AUD_init (void)
 
     LIST_INIT (&s->hw_head_out);
     LIST_INIT (&s->hw_head_in);
+    LIST_INIT (&s->cap_head);
     atexit (audio_atexit);
 
     s->ts = qemu_new_timer (vm_clock, audio_timer, s);
@@ -1479,3 +1736,136 @@ AudioState *AUD_init (void)
     qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);
     return s;
 }
+
+CaptureVoiceOut *AUD_add_capture (
+    AudioState *s,
+    audsettings_t *as,
+    struct audio_capture_ops *ops,
+    void *cb_opaque
+    )
+{
+    CaptureVoiceOut *cap;
+    struct capture_callback *cb;
+
+    if (!s) {
+        /* XXX suppress */
+        s = &glob_audio_state;
+    }
+
+    if (audio_validate_settings (as)) {
+        dolog ("Invalid settings were passed when trying to add capture\n");
+        audio_print_settings (as);
+        goto err0;
+    }
+
+    cb = audio_calloc (AUDIO_FUNC, 1, sizeof (*cb));
+    if (!cb) {
+        dolog ("Could not allocate capture callback information, size %zu\n",
+               sizeof (*cb));
+        goto err0;
+    }
+    cb->ops = *ops;
+    cb->opaque = cb_opaque;
+
+    cap = audio_pcm_capture_find_specific (s, as);
+    if (cap) {
+        LIST_INSERT_HEAD (&cap->cb_head, cb, entries);
+        return cap;
+    }
+    else {
+        HWVoiceOut *hw;
+        CaptureVoiceOut *cap;
+
+        cap = audio_calloc (AUDIO_FUNC, 1, sizeof (*cap));
+        if (!cap) {
+            dolog ("Could not allocate capture voice, size %zu\n",
+                   sizeof (*cap));
+            goto err1;
+        }
+
+        hw = &cap->hw;
+        LIST_INIT (&hw->sw_head);
+        LIST_INIT (&cap->cb_head);
+
+        /* XXX find a more elegant way */
+        hw->samples = 4096 * 4;
+        hw->mix_buf = audio_calloc (AUDIO_FUNC, hw->samples,
+                                    sizeof (st_sample_t));
+        if (!hw->mix_buf) {
+            dolog ("Could not allocate capture mix buffer (%d samples)\n",
+                   hw->samples);
+            goto err2;
+        }
+
+        audio_pcm_init_info (&hw->info, as);
+
+        cap->buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
+        if (!cap->buf) {
+            dolog ("Could not allocate capture buffer "
+                   "(%d samples, each %d bytes)\n",
+                   hw->samples, 1 << hw->info.shift);
+            goto err3;
+        }
+
+        hw->clip = mixeng_clip
+            [hw->info.nchannels == 2]
+            [hw->info.sign]
+            [hw->info.swap_endianness]
+            [hw->info.bits == 16];
+
+        LIST_INSERT_HEAD (&s->cap_head, cap, entries);
+        LIST_INSERT_HEAD (&cap->cb_head, cb, entries);
+
+        hw = NULL;
+        while ((hw = audio_pcm_hw_find_any_out (s, hw))) {
+            audio_attach_capture (s, hw);
+        }
+        return cap;
+
+    err3:
+        qemu_free (cap->hw.mix_buf);
+    err2:
+        qemu_free (cap);
+    err1:
+        qemu_free (cb);
+    err0:
+        return NULL;
+    }
+}
+
+void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque)
+{
+    struct capture_callback *cb;
+
+    for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
+        if (cb->opaque == cb_opaque) {
+            cb->ops.destroy (cb_opaque);
+            LIST_REMOVE (cb, entries);
+            qemu_free (cb);
+
+            if (!cap->cb_head.lh_first) {
+                SWVoiceOut *sw = cap->hw.sw_head.lh_first, *sw1;
+
+                while (sw) {
+                    SWVoiceCap *sc = (SWVoiceCap *) sw;
+#ifdef DEBUG_CAPTURE
+                    dolog ("freeing %s\n", sw->name);
+#endif
+
+                    sw1 = sw->entries.le_next;
+                    if (sw->rate) {
+                        st_rate_stop (sw->rate);
+                        sw->rate = NULL;
+                    }
+                    LIST_REMOVE (sw, entries);
+                    LIST_REMOVE (sc, entries);
+                    qemu_free (sc);
+                    sw = sw1;
+                }
+                LIST_REMOVE (cap, entries);
+                qemu_free (cap);
+            }
+            return;
+        }
+    }
+}
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/audio/audio.h
--- a/tools/ioemu/audio/audio.h Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/audio/audio.h Mon Aug 07 18:25:30 2006 +0100
@@ -24,6 +24,7 @@
 #ifndef QEMU_AUDIO_H
 #define QEMU_AUDIO_H
 
+#include "config.h"
 #include "sys-queue.h"
 
 typedef void (*audio_callback_fn_t) (void *opaque, int avail);
@@ -35,14 +36,44 @@ typedef enum {
     AUD_FMT_S16
 } audfmt_e;
 
+#ifdef WORDS_BIGENDIAN
+#define AUDIO_HOST_ENDIANNESS 1
+#else
+#define AUDIO_HOST_ENDIANNESS 0
+#endif
+
 typedef struct {
     int freq;
     int nchannels;
     audfmt_e fmt;
+    int endianness;
 } audsettings_t;
+
+typedef enum {
+    AUD_CNOTIFY_ENABLE,
+    AUD_CNOTIFY_DISABLE
+} audcnotification_e;
+
+struct audio_capture_ops {
+    void (*notify) (void *opaque, audcnotification_e cmd);
+    void (*capture) (void *opaque, void *buf, int size);
+    void (*destroy) (void *opaque);
+};
+
+struct capture_ops {
+    void (*info) (void *opaque);
+    void (*destroy) (void *opaque);
+};
+
+typedef struct CaptureState {
+    void *opaque;
+    struct capture_ops ops;
+    LIST_ENTRY (CaptureState) entries;
+} CaptureState;
 
 typedef struct AudioState AudioState;
 typedef struct SWVoiceOut SWVoiceOut;
+typedef struct CaptureVoiceOut CaptureVoiceOut;
 typedef struct SWVoiceIn SWVoiceIn;
 
 typedef struct QEMUSoundCard {
@@ -66,6 +97,13 @@ void AUD_help (void);
 void AUD_help (void);
 void AUD_register_card (AudioState *s, const char *name, QEMUSoundCard *card);
 void AUD_remove_card (QEMUSoundCard *card);
+CaptureVoiceOut *AUD_add_capture (
+    AudioState *s,
+    audsettings_t *as,
+    struct audio_capture_ops *ops,
+    void *opaque
+    );
+void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque);
 
 SWVoiceOut *AUD_open_out (
     QEMUSoundCard *card,
@@ -73,8 +111,7 @@ SWVoiceOut *AUD_open_out (
     const char *name,
     void *callback_opaque,
     audio_callback_fn_t callback_fn,
-    audsettings_t *settings,
-    int sw_endian
+    audsettings_t *settings
     );
 
 void AUD_close_out (QEMUSoundCard *card, SWVoiceOut *sw);
@@ -92,8 +129,7 @@ SWVoiceIn *AUD_open_in (
     const char *name,
     void *callback_opaque,
     audio_callback_fn_t callback_fn,
-    audsettings_t *settings,
-    int sw_endian
+    audsettings_t *settings
     );
 
 void AUD_close_in (QEMUSoundCard *card, SWVoiceIn *sw);
@@ -111,7 +147,7 @@ static inline void *advance (void *p, in
 }
 
 uint32_t popcount (uint32_t u);
-inline uint32_t lsbindex (uint32_t u);
+uint32_t lsbindex (uint32_t u);
 
 #ifdef __GNUC__
 #define audio_MIN(a, b) ( __extension__ ({      \
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/audio/audio_int.h
--- a/tools/ioemu/audio/audio_int.h     Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/audio/audio_int.h     Mon Aug 07 18:25:30 2006 +0100
@@ -61,13 +61,14 @@ struct audio_pcm_info {
     int align;
     int shift;
     int bytes_per_second;
-    int swap_endian;
-};
+    int swap_endianness;
+};
+
+typedef struct SWVoiceCap SWVoiceCap;
 
 typedef struct HWVoiceOut {
     int enabled;
     int pending_disable;
-    int valid;
     struct audio_pcm_info info;
 
     f_sample *clip;
@@ -79,6 +80,7 @@ typedef struct HWVoiceOut {
 
     int samples;
     LIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head;
+    LIST_HEAD (sw_cap_listhead, SWVoiceCap) cap_head;
     struct audio_pcm_ops *pcm_ops;
     LIST_ENTRY (HWVoiceOut) entries;
 } HWVoiceOut;
@@ -160,14 +162,34 @@ struct audio_pcm_ops {
     int  (*ctl_in)  (HWVoiceIn *hw, int cmd, ...);
 };
 
+struct capture_callback {
+    struct audio_capture_ops ops;
+    void *opaque;
+    LIST_ENTRY (capture_callback) entries;
+};
+
+struct CaptureVoiceOut {
+    HWVoiceOut hw;
+    void *buf;
+    LIST_HEAD (cb_listhead, capture_callback) cb_head;
+    LIST_ENTRY (CaptureVoiceOut) entries;
+};
+
+struct SWVoiceCap {
+    SWVoiceOut sw;
+    CaptureVoiceOut *cap;
+    LIST_ENTRY (SWVoiceCap) entries;
+};
+
 struct AudioState {
     struct audio_driver *drv;
     void *drv_opaque;
 
     QEMUTimer *ts;
-    LIST_HEAD (card_head, QEMUSoundCard) card_head;
+    LIST_HEAD (card_listhead, QEMUSoundCard) card_head;
     LIST_HEAD (hw_in_listhead, HWVoiceIn) hw_head_in;
     LIST_HEAD (hw_out_listhead, HWVoiceOut) hw_head_out;
+    LIST_HEAD (cap_listhead, CaptureVoiceOut) cap_head;
     int nb_hw_voices_out;
     int nb_hw_voices_in;
 };
@@ -182,8 +204,7 @@ extern struct audio_driver dsound_audio_
 extern struct audio_driver dsound_audio_driver;
 extern volume_t nominal_volume;
 
-void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as,
-                          int swap_endian);
+void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as);
 void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int 
len);
 
 int  audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int len);
@@ -202,15 +223,6 @@ static inline int audio_ring_dist (int d
 static inline int audio_ring_dist (int dst, int src, int len)
 {
     return (dst >= src) ? (dst - src) : (len - src + dst);
-}
-
-static inline int audio_need_to_swap_endian (int endianness)
-{
-#ifdef WORDS_BIGENDIAN
-    return endianness != 1;
-#else
-    return endianness != 0;
-#endif
 }
 
 #if defined __GNUC__
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/audio/audio_template.h
--- a/tools/ioemu/audio/audio_template.h        Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/audio/audio_template.h        Mon Aug 07 18:25:30 2006 +0100
@@ -140,13 +140,12 @@ static int glue (audio_pcm_sw_init_, TYP
     SW *sw,
     HW *hw,
     const char *name,
-    audsettings_t *as,
-    int endian
+    audsettings_t *as
     )
 {
     int err;
 
-    audio_pcm_init_info (&sw->info, as, audio_need_to_swap_endian (endian));
+    audio_pcm_init_info (&sw->info, as);
     sw->hw = hw;
     sw->active = 0;
 #ifdef DAC
@@ -164,7 +163,7 @@ static int glue (audio_pcm_sw_init_, TYP
 #endif
         [sw->info.nchannels == 2]
         [sw->info.sign]
-        [sw->info.swap_endian]
+        [sw->info.swap_endianness]
         [sw->info.bits == 16];
 
     sw->name = qemu_strdup (name);
@@ -200,6 +199,9 @@ static void glue (audio_pcm_hw_gc_, TYPE
     HW *hw = *hwp;
 
     if (!hw->sw_head.lh_first) {
+#ifdef DAC
+        audio_detach_capture (hw);
+#endif
         LIST_REMOVE (hw, entries);
         glue (s->nb_hw_voices_, TYPE) += 1;
         glue (audio_pcm_hw_free_resources_ ,TYPE) (hw);
@@ -266,7 +268,9 @@ static HW *glue (audio_pcm_hw_add_new_, 
 
     hw->pcm_ops = drv->pcm_ops;
     LIST_INIT (&hw->sw_head);
-
+#ifdef DAC
+    LIST_INIT (&hw->cap_head);
+#endif
     if (glue (hw->pcm_ops->init_, TYPE) (hw, as)) {
         goto err0;
     }
@@ -283,7 +287,7 @@ static HW *glue (audio_pcm_hw_add_new_, 
 #endif
         [hw->info.nchannels == 2]
         [hw->info.sign]
-        [hw->info.swap_endian]
+        [hw->info.swap_endianness]
         [hw->info.bits == 16];
 
     if (glue (audio_pcm_hw_alloc_resources_, TYPE) (hw)) {
@@ -292,6 +296,9 @@ static HW *glue (audio_pcm_hw_add_new_, 
 
     LIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries);
     glue (s->nb_hw_voices_, TYPE) -= 1;
+#ifdef DAC
+    audio_attach_capture (s, hw);
+#endif
     return hw;
 
  err1:
@@ -328,8 +335,7 @@ static SW *glue (audio_pcm_create_voice_
 static SW *glue (audio_pcm_create_voice_pair_, TYPE) (
     AudioState *s,
     const char *sw_name,
-    audsettings_t *as,
-    int sw_endian
+    audsettings_t *as
     )
 {
     SW *sw;
@@ -357,7 +363,7 @@ static SW *glue (audio_pcm_create_voice_
 
     glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw);
 
-    if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as, sw_endian)) {
+    if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as)) {
         goto err3;
     }
 
@@ -399,8 +405,7 @@ SW *glue (AUD_open_, TYPE) (
     const char *name,
     void *callback_opaque ,
     audio_callback_fn_t callback_fn,
-    audsettings_t *as,
-    int sw_endian
+    audsettings_t *as
     )
 {
     AudioState *s;
@@ -421,7 +426,7 @@ SW *glue (AUD_open_, TYPE) (
 
     s = card->audio;
 
-    if (audio_bug (AUDIO_FUNC, audio_validate_settigs (as))) {
+    if (audio_bug (AUDIO_FUNC, audio_validate_settings (as))) {
         audio_print_settings (as);
         goto fail;
     }
@@ -473,12 +478,12 @@ SW *glue (AUD_open_, TYPE) (
         }
 
         glue (audio_pcm_sw_fini_, TYPE) (sw);
-        if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as, sw_endian)) {
+        if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as)) {
             goto fail;
         }
     }
     else {
-        sw = glue (audio_pcm_create_voice_pair_, TYPE) (s, name, as, 
sw_endian);
+        sw = glue (audio_pcm_create_voice_pair_, TYPE) (s, name, as);
         if (!sw) {
             dolog ("Failed to create voice `%s'\n", name);
             return NULL;
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/audio/coreaudio.c
--- a/tools/ioemu/audio/coreaudio.c     Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/audio/coreaudio.c     Mon Aug 07 18:25:30 2006 +0100
@@ -275,8 +275,6 @@ static OSStatus audioDeviceIOProc(
 #endif
     }
 
-    /* cleanup */
-    mixeng_clear (src, frameCount);
     rpos = (rpos + frameCount) % hw->samples;
     core->decr += frameCount;
     core->rpos = rpos;
@@ -297,7 +295,6 @@ static int coreaudio_init_out (HWVoiceOu
     UInt32 propertySize;
     int err;
     int bits = 8;
-    int endianess = 0;
     const char *typ = "playback";
     AudioValueRange frameRange;
 
@@ -310,16 +307,9 @@ static int coreaudio_init_out (HWVoiceOu
 
     if (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) {
         bits = 16;
-        endianess = 1;
-    }
-
-    audio_pcm_init_info (
-        &hw->info,
-        as,
-        /* Following is irrelevant actually since we do not use
-           mixengs clipping routines */
-        audio_need_to_swap_endian (endianess)
-        );
+    }
+
+    audio_pcm_init_info (&hw->info, as);
 
     /* open default output device */
     propertySize = sizeof(core->outputDeviceID);
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/audio/dsound_template.h
--- a/tools/ioemu/audio/dsound_template.h       Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/audio/dsound_template.h       Mon Aug 07 18:25:30 2006 +0100
@@ -70,7 +70,13 @@ static int glue (dsound_lock_, TYPE) (
     int i;
     LPVOID p1 = NULL, p2 = NULL;
     DWORD blen1 = 0, blen2 = 0;
-
+    DWORD flag;
+
+#ifdef DSBTYPE_IN
+    flag = entire ? DSCBLOCK_ENTIREBUFFER : 0;
+#else
+    flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
+#endif
     for (i = 0; i < conf.lock_retries; ++i) {
         hr = glue (IFACE, _Lock) (
             buf,
@@ -80,13 +86,7 @@ static int glue (dsound_lock_, TYPE) (
             &blen1,
             &p2,
             &blen2,
-            (entire
-#ifdef DSBTYPE_IN
-             ? DSCBLOCK_ENTIREBUFFER
-#else
-             ? DSBLOCK_ENTIREBUFFER
-#endif
-             : 0)
+            flag
             );
 
         if (FAILED (hr)) {
@@ -250,8 +250,8 @@ static int dsound_init_out (HWVoiceOut *
     }
 
     ds->first_time = 1;
-
-    audio_pcm_init_info (&hw->info, &obt_as, audio_need_to_swap_endian (0));
+    obt_as.endianness = 0;
+    audio_pcm_init_info (&hw->info, &obt_as);
 
     if (bc.dwBufferBytes & hw->info.align) {
         dolog (
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/audio/dsoundaudio.c
--- a/tools/ioemu/audio/dsoundaudio.c   Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/audio/dsoundaudio.c   Mon Aug 07 18:25:30 2006 +0100
@@ -453,13 +453,11 @@ static void dsound_write_sample (HWVoice
 
     if (src_len1) {
         hw->clip (dst, src1, src_len1);
-        mixeng_clear (src1, src_len1);
     }
 
     if (src_len2) {
         dst = advance (dst, src_len1 << hw->info.shift);
         hw->clip (dst, src2, src_len2);
-        mixeng_clear (src2, src_len2);
     }
 
     hw->rpos = pos % hw->samples;
@@ -987,6 +985,12 @@ static void *dsound_audio_init (void)
     hr = IDirectSound_Initialize (s->dsound, NULL);
     if (FAILED (hr)) {
         dsound_logerr (hr, "Could not initialize DirectSound\n");
+
+        hr = IDirectSound_Release (s->dsound);
+        if (FAILED (hr)) {
+            dsound_logerr (hr, "Could not release DirectSound\n");
+        }
+        s->dsound = NULL;
         return NULL;
     }
 
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/audio/fmodaudio.c
--- a/tools/ioemu/audio/fmodaudio.c     Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/audio/fmodaudio.c     Mon Aug 07 18:25:30 2006 +0100
@@ -153,13 +153,11 @@ static void fmod_write_sample (HWVoiceOu
 
     if (src_len1) {
         hw->clip (dst, src1, src_len1);
-        mixeng_clear (src1, src_len1);
     }
 
     if (src_len2) {
         dst = advance (dst, src_len1 << hw->info.shift);
         hw->clip (dst, src2, src_len2);
-        mixeng_clear (src2, src_len2);
     }
 
     hw->rpos = pos % hw->samples;
@@ -360,6 +358,7 @@ static int fmod_init_out (HWVoiceOut *hw
 {
     int bits16, mode, channel;
     FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
+    audsettings_t obt_as = *as;
 
     mode = aud_to_fmodfmt (as->fmt, as->nchannels == 2 ? 1 : 0);
     fmd->fmod_sample = FSOUND_Sample_Alloc (
@@ -386,7 +385,8 @@ static int fmod_init_out (HWVoiceOut *hw
     fmd->channel = channel;
 
     /* FMOD always operates on little endian frames? */
-    audio_pcm_init_info (&hw->info, as, audio_need_to_swap_endian (0));
+    obt_as.endianness = 0;
+    audio_pcm_init_info (&hw->info, &obt_as);
     bits16 = (mode & FSOUND_16BITS) != 0;
     hw->samples = conf.nb_samples;
     return 0;
@@ -420,6 +420,7 @@ static int fmod_init_in (HWVoiceIn *hw, 
 {
     int bits16, mode;
     FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
+    audsettings_t obt_as = *as;
 
     if (conf.broken_adc) {
         return -1;
@@ -442,7 +443,8 @@ static int fmod_init_in (HWVoiceIn *hw, 
     }
 
     /* FMOD always operates on little endian frames? */
-    audio_pcm_init_info (&hw->info, as, audio_need_to_swap_endian (0));
+    obt_as.endianness = 0;
+    audio_pcm_init_info (&hw->info, &obt_as);
     bits16 = (mode & FSOUND_16BITS) != 0;
     hw->samples = conf.nb_samples;
     return 0;
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/audio/noaudio.c
--- a/tools/ioemu/audio/noaudio.c       Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/audio/noaudio.c       Mon Aug 07 18:25:30 2006 +0100
@@ -40,21 +40,20 @@ static int no_run_out (HWVoiceOut *hw)
 {
     NoVoiceOut *no = (NoVoiceOut *) hw;
     int live, decr, samples;
-    int64_t now = qemu_get_clock (vm_clock);
-    int64_t ticks = now - no->old_ticks;
-    int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec;
-
-    if (bytes > INT_MAX) {
-        samples = INT_MAX >> hw->info.shift;
-    }
-    else {
-        samples = bytes >> hw->info.shift;
-    }
+    int64_t now;
+    int64_t ticks;
+    int64_t bytes;
 
     live = audio_pcm_hw_get_live_out (&no->hw);
     if (!live) {
         return 0;
     }
+
+    now = qemu_get_clock (vm_clock);
+    ticks = now - no->old_ticks;
+    bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec;
+    bytes = audio_MIN (bytes, INT_MAX);
+    samples = bytes >> hw->info.shift;
 
     no->old_ticks = now;
     decr = audio_MIN (live, samples);
@@ -69,7 +68,7 @@ static int no_write (SWVoiceOut *sw, voi
 
 static int no_init_out (HWVoiceOut *hw, audsettings_t *as)
 {
-    audio_pcm_init_info (&hw->info, as, 0);
+    audio_pcm_init_info (&hw->info, as);
     hw->samples = 1024;
     return 0;
 }
@@ -88,7 +87,7 @@ static int no_ctl_out (HWVoiceOut *hw, i
 
 static int no_init_in (HWVoiceIn *hw, audsettings_t *as)
 {
-    audio_pcm_init_info (&hw->info, as, 0);
+    audio_pcm_init_info (&hw->info, as);
     hw->samples = 1024;
     return 0;
 }
@@ -101,17 +100,20 @@ static int no_run_in (HWVoiceIn *hw)
 static int no_run_in (HWVoiceIn *hw)
 {
     NoVoiceIn *no = (NoVoiceIn *) hw;
-    int64_t now = qemu_get_clock (vm_clock);
-    int64_t ticks = now - no->old_ticks;
-    int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec;
     int live = audio_pcm_hw_get_live_in (hw);
     int dead = hw->samples - live;
-    int samples;
+    int samples = 0;
 
-    bytes = audio_MIN (bytes, INT_MAX);
-    samples = bytes >> hw->info.shift;
-    samples = audio_MIN (samples, dead);
+    if (dead) {
+        int64_t now = qemu_get_clock (vm_clock);
+        int64_t ticks = now - no->old_ticks;
+        int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec;
 
+        no->old_ticks = now;
+        bytes = audio_MIN (bytes, INT_MAX);
+        samples = bytes >> hw->info.shift;
+        samples = audio_MIN (samples, dead);
+    }
     return samples;
 }
 
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/audio/ossaudio.c
--- a/tools/ioemu/audio/ossaudio.c      Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/audio/ossaudio.c      Mon Aug 07 18:25:30 2006 +0100
@@ -55,12 +55,14 @@ static struct {
     int fragsize;
     const char *devpath_out;
     const char *devpath_in;
+    int debug;
 } conf = {
     .try_mmap = 0,
     .nfrags = 4,
     .fragsize = 4096,
     .devpath_out = "/dev/dsp",
-    .devpath_in = "/dev/dsp"
+    .devpath_in = "/dev/dsp",
+    .debug = 0
 };
 
 struct oss_params {
@@ -324,9 +326,20 @@ static int oss_run_out (HWVoiceOut *hw)
             return 0;
         }
 
-        if (abinfo.bytes < 0 || abinfo.bytes > bufsize) {
-            ldebug ("warning: Invalid available size, size=%d bufsize=%d\n",
-                    abinfo.bytes, bufsize);
+        if (abinfo.bytes > bufsize) {
+            if (conf.debug) {
+                dolog ("warning: Invalid available size, size=%d bufsize=%d\n"
+                       "please report your OS/audio hw to 
malc@xxxxxxxxxxxxx\n",
+                       abinfo.bytes, bufsize);
+            }
+            abinfo.bytes = bufsize;
+        }
+
+        if (abinfo.bytes < 0) {
+            if (conf.debug) {
+                dolog ("warning: Invalid available size, size=%d bufsize=%d\n",
+                       abinfo.bytes, bufsize);
+            }
             return 0;
         }
 
@@ -369,14 +382,11 @@ static int oss_run_out (HWVoiceOut *hw)
                            "alignment %d\n",
                            wbytes, written, hw->info.align + 1);
                 }
-                mixeng_clear (src, wsamples);
                 decr -= wsamples;
                 rpos = (rpos + wsamples) % hw->samples;
                 break;
             }
         }
-
-        mixeng_clear (src, convert_samples);
 
         rpos = (rpos + convert_samples) % hw->samples;
         samples -= convert_samples;
@@ -443,12 +453,9 @@ static int oss_init_out (HWVoiceOut *hw,
     obt_as.freq = obt.freq;
     obt_as.nchannels = obt.nchannels;
     obt_as.fmt = effective_fmt;
-
-    audio_pcm_init_info (
-        &hw->info,
-        &obt_as,
-        audio_need_to_swap_endian (endianness)
-        );
+    obt_as.endianness = endianness;
+
+    audio_pcm_init_info (&hw->info, &obt_as);
     oss->nfrags = obt.nfrags;
     oss->fragsize = obt.fragsize;
 
@@ -587,12 +594,9 @@ static int oss_init_in (HWVoiceIn *hw, a
     obt_as.freq = obt.freq;
     obt_as.nchannels = obt.nchannels;
     obt_as.fmt = effective_fmt;
-
-    audio_pcm_init_info (
-        &hw->info,
-        &obt_as,
-        audio_need_to_swap_endian (endianness)
-        );
+    obt_as.endianness = endianness;
+
+    audio_pcm_init_info (&hw->info, &obt_as);
     oss->nfrags = obt.nfrags;
     oss->fragsize = obt.fragsize;
 
@@ -730,6 +734,8 @@ static struct audio_option oss_options[]
      "Path to DAC device", NULL, 0},
     {"ADC_DEV", AUD_OPT_STR, &conf.devpath_in,
      "Path to ADC device", NULL, 0},
+    {"DEBUG", AUD_OPT_BOOL, &conf.debug,
+     "Turn on some debugging messages", NULL, 0},
     {NULL, 0, NULL, NULL, NULL, 0}
 };
 
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/audio/rate_template.h
--- a/tools/ioemu/audio/rate_template.h Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/audio/rate_template.h Mon Aug 07 18:25:30 2006 +0100
@@ -51,7 +51,7 @@ void NAME (void *opaque, st_sample_t *ib
     if (rate->opos_inc == (1ULL + UINT_MAX)) {
         int i, n = *isamp > *osamp ? *osamp : *isamp;
         for (i = 0; i < n; i++) {
-            OP (obuf[i].l, ibuf[i].r);
+            OP (obuf[i].l, ibuf[i].l);
             OP (obuf[i].r, ibuf[i].r);
         }
         *isamp = n;
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/audio/sdlaudio.c
--- a/tools/ioemu/audio/sdlaudio.c      Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/audio/sdlaudio.c      Mon Aug 07 18:25:30 2006 +0100
@@ -240,7 +240,6 @@ static void sdl_callback (void *opaque, 
 
             /* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
             hw->clip (buf, src, chunk);
-            mixeng_clear (src, chunk);
             sdl->rpos = (sdl->rpos + chunk) % hw->samples;
             to_mix -= chunk;
             buf += chunk << hw->info.shift;
@@ -336,12 +335,9 @@ static int sdl_init_out (HWVoiceOut *hw,
     obt_as.freq = obt.freq;
     obt_as.nchannels = obt.channels;
     obt_as.fmt = effective_fmt;
-
-    audio_pcm_init_info (
-        &hw->info,
-        &obt_as,
-        audio_need_to_swap_endian (endianess)
-        );
+    obt_as.endianness = endianess;
+
+    audio_pcm_init_info (&hw->info, &obt_as);
     hw->samples = obt.samples;
 
     s->initialized = 1;
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/audio/wavaudio.c
--- a/tools/ioemu/audio/wavaudio.c      Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/audio/wavaudio.c      Mon Aug 07 18:25:30 2006 +0100
@@ -81,7 +81,6 @@ static int wav_run_out (HWVoiceOut *hw)
 
         hw->clip (dst, src, convert_samples);
         qemu_put_buffer (wav->f, dst, convert_samples << hw->info.shift);
-        mixeng_clear (src, convert_samples);
 
         rpos = (rpos + convert_samples) % hw->samples;
         samples -= convert_samples;
@@ -136,7 +135,8 @@ static int wav_init_out (HWVoiceOut *hw,
 
     hdr[34] = bits16 ? 0x10 : 0x08;
 
-    audio_pcm_init_info (&hw->info, &wav_as, audio_need_to_swap_endian (0));
+    wav_as.endianness = 0;
+    audio_pcm_init_info (&hw->info, &wav_as);
 
     hw->samples = 1024;
     wav->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/block-cow.c
--- a/tools/ioemu/block-cow.c   Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/block-cow.c   Mon Aug 07 18:25:30 2006 +0100
@@ -250,6 +250,12 @@ static int cow_create(const char *filena
     return 0;
 }
 
+static void cow_flush(BlockDriverState *bs)
+{
+    BDRVCowState *s = bs->opaque;
+    fsync(s->fd);
+}
+
 BlockDriver bdrv_cow = {
     "cow",
     sizeof(BDRVCowState),
@@ -259,6 +265,7 @@ BlockDriver bdrv_cow = {
     cow_write,
     cow_close,
     cow_create,
+    cow_flush,
     cow_is_allocated,
 };
 #endif
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/block-qcow.c
--- a/tools/ioemu/block-qcow.c  Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/block-qcow.c  Mon Aug 07 18:25:30 2006 +0100
@@ -693,6 +693,12 @@ int qcow_compress_cluster(BlockDriverSta
     return 0;
 }
 
+static void qcow_flush(BlockDriverState *bs)
+{
+    BDRVQcowState *s = bs->opaque;
+    fsync(s->fd);
+}
+
 BlockDriver bdrv_qcow = {
     "qcow",
     sizeof(BDRVQcowState),
@@ -702,6 +708,7 @@ BlockDriver bdrv_qcow = {
     qcow_write,
     qcow_close,
     qcow_create,
+    qcow_flush,
     qcow_is_allocated,
     qcow_set_key,
     qcow_make_empty
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/block-vmdk.c
--- a/tools/ioemu/block-vmdk.c  Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/block-vmdk.c  Mon Aug 07 18:25:30 2006 +0100
@@ -426,6 +426,12 @@ static void vmdk_close(BlockDriverState 
     close(s->fd);
 }
 
+static void vmdk_flush(BlockDriverState *bs)
+{
+    BDRVVmdkState *s = bs->opaque;
+    fsync(s->fd);
+}
+
 BlockDriver bdrv_vmdk = {
     "vmdk",
     sizeof(BDRVVmdkState),
@@ -435,5 +441,6 @@ BlockDriver bdrv_vmdk = {
     vmdk_write,
     vmdk_close,
     vmdk_create,
+    vmdk_flush,
     vmdk_is_allocated,
 };
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/block-vpc.c
--- a/tools/ioemu/block-vpc.c   Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/block-vpc.c   Mon Aug 07 18:25:30 2006 +0100
@@ -163,7 +163,7 @@ static inline int seek_to_sector(BlockDr
     bitmap_offset = 512 * s->pagetable[pagetable_index];
     block_offset = bitmap_offset + 512 + (512 * pageentry_index);
     
-//    printf("sector: %llx, index: %x, offset: %x, bioff: %llx, bloff: %llx\n",
+//    printf("sector: %" PRIx64 ", index: %x, offset: %x, bioff: %" PRIx64 ", 
bloff: %" PRIx64 "\n",
 //     sector_num, pagetable_index, pageentry_index,
 //     bitmap_offset, block_offset);
 
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/block-vvfat.c
--- a/tools/ioemu/block-vvfat.c Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/block-vvfat.c Mon Aug 07 18:25:30 2006 +0100
@@ -2772,6 +2772,7 @@ BlockDriver bdrv_vvfat = {
     vvfat_read,
     vvfat_write,
     vvfat_close,
+    NULL, /* ??? Not sure if we can do any meaningful flushing.  */
     NULL,
     vvfat_is_allocated
 };
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/block.c
--- a/tools/ioemu/block.c       Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/block.c       Mon Aug 07 18:25:30 2006 +0100
@@ -615,6 +615,14 @@ const char *bdrv_get_device_name(BlockDr
     return bs->device_name;
 }
 
+void bdrv_flush(BlockDriverState *bs)
+{
+    if (bs->drv->bdrv_flush)
+        bs->drv->bdrv_flush(bs);
+    if (bs->backing_hd)
+        bdrv_flush(bs->backing_hd);
+}
+
 void bdrv_info(void)
 {
     BlockDriverState *bs;
@@ -754,6 +762,51 @@ static void raw_close(BlockDriverState *
     close(s->fd);
 }
 
+#ifdef _WIN32
+#include <windows.h>
+#include <winioctl.h>
+
+int qemu_ftruncate64(int fd, int64_t length)
+{
+    LARGE_INTEGER li;
+    LONG high;
+    HANDLE h;
+    BOOL res;
+
+    if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)
+       return -1;
+
+    h = (HANDLE)_get_osfhandle(fd);
+
+    /* get current position, ftruncate do not change position */
+    li.HighPart = 0;
+    li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
+    if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
+       return -1;
+
+    high = length >> 32;
+    if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN))
+       return -1;
+    res = SetEndOfFile(h);
+
+    /* back to old position */
+    SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
+    return res ? 0 : -1;
+}
+
+static int set_sparse(int fd)
+{
+    DWORD returned;
+    return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,
+                                NULL, 0, NULL, 0, &returned, NULL);
+}
+#else
+static inline int set_sparse(int fd)
+{
+    return 1;
+}
+#endif
+
 static int raw_create(const char *filename, int64_t total_size,
                       const char *backing_file, int flags)
 {
@@ -766,9 +819,16 @@ static int raw_create(const char *filena
               0644);
     if (fd < 0)
         return -EIO;
+    set_sparse(fd);
     ftruncate(fd, total_size * 512);
     close(fd);
     return 0;
+}
+
+static void raw_flush(BlockDriverState *bs)
+{
+    BDRVRawState *s = bs->opaque;
+    fsync(s->fd);
 }
 
 BlockDriver bdrv_raw = {
@@ -780,6 +840,7 @@ BlockDriver bdrv_raw = {
     raw_write,
     raw_close,
     raw_create,
+    raw_flush,
 };
 
 void bdrv_init(void)
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/block_int.h
--- a/tools/ioemu/block_int.h   Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/block_int.h   Mon Aug 07 18:25:30 2006 +0100
@@ -36,6 +36,7 @@ struct BlockDriver {
     void (*bdrv_close)(BlockDriverState *bs);
     int (*bdrv_create)(const char *filename, int64_t total_sectors, 
                        const char *backing_file, int flags);
+    void (*bdrv_flush)(BlockDriverState *bs);
     int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num,
                              int nb_sectors, int *pnum);
     int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/cocoa.m
--- a/tools/ioemu/cocoa.m       Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/cocoa.m       Mon Aug 07 18:25:30 2006 +0100
@@ -439,23 +439,40 @@ static void cocoa_refresh(DisplayState *
                                 kbd_put_keycode(keycode & 0x7f); //remove e0 
bit in front
                             /* handle monitor key events */
                             } else {
+                                int keysym = 0;
+
                                 switch([event keyCode]) {
-                                    case 123:
-                                        kbd_put_keysym(QEMU_KEY_LEFT);
-                                        break;
-                                    case 124:
-                                        kbd_put_keysym(QEMU_KEY_RIGHT);
-                                        break;
-                                    case 125:
-                                        kbd_put_keysym(QEMU_KEY_DOWN);
-                                        break;
-                                    case 126:
-                                        kbd_put_keysym(QEMU_KEY_UP);
-                                        break;
-                                    default:
-                                        kbd_put_keysym([[event characters] 
characterAtIndex:0]);
-                                        break;
+                                case 115:
+                                    keysym = QEMU_KEY_HOME;
+                                    break;
+                                case 117:
+                                    keysym = QEMU_KEY_DELETE;
+                                    break;
+                                case 119:
+                                    keysym = QEMU_KEY_END;
+                                    break;
+                                case 123:
+                                    keysym = QEMU_KEY_LEFT;
+                                    break;
+                                case 124:
+                                    keysym = QEMU_KEY_RIGHT;
+                                    break;
+                                case 125:
+                                    keysym = QEMU_KEY_DOWN;
+                                    break;
+                                case 126:
+                                    keysym = QEMU_KEY_UP;
+                                    break;
+                                default:
+                                    {
+                                        NSString *ks = [event characters];
+
+                                        if ([ks length] > 0)
+                                            keysym = [ks characterAtIndex:0];
+                                    }
                                 }
+                                if (keysym)
+                                    kbd_put_keysym(keysym);
                             }
                         }
                     }
@@ -867,10 +884,9 @@ static void setupWindowMenu(void)
     /* Finally give up our references to the objects */
     [windowMenu release];
     [windowMenuItem release];
- 
-}
-
-static void CustomApplicationMain (argc, argv)
+}
+
+static void CustomApplicationMain(void)
 {
     NSAutoreleasePool   *pool = [[NSAutoreleasePool alloc] init];
     QemuCocoaGUIController *gui_controller;
@@ -904,8 +920,8 @@ int main(int argc, char **argv)
 {
     gArgc = argc;
     gArgv = argv;
-    
-    CustomApplicationMain (argc, argv);
-    
+
+    CustomApplicationMain();
+
     return 0;
 }
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/configure
--- a/tools/ioemu/configure     Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/configure     Mon Aug 07 18:25:30 2006 +0100
@@ -96,6 +96,8 @@ softmmu="yes"
 softmmu="yes"
 user="no"
 build_docs="no"
+build_acpi_tables="no"
+uname_release=""
 
 # OS specific
 targetos=`uname -s`
@@ -212,7 +214,7 @@ for opt do
   ;;
   --fmod-inc=*) fmod_inc="$optarg"
   ;;
-  --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-"
+  --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" ; user="no"
   ;;
   --disable-slirp) slirp="no"
   ;;
@@ -235,6 +237,10 @@ for opt do
   --disable-user) user="no"
   ;;
   --enable-user) user="yes"
+  ;;
+  --enable-uname-release=*) uname_release="$optarg"
+  ;;
+  --enable-iasl) build_acpi_tables="yes"
   ;;
   esac
 done
@@ -283,6 +289,8 @@ echo "  --disable-user           disable
 echo "  --disable-user           disable all linux 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 "  --enable-iasl            compilation of ACPI tables with the IASL 
compiler"
 echo ""
 echo "NOTE: The object files are build at the place where configure is 
launched"
 exit 1
@@ -292,15 +300,21 @@ ar="${cross_prefix}${ar}"
 ar="${cross_prefix}${ar}"
 strip="${cross_prefix}${strip}"
 
-if [ ! -x "`which $cc`" ] ; then
-    echo "Compiler $cc could not be found"
-    exit
+# check that the C compiler works.
+cat > $TMPC <<EOF
+int main(void) {}
+EOF
+
+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"
+    exit 1
 fi
 
 if test "$mingw32" = "yes" ; then
     linux="no"
     EXESUF=".exe"
-    gdbstub="no"
     oss="no"
     if [ "$cpu" = "i386" ] ; then
         kqemu="yes"
@@ -551,6 +565,8 @@ echo "FMOD support      $fmod $fmod_supp
 echo "FMOD support      $fmod $fmod_support"
 echo "kqemu support     $kqemu"
 echo "Documentation     $build_docs"
+[ ! -z "$uname_release" ] && \
+echo "uname -r          $uname_release"
 
 if test $sdl_too_old = "yes"; then
 echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -703,6 +719,9 @@ if [ "$build_docs" = "yes" ] ; then
 if [ "$build_docs" = "yes" ] ; then
   echo "BUILD_DOCS=yes" >> $config_mak
 fi
+if [ "$build_acpi_tables" = "yes" ] ; then
+  echo "BUILD_ACPI_TABLES=yes" >> $config_mak
+fi
 
 # XXX: suppress that
 if [ "$bsd" = "yes" ] ; then
@@ -710,6 +729,8 @@ if [ "$bsd" = "yes" ] ; then
   echo "#define MAP_ANONYMOUS MAP_ANON" >> $config_h
   echo "#define _BSD 1" >> $config_h
 fi
+
+echo "#define CONFIG_UNAME_RELEASE \"$uname_release\"" >> $config_h
 
 for target in $target_list; do
 target_dir="$target"
@@ -723,6 +744,7 @@ target_bigendian="no"
 [ "$target_cpu" = "ppc" ] && target_bigendian=yes
 [ "$target_cpu" = "ppc64" ] && target_bigendian=yes
 [ "$target_cpu" = "mips" ] && target_bigendian=yes
+[ "$target_cpu" = "sh4eb" ] && target_bigendian=yes
 target_softmmu="no"
 if expr $target : '.*-softmmu' > /dev/null ; then
   target_softmmu="yes"
@@ -759,6 +781,7 @@ echo "include ../config-host.mak" >> $co
 echo "include ../config-host.mak" >> $config_mak
 echo "#include \"../config-host.h\"" >> $config_h
 
+bflt="no"
 interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"`
 echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h
 
@@ -779,6 +802,7 @@ elif test "$target_cpu" = "arm" -o "$tar
   echo "TARGET_ARCH=arm" >> $config_mak
   echo "#define TARGET_ARCH \"arm\"" >> $config_h
   echo "#define TARGET_ARM 1" >> $config_h
+  bflt="yes"
 elif test "$target_cpu" = "sparc" ; then
   echo "TARGET_ARCH=sparc" >> $config_mak
   echo "#define TARGET_ARCH \"sparc\"" >> $config_h
@@ -809,10 +833,13 @@ elif test "$target_cpu" = "mips" -o "$ta
   echo "TARGET_ARCH=mips" >> $config_mak
   echo "#define TARGET_ARCH \"mips\"" >> $config_h
   echo "#define TARGET_MIPS 1" >> $config_h
-elif test "$target_cpu" = "sh4" ; then
+  echo "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
   echo "#define TARGET_SH4 1" >> $config_h
+  bflt="yes"
 else
   echo "Unsupported target CPU"
   exit 1
@@ -834,9 +861,13 @@ if expr $target : '.*-dm' > /dev/null ; 
   echo "#define CONFIG_DM 1" >> $config_h
 fi
 
-if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" ; then
+if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = 
"sparc" -o "$target_cpu" = "sparc64"; then
   echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
   echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
+fi
+if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then
+  echo "TARGET_HAS_BFLT=yes" >> $config_mak
+  echo "#define TARGET_HAS_BFLT 1" >> $config_h
 fi
 # sdl defines
 
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/console.c
--- a/tools/ioemu/console.c     Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/console.c     Mon Aug 07 18:25:30 2006 +0100
@@ -27,8 +27,8 @@
 #define DEFAULT_BACKSCROLL 512
 #define MAX_CONSOLES 12
 
-#define RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
-#define RGB(r, g, b) RGBA(r, g, b, 0xff)
+#define QEMU_RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
+#define QEMU_RGB(r, g, b) QEMU_RGBA(r, g, b, 0xff)
 
 typedef struct TextAttributes {
     uint8_t fgcol:4;
@@ -52,6 +52,57 @@ enum TTYState {
     TTY_STATE_ESC,
     TTY_STATE_CSI,
 };
+
+typedef struct QEMUFIFO {
+    uint8_t *buf;
+    int buf_size;
+    int count, wptr, rptr;
+} QEMUFIFO;
+
+int qemu_fifo_write(QEMUFIFO *f, const uint8_t *buf, int len1)
+{
+    int l, len;
+
+    l = f->buf_size - f->count;
+    if (len1 > l)
+        len1 = l;
+    len = len1;
+    while (len > 0) {
+        l = f->buf_size - f->wptr;
+        if (l > len)
+            l = len;
+        memcpy(f->buf + f->wptr, buf, l);
+        f->wptr += l;
+        if (f->wptr >= f->buf_size)
+            f->wptr = 0;
+        buf += l;
+        len -= l;
+    }
+    f->count += len1;
+    return len1;
+}
+
+int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1)
+{
+    int l, len;
+
+    if (len1 > f->count)
+        len1 = f->count;
+    len = len1;
+    while (len > 0) {
+        l = f->buf_size - f->rptr;
+        if (l > len)
+            l = len;
+        memcpy(buf, f->buf + f->rptr, l);
+        f->rptr += l;
+        if (f->rptr >= f->buf_size)
+            f->rptr = 0;
+        buf += l;
+        len -= l;
+    }
+    f->count -= len1;
+    return len1;
+}
 
 /* ??? This is mis-named.
    It is used for both text and graphical consoles.  */
@@ -81,8 +132,13 @@ struct TextConsole {
     int nb_esc_params;
 
     /* kbd read handler */
+    IOCanRWHandler *fd_can_read; 
     IOReadHandler *fd_read;
     void *fd_opaque;
+    /* fifo for key pressed */
+    QEMUFIFO out_fifo;
+    uint8_t out_fifo_buf[16];
+    QEMUTimer *kbd_timer;
 };
 
 static TextConsole *active_console;
@@ -274,24 +330,24 @@ enum color_names {
 
 static const uint32_t color_table_rgb[2][8] = {
     {   /* dark */
-        RGB(0x00, 0x00, 0x00),  /* black */
-        RGB(0xaa, 0x00, 0x00),  /* red */
-        RGB(0x00, 0xaa, 0x00),  /* green */
-        RGB(0xaa, 0xaa, 0x00),  /* yellow */
-        RGB(0x00, 0x00, 0xaa),  /* blue */
-        RGB(0xaa, 0x00, 0xaa),  /* magenta */
-        RGB(0x00, 0xaa, 0xaa),  /* cyan */
-        RGB(0xaa, 0xaa, 0xaa),  /* white */
+        QEMU_RGB(0x00, 0x00, 0x00),  /* black */
+        QEMU_RGB(0xaa, 0x00, 0x00),  /* red */
+        QEMU_RGB(0x00, 0xaa, 0x00),  /* green */
+        QEMU_RGB(0xaa, 0xaa, 0x00),  /* yellow */
+        QEMU_RGB(0x00, 0x00, 0xaa),  /* blue */
+        QEMU_RGB(0xaa, 0x00, 0xaa),  /* magenta */
+        QEMU_RGB(0x00, 0xaa, 0xaa),  /* cyan */
+        QEMU_RGB(0xaa, 0xaa, 0xaa),  /* white */
     },
     {   /* bright */
-        RGB(0x00, 0x00, 0x00),  /* black */
-        RGB(0xff, 0x00, 0x00),  /* red */
-        RGB(0x00, 0xff, 0x00),  /* green */
-        RGB(0xff, 0xff, 0x00),  /* yellow */
-        RGB(0x00, 0x00, 0xff),  /* blue */
-        RGB(0xff, 0x00, 0xff),  /* magenta */
-        RGB(0x00, 0xff, 0xff),  /* cyan */
-        RGB(0xff, 0xff, 0xff),  /* white */
+        QEMU_RGB(0x00, 0x00, 0x00),  /* black */
+        QEMU_RGB(0xff, 0x00, 0x00),  /* red */
+        QEMU_RGB(0x00, 0xff, 0x00),  /* green */
+        QEMU_RGB(0xff, 0xff, 0x00),  /* yellow */
+        QEMU_RGB(0x00, 0x00, 0xff),  /* blue */
+        QEMU_RGB(0xff, 0x00, 0xff),  /* magenta */
+        QEMU_RGB(0x00, 0xff, 0xff),  /* cyan */
+        QEMU_RGB(0xff, 0xff, 0xff),  /* white */
     }
 };
 
@@ -563,7 +619,6 @@ static void console_put_lf(TextConsole *
     TextCell *c;
     int x, y1;
 
-    s->x = 0;
     s->y++;
     if (s->y >= s->height) {
         s->y = s->height - 1;
@@ -712,15 +767,12 @@ static void console_putchar(TextConsole 
             console_put_lf(s);
             break;
         case '\b':  /* backspace */
-            if(s->x > 0) s->x--;
-            y1 = (s->y_base + s->y) % s->total_height;
-            c = &s->cells[y1 * s->width + s->x];
-            c->ch = ' ';
-            c->t_attrib = s->t_attrib;
-            update_xy(s, s->x, s->y);
+            if (s->x > 0) 
+                s->x--;
             break;
         case '\t':  /* tabspace */
             if (s->x + (8 - (s->x % 8)) > s->width) {
+                s->x = 0;
                 console_put_lf(s);
             } else {
                 s->x = s->x + (8 - (s->x % 8));
@@ -739,8 +791,10 @@ static void console_putchar(TextConsole 
             c->t_attrib = s->t_attrib;
             update_xy(s, s->x, s->y);
             s->x++;
-            if (s->x >= s->width)
+            if (s->x >= s->width) {
+                s->x = 0;
                 console_put_lf(s);
+            }
             break;
         }
         break;
@@ -835,6 +889,7 @@ static void console_chr_add_read_handler
                                          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;
 }
@@ -854,6 +909,28 @@ static void console_send_event(CharDrive
     }
 }
 
+static void kbd_send_chars(void *opaque)
+{
+    TextConsole *s = opaque;
+    int len;
+    uint8_t buf[16];
+    
+    len = s->fd_can_read(s->fd_opaque);
+    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);
+    }
+    /* characters are pending: we send them a bit later (XXX:
+       horrible, should change char device API) */
+    if (s->out_fifo.count > 0) {
+        qemu_mod_timer(s->kbd_timer, qemu_get_clock(rt_clock) + 1);
+    }
+}
+
 /* called when an ascii key is pressed */
 void kbd_put_keysym(int keysym)
 {
@@ -879,25 +956,26 @@ void kbd_put_keysym(int keysym)
         console_scroll(10);
         break;
     default:
+        /* convert the QEMU keysym to VT100 key string */
+        q = buf;
+        if (keysym >= 0xe100 && keysym <= 0xe11f) {
+            *q++ = '\033';
+            *q++ = '[';
+            c = keysym - 0xe100;
+            if (c >= 10)
+                *q++ = '0' + (c / 10);
+            *q++ = '0' + (c % 10);
+            *q++ = '~';
+        } else if (keysym >= 0xe120 && keysym <= 0xe17f) {
+            *q++ = '\033';
+            *q++ = '[';
+            *q++ = keysym & 0xff;
+        } else {
+                *q++ = keysym;
+        }
         if (s->fd_read) {
-            /* convert the QEMU keysym to VT100 key string */
-            q = buf;
-            if (keysym >= 0xe100 && keysym <= 0xe11f) {
-                *q++ = '\033';
-                *q++ = '[';
-                c = keysym - 0xe100;
-                if (c >= 10)
-                    *q++ = '0' + (c / 10);
-                *q++ = '0' + (c % 10);
-                *q++ = '~';
-            } else if (keysym >= 0xe120 && keysym <= 0xe17f) {
-                *q++ = '\033';
-                *q++ = '[';
-                *q++ = keysym & 0xff;
-            } else {
-                *q++ = keysym;
-            }
-            s->fd_read(s->fd_opaque, buf, q - buf);
+            qemu_fifo_write(&s->out_fifo, buf, q - buf);
+            kbd_send_chars(s);
         }
         break;
     }
@@ -984,6 +1062,10 @@ CharDriverState *text_console_init(Displ
     chr->chr_add_read_handler = console_chr_add_read_handler;
     chr->chr_send_event = console_send_event;
 
+    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);
+    
     if (!color_inited) {
         color_inited = 1;
         set_color_table(ds);
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/cpu-all.h
--- a/tools/ioemu/cpu-all.h     Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/cpu-all.h     Mon Aug 07 18:25:30 2006 +0100
@@ -878,6 +878,10 @@ extern uint8_t *phys_ram_dirty;
 #define IO_MEM_ROM         (1 << IO_MEM_SHIFT) /* hardcoded offset */
 #define IO_MEM_UNASSIGNED  (2 << IO_MEM_SHIFT)
 #define IO_MEM_NOTDIRTY    (4 << IO_MEM_SHIFT) /* used internally, never use 
directly */
+/* acts like a ROM when read and like a device when written. As an
+   exception, the write memory callback gets the ram offset instead of
+   the physical address */
+#define IO_MEM_ROMD        (1)
 
 typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, 
uint32_t value);
 typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
@@ -946,13 +950,105 @@ void dump_exec_info(FILE *f,
 void dump_exec_info(FILE *f,
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
 
+/*******************************************/
+/* host CPU ticks (if available) */
+
+#if defined(__powerpc__)
+
+static inline uint32_t get_tbl(void) 
+{
+    uint32_t tbl;
+    asm volatile("mftb %0" : "=r" (tbl));
+    return tbl;
+}
+
+static inline uint32_t get_tbu(void) 
+{
+       uint32_t tbl;
+       asm volatile("mftbu %0" : "=r" (tbl));
+       return tbl;
+}
+
+static inline int64_t cpu_get_real_ticks(void)
+{
+    uint32_t l, h, h1;
+    /* NOTE: we test if wrapping has occurred */
+    do {
+        h = get_tbu();
+        l = get_tbl();
+        h1 = get_tbu();
+    } while (h != h1);
+    return ((int64_t)h << 32) | l;
+}
+
+#elif defined(__i386__)
+
+static inline int64_t cpu_get_real_ticks(void)
+{
+    int64_t val;
+    asm volatile ("rdtsc" : "=A" (val));
+    return val;
+}
+
+#elif defined(__x86_64__)
+
+static inline int64_t cpu_get_real_ticks(void)
+{
+    uint32_t low,high;
+    int64_t val;
+    asm volatile("rdtsc" : "=a" (low), "=d" (high));
+    val = high;
+    val <<= 32;
+    val |= low;
+    return val;
+}
+
+#elif defined(__ia64)
+
+static inline int64_t cpu_get_real_ticks(void)
+{
+       int64_t val;
+       asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory");
+       return val;
+}
+
+#elif defined(__s390__)
+
+static inline int64_t cpu_get_real_ticks(void)
+{
+    int64_t val;
+    asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc");
+    return val;
+}
+
+#elif defined(__sparc_v9__)
+
+static inline int64_t cpu_get_real_ticks (void)
+{
+#if     defined(_LP64)
+        uint64_t        rval;
+        asm volatile("rd %%tick,%0" : "=r"(rval));
+        return rval;
+#else
+        union {
+                uint64_t i64;
+                struct {
+                        uint32_t high;
+                        uint32_t low;
+                }       i32;
+        } rval;
+        asm volatile("rd %%tick,%1; srlx %1,32,%0"
+                : "=r"(rval.i32.high), "=r"(rval.i32.low));
+        return rval.i64;
+#endif
+}
+#endif
+
 /* profiling */
 #ifdef CONFIG_PROFILER
 static inline int64_t profile_getclock(void)
 {
-    int64_t val;
-    asm volatile ("rdtsc" : "=A" (val));
-    return val;
+    return cpu_get_real_ticks();
 }
 
 extern int64_t kqemu_time, kqemu_time_start;
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/cpu-defs.h
--- a/tools/ioemu/cpu-defs.h    Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/cpu-defs.h    Mon Aug 07 18:25:30 2006 +0100
@@ -47,7 +47,7 @@ typedef uint32_t target_ulong;
 #elif TARGET_LONG_SIZE == 8
 typedef int64_t target_long;
 typedef uint64_t target_ulong;
-#define TARGET_FMT_lx "%016llx"
+#define TARGET_FMT_lx "%016" PRIx64
 #else
 #error TARGET_LONG_SIZE undefined
 #endif
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/cpu-exec.c
--- a/tools/ioemu/cpu-exec.c    Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/cpu-exec.c    Mon Aug 07 18:25:30 2006 +0100
@@ -47,7 +47,7 @@ void cpu_loop_exit(void)
     longjmp(env->jmp_env, 1);
 }
 #endif
-#ifndef TARGET_SPARC
+#if !(defined(TARGET_SPARC) || defined(TARGET_SH4))
 #define reg_T2
 #endif
 
@@ -175,9 +175,13 @@ static inline TranslationBlock *tb_find_
     pc = env->regs[15];
 #elif defined(TARGET_SPARC)
 #ifdef TARGET_SPARC64
-    flags = (env->pstate << 2) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
-#else
-    flags = env->psrs | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1);
+    // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
+    flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
+        | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
+#else
+    // FPU enable . MMU enabled . MMU no-fault . Supervisor
+    flags = (env->psref << 3) | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1)
+        | env->psrs;
 #endif
     cs_base = env->npc;
     pc = env->pc;
@@ -253,7 +257,7 @@ int cpu_exec(CPUState *env1)
     uint32_t *saved_regwptr;
 #endif
 #endif
-#ifdef __sparc__
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
     int saved_i7, tmp_T0;
 #endif
     int ret, interrupt_request;
@@ -323,7 +327,7 @@ int cpu_exec(CPUState *env1)
 #if defined(reg_T2)
     saved_T2 = T2;
 #endif
-#ifdef __sparc__
+#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
@@ -447,7 +451,7 @@ int cpu_exec(CPUState *env1)
 
             T0 = 0; /* force lookup of first TB */
             for(;;) {
-#ifdef __sparc__
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
                 /* g1 can be modified by some libc? functions */ 
                 tmp_T0 = T0;
 #endif     
@@ -467,7 +471,7 @@ int cpu_exec(CPUState *env1)
                         do_interrupt(intno, 0, 0, 0, 1);
                         /* ensure that no TB jump will be modified as
                            the program flow was changed */
-#ifdef __sparc__
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
                         tmp_T0 = 0;
 #else
                         T0 = 0;
@@ -486,7 +490,7 @@ int cpu_exec(CPUState *env1)
                            env->error_code = 0;
                             do_interrupt(env);
                             env->interrupt_request &= ~CPU_INTERRUPT_HARD;
-#ifdef __sparc__
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
                             tmp_T0 = 0;
 #else
                             T0 = 0;
@@ -497,7 +501,7 @@ int cpu_exec(CPUState *env1)
                             env->error_code = 0;
                             do_interrupt(env);
                             env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
-#ifdef __sparc__
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
                             tmp_T0 = 0;
 #else
                             T0 = 0;
@@ -516,7 +520,7 @@ int cpu_exec(CPUState *env1)
                         env->error_code = 0;
                         do_interrupt(env);
                         env->interrupt_request &= ~CPU_INTERRUPT_HARD;
-#ifdef __sparc__
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
                         tmp_T0 = 0;
 #else
                         T0 = 0;
@@ -534,7 +538,7 @@ int cpu_exec(CPUState *env1)
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
                            do_interrupt(env->interrupt_index);
                            env->interrupt_index = 0;
-#ifdef __sparc__
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
                             tmp_T0 = 0;
 #else
                             T0 = 0;
@@ -561,11 +565,13 @@ int cpu_exec(CPUState *env1)
 #elif defined(TARGET_SH4)
                    /* XXXXX */
 #endif
+                   /* Don't use the cached interupt_request value,
+                      do_interrupt may have updated the EXITTB flag. */
                     if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
                         env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
                         /* ensure that no TB jump will be modified as
                            the program flow was changed */
-#ifdef __sparc__
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
                         tmp_T0 = 0;
 #else
                         T0 = 0;
@@ -633,7 +639,7 @@ int cpu_exec(CPUState *env1)
                             lookup_symbol(tb->pc));
                 }
 #endif
-#ifdef __sparc__
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
                 T0 = tmp_T0;
 #endif     
                 /* see if we can patch the calling TB. When the TB
@@ -669,7 +675,9 @@ int cpu_exec(CPUState *env1)
                                      "mov      %%o7,%%i0"
                                      : /* no outputs */
                                      : "r" (gen_func) 
-                                     : "i0", "i1", "i2", "i3", "i4", "i5");
+                                     : "i0", "i1", "i2", "i3", "i4", "i5",
+                                       "l0", "l1", "l2", "l3", "l4", "l5",
+                                       "l6", "l7");
 #elif defined(__arm__)
                 asm volatile ("mov pc, %0\n\t"
                               ".global exec_loop\n\t"
@@ -834,7 +842,7 @@ int cpu_exec(CPUState *env1)
 #else
 #error unsupported target CPU
 #endif
-#ifdef __sparc__
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
     asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
 #endif
     T0 = saved_T0;
@@ -1168,19 +1176,14 @@ static inline int handle_cpu_signal(unsi
            a virtual CPU fault */
         cpu_restore_state(tb, env, pc, puc);
     }
-    if (ret == 1) {
 #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);
-        //        do_raise_exception_err(env->exception_index, 
env->error_code);
-    } else {
-        /* activate soft MMU for this block */
-        cpu_resume_from_signal(env, puc);
-    }
+    sigprocmask(SIG_SETMASK, old_set, NULL);
+    cpu_loop_exit();
     /* never comes here */
     return 1;
 }
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/disas.c
--- a/tools/ioemu/disas.c       Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/disas.c       Mon Aug 07 18:25:30 2006 +0100
@@ -58,7 +58,7 @@ perror_memory (status, memaddr, info)
     /* Actually, address between memaddr and memaddr + len was
        out of bounds.  */
     (*info->fprintf_func) (info->stream,
-                          "Address 0x%llx is out of bounds.\n", memaddr);
+                          "Address 0x%" PRIx64 " is out of bounds.\n", 
memaddr);
 }
 
 /* This could be in a separate file, to save miniscule amounts of space
@@ -73,7 +73,7 @@ generic_print_address (addr, info)
      bfd_vma addr;
      struct disassemble_info *info;
 {
-    (*info->fprintf_func) (info->stream, "0x%llx", addr);
+    (*info->fprintf_func) (info->stream, "0x%" PRIx64, addr);
 }
 
 /* Just return the given address.  */
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/dyngen-exec.h
--- a/tools/ioemu/dyngen-exec.h Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/dyngen-exec.h Mon Aug 07 18:25:30 2006 +0100
@@ -35,11 +35,14 @@ typedef unsigned char uint8_t;
 typedef unsigned char uint8_t;
 typedef unsigned short uint16_t;
 typedef unsigned int uint32_t;
+// Linux/Sparc64 defines uint64_t
+#if !(defined (__sparc_v9__) && defined(__linux__))
 /* XXX may be done for all 64 bits targets ? */
 #if defined (__x86_64__) || defined(__ia64)
 typedef unsigned long uint64_t;
 #else
 typedef unsigned long long uint64_t;
+#endif
 #endif
 
 /* if Solaris/__sun__, don't typedef int8_t, as it will be typedef'd
@@ -50,10 +53,13 @@ typedef signed char int8_t;
 #endif
 typedef signed short int16_t;
 typedef signed int int32_t;
+// Linux/Sparc64 defines int64_t
+#if !(defined (__sparc_v9__) && defined(__linux__))
 #if defined (__x86_64__) || defined(__ia64)
 typedef signed long int64_t;
 #else
 typedef signed long long int64_t;
+#endif
 #endif
 
 #define INT8_MIN               (-128)
@@ -121,6 +127,19 @@ extern int printf(const char *, ...);
 #define AREG3 "s2"
 #endif
 #ifdef __sparc__
+#ifdef HOST_SOLARIS
+#define AREG0 "g2"
+#define AREG1 "g3"
+#define AREG2 "g4"
+#define AREG3 "g5"
+#define AREG4 "g6"
+#else
+#ifdef __sparc_v9__
+#define AREG0 "g1"
+#define AREG1 "g4"
+#define AREG2 "g5"
+#define AREG3 "g7"
+#else
 #define AREG0 "g6"
 #define AREG1 "g1"
 #define AREG2 "g2"
@@ -133,6 +152,8 @@ extern int printf(const char *, ...);
 #define AREG9 "l5"
 #define AREG10 "l6"
 #define AREG11 "l7"
+#endif
+#endif
 #define USE_FP_CONVERT
 #endif
 #ifdef __s390__
@@ -241,10 +262,8 @@ extern int __op_jmp0, __op_jmp1, __op_jm
                                          ASM_NAME(__op_gen_label) #n)
 #endif
 #ifdef __sparc__
-#define EXIT_TB() asm volatile ("jmpl %i0 + 8, %g0\n" \
-                                "nop")
-#define        GOTO_LABEL_PARAM(n) asm volatile ( \
-               "set " ASM_NAME(__op_gen_label) #n ", %g1; jmp %g1; nop")
+#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__
 #define EXIT_TB() asm volatile ("b exec_loop")
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/dyngen.c
--- a/tools/ioemu/dyngen.c      Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/dyngen.c      Mon Aug 07 18:25:30 2006 +0100
@@ -1196,7 +1196,7 @@ void get_reloc_expr(char *name, int name
     } else {
 #ifdef HOST_SPARC
         if (sym_name[0] == '.')
-            snprintf(name, sizeof(name),
+            snprintf(name, name_size,
                      "(long)(&__dot_%s)",
                      sym_name + 1);
         else
@@ -1440,6 +1440,15 @@ void gen_code(const char *name, host_ulo
     }
 #elif defined(HOST_SPARC)
     {
+#define INSN_SAVE       0x9de3a000
+#define INSN_RET        0x81c7e008
+#define INSN_RETL       0x81c3e008
+#define INSN_RESTORE    0x81e80000
+#define INSN_RETURN     0x81cfe008
+#define INSN_NOP        0x01000000
+#define INSN_ADD_SP     0x9c03a000 // add %sp, nn, %sp
+#define INSN_SUB_SP     0x9c23a000 // sub %sp, nn, %sp
+
         uint32_t start_insn, end_insn1, end_insn2;
         uint8_t *p;
         p = (void *)(p_end - 8);
@@ -1448,13 +1457,21 @@ void gen_code(const char *name, host_ulo
         start_insn = get32((uint32_t *)(p_start + 0x0));
         end_insn1 = get32((uint32_t *)(p + 0x0));
         end_insn2 = get32((uint32_t *)(p + 0x4));
-        if ((start_insn & ~0x1fff) == 0x9de3a000) {
+        if (((start_insn & ~0x1fff) == INSN_SAVE) ||
+            (start_insn & ~0x1fff) == INSN_ADD_SP) {
             p_start += 0x4;
             start_offset += 0x4;
-            if ((int)(start_insn | ~0x1fff) < -128)
-                error("Found bogus save at the start of %s", name);
-            if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000)
+            if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
+                /* SPARC v7: ret; restore; */ ;
+            else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
+                /* SPARC v9: return; nop; */ ;
+            else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == 
INSN_SUB_SP)
+                /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
+            else
+
                 error("ret; restore; not found at end of %s", name);
+        } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
+            ;
         } else {
             error("No save at the beginning of %s", name);
         }
@@ -1462,7 +1479,7 @@ void gen_code(const char *name, host_ulo
         /* Skip a preceeding nop, if present.  */
         if (p > p_start) {
             skip_insn = get32((uint32_t *)(p - 0x4));
-            if (skip_insn == 0x01000000)
+            if (skip_insn == INSN_NOP)
                 p -= 4;
         }
 #endif
@@ -1470,21 +1487,41 @@ void gen_code(const char *name, host_ulo
     }
 #elif defined(HOST_SPARC64)
     {
+#define INSN_SAVE       0x9de3a000
+#define INSN_RET        0x81c7e008
+#define INSN_RETL       0x81c3e008
+#define INSN_RESTORE    0x81e80000
+#define INSN_RETURN     0x81cfe008
+#define INSN_NOP        0x01000000
+#define INSN_ADD_SP     0x9c03a000 // add %sp, nn, %sp
+#define INSN_SUB_SP     0x9c23a000 // sub %sp, nn, %sp
+
         uint32_t start_insn, end_insn1, end_insn2, skip_insn;
         uint8_t *p;
         p = (void *)(p_end - 8);
+#if 0
+        /* XXX: check why it occurs */
         if (p <= p_start)
             error("empty code for %s", name);
+#endif
         start_insn = get32((uint32_t *)(p_start + 0x0));
         end_insn1 = get32((uint32_t *)(p + 0x0));
         end_insn2 = get32((uint32_t *)(p + 0x4));
-        if ((start_insn & ~0x1fff) == 0x9de3a000) {
+        if (((start_insn & ~0x1fff) == INSN_SAVE) ||
+            (start_insn & ~0x1fff) == INSN_ADD_SP) {
             p_start += 0x4;
             start_offset += 0x4;
-            if ((int)(start_insn | ~0x1fff) < -256)
-                error("Found bogus save at the start of %s", name);
-            if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000)
+            if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
+                /* SPARC v7: ret; restore; */ ;
+            else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
+                /* SPARC v9: return; nop; */ ;
+            else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == 
INSN_SUB_SP)
+                /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
+            else
+
                 error("ret; restore; not found at end of %s", name);
+        } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
+            ;
         } else {
             error("No save at the beginning of %s", name);
         }
@@ -2151,6 +2188,18 @@ void gen_code(const char *name, host_ulo
                                    reloc_offset, reloc_offset, name, addend,
                                    reloc_offset);
                            break;
+                        case R_SPARC_WDISP22:
+                            fprintf(outfile,
+                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
+                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
+                                    " & ~0x3fffff) "
+                                    " | ((((%s + %d) - (long)(gen_code_ptr + 
%d))>>2) "
+                                    "    & 0x3fffff);\n",
+                                    rel->r_offset - start_offset,
+                                    rel->r_offset - start_offset,
+                                    name, addend,
+                                    rel->r_offset - start_offset);
+                            break;
                         default:
                             error("unsupported sparc relocation (%d)", type);
                         }
@@ -2168,7 +2217,7 @@ void gen_code(const char *name, host_ulo
                        rel->r_offset < start_offset + copy_size) {
                         sym_name = strtab + 
symtab[ELF64_R_SYM(rel->r_info)].st_name;
                         get_reloc_expr(name, sizeof(name), sym_name);
-                        type = ELF64_R_TYPE(rel->r_info);
+                        type = ELF32_R_TYPE(rel->r_info);
                         addend = rel->r_addend;
                         reloc_offset = rel->r_offset - start_offset;
                         switch(type) {
@@ -2192,6 +2241,15 @@ void gen_code(const char *name, host_ulo
                                    " | ((%s + %d) & 0x3ff);\n",
                                     reloc_offset, reloc_offset, name, addend);
                            break;
+                        case R_SPARC_OLO10:
+                            addend += ELF64_R_TYPE_DATA (rel->r_info);
+                            fprintf(outfile,
+                                   "    *(uint32_t *)(gen_code_ptr + %d) = "
+                                   "((*(uint32_t *)(gen_code_ptr + %d)) "
+                                   " & ~0x3ff) "
+                                   " | ((%s + %d) & 0x3ff);\n",
+                                    reloc_offset, reloc_offset, name, addend);
+                           break;
                        case R_SPARC_WDISP30:
                            fprintf(outfile,
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
@@ -2202,8 +2260,18 @@ void gen_code(const char *name, host_ulo
                                    reloc_offset, reloc_offset, name, addend,
                                    reloc_offset);
                            break;
+                        case R_SPARC_WDISP22:
+                            fprintf(outfile,
+                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
+                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
+                                    " & ~0x3fffff) "
+                                    " | ((((%s + %d) - (long)(gen_code_ptr + 
%d))>>2) "
+                                    "    & 0x3fffff);\n",
+                                    reloc_offset, reloc_offset, name, addend,
+                                   reloc_offset);
+                            break;
                         default:
-                           error("unsupported sparc64 relocation (%d)", type);
+                           error("unsupported sparc64 relocation (%d) for 
symbol %s", type, name);
                         }
                     }
                 }
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/dyngen.h
--- a/tools/ioemu/dyngen.h      Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/dyngen.h      Mon Aug 07 18:25:30 2006 +0100
@@ -19,7 +19,13 @@
  */
 
 int __op_param1, __op_param2, __op_param3;
-int __op_gen_label1, __op_gen_label2, __op_gen_label3;
+#ifdef __sparc__
+  void __op_gen_label1(){}
+  void __op_gen_label2(){}
+  void __op_gen_label3(){}
+#else
+  int __op_gen_label1, __op_gen_label2, __op_gen_label3;
+#endif
 int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
 
 #ifdef __i386__
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/elf.h
--- a/tools/ioemu/elf.h Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/elf.h Mon Aug 07 18:25:30 2006 +0100
@@ -227,6 +227,7 @@ typedef struct {
 
 #define ELF64_R_SYM(i)                 ((i) >> 32)
 #define ELF64_R_TYPE(i)                        ((i) & 0xffffffff)
+#define ELF64_R_TYPE_DATA(i)            (((ELF64_R_TYPE(i) >> 8) ^ 0x00800000) 
- 0x00800000)
 
 #define R_386_NONE     0
 #define R_386_32       1
@@ -326,6 +327,7 @@ typedef struct {
 #define R_SPARC_10             30
 #define R_SPARC_11             31
 #define R_SPARC_64             32
+#define R_SPARC_OLO10           33
 #define R_SPARC_WDISP16                40
 #define R_SPARC_WDISP19                41
 #define R_SPARC_7              43
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/exec-all.h
--- a/tools/ioemu/exec-all.h    Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/exec-all.h    Mon Aug 07 18:25:30 2006 +0100
@@ -571,7 +571,7 @@ static inline target_ulong get_phys_addr
         ldub_code(addr);
     }
     pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK;
-    if (pd > IO_MEM_ROM) {
+    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);
     }
     return addr + env->tlb_table[is_user][index].addend - (unsigned 
long)phys_ram_base;
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/exec.c
--- a/tools/ioemu/exec.c        Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/exec.c        Mon Aug 07 18:25:30 2006 +0100
@@ -1488,7 +1488,7 @@ int tlb_set_page_exec(CPUState *env, tar
     if (is_softmmu) 
 #endif
     {
-        if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
+        if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
             /* IO memory case */
             address = vaddr | pd;
             addend = paddr;
@@ -1513,9 +1513,11 @@ int tlb_set_page_exec(CPUState *env, tar
             te->addr_code = -1;
         }
         if (prot & PAGE_WRITE) {
-            if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM) {
-                /* ROM: access is ignored (same as unassigned) */
-                te->addr_write = vaddr | IO_MEM_ROM;
+            if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM || 
+                (pd & IO_MEM_ROMD)) {
+                /* write access calls the I/O callback */
+                te->addr_write = vaddr | 
+                    (pd & ~(TARGET_PAGE_MASK | IO_MEM_ROMD));
             } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && 
                        !cpu_physical_memory_is_dirty(pd)) {
                 te->addr_write = vaddr | IO_MEM_NOTDIRTY;
@@ -1779,14 +1781,23 @@ void cpu_register_physical_memory(target
 {
     target_phys_addr_t addr, end_addr;
     PhysPageDesc *p;
+    CPUState *env;
 
     size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
     end_addr = start_addr + size;
     for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
         p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
         p->phys_offset = phys_offset;
-        if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM)
+        if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
+            (phys_offset & IO_MEM_ROMD))
             phys_offset += TARGET_PAGE_SIZE;
+    }
+    
+    /* since each CPU stores ram addresses in its TLB cache, we must
+       reset the modified entries */
+    /* XXX: slow ! */
+    for(env = first_cpu; env != NULL; env = env->next_cpu) {
+        tlb_flush(env, 1);
     }
 }
 
@@ -2048,7 +2059,8 @@ void cpu_physical_memory_rw(target_phys_
                 }
             }
         } else {
-            if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
+            if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && 
+                !(pd & IO_MEM_ROMD)) {
                 /* I/O case */
                 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
                 if (l >= 4 && ((addr & 3) == 0)) {
@@ -2103,7 +2115,8 @@ void cpu_physical_memory_write_rom(targe
         }
         
         if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
-            (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM) {
+            (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
+            !(pd & IO_MEM_ROMD)) {
             /* do nothing */
         } else {
             unsigned long addr1;
@@ -2135,7 +2148,8 @@ uint32_t ldl_phys(target_phys_addr_t add
         pd = p->phys_offset;
     }
         
-    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
+    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && 
+        !(pd & IO_MEM_ROMD)) {
         /* I/O case */
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
@@ -2164,7 +2178,8 @@ uint64_t ldq_phys(target_phys_addr_t add
         pd = p->phys_offset;
     }
         
-    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
+    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
+        !(pd & IO_MEM_ROMD)) {
         /* I/O case */
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
 #ifdef TARGET_WORDS_BIGENDIAN
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/fpu/softfloat-native.c
--- a/tools/ioemu/fpu/softfloat-native.c        Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/fpu/softfloat-native.c        Mon Aug 07 18:25:30 2006 +0100
@@ -6,7 +6,7 @@ void set_float_rounding_mode(int val STA
 void set_float_rounding_mode(int val STATUS_PARAM)
 {
     STATUS(float_rounding_mode) = val;
-#if defined(_BSD) && !defined(__APPLE__)
+#if defined(_BSD) && !defined(__APPLE__) || (defined(HOST_SOLARIS) && 
HOST_SOLARIS < 10)
     fpsetround(val);
 #elif defined(__arm__)
     /* nothing to do */
@@ -22,9 +22,14 @@ void set_floatx80_rounding_precision(int
 }
 #endif
 
-#if defined(_BSD)
-#define lrint(d)               ((long)rint(d))
-#define llrint(d)              ((long long)rint(d))
+#if defined(_BSD) || (defined(HOST_SOLARIS) && HOST_SOLARIS < 10)
+#define lrint(d)               ((int32_t)rint(d))
+#define llrint(d)              ((int64_t)rint(d))
+#define lrintf(f)              ((int32_t)rint(f))
+#define llrintf(f)             ((int64_t)rint(f))
+#define sqrtf(f)               ((float)sqrt(f))
+#define remainderf(fa, fb)     ((float)remainder(fa, fb))
+#define rintf(f)               ((float)rint(f))
 #endif
 
 #if defined(__powerpc__)
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/gdbstub.c
--- a/tools/ioemu/gdbstub.c     Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/gdbstub.c     Mon Aug 07 18:25:30 2006 +0100
@@ -17,6 +17,7 @@
  * 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 "config.h"
 #ifdef CONFIG_USER_ONLY
 #include <stdlib.h>
 #include <stdio.h>
@@ -24,16 +25,25 @@
 #include <string.h>
 #include <errno.h>
 #include <unistd.h>
+#include <fcntl.h>
 
 #include "qemu.h"
 #else
 #include "vl.h"
 #endif
 
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
+#include "qemu_socket.h"
+#ifdef _WIN32
+/* XXX: these constants may be independent of the host ones even for Unix */
+#ifndef SIGTRAP
+#define SIGTRAP 5
+#endif
+#ifndef SIGINT
+#define SIGINT 2
+#endif
+#else
 #include <signal.h>
+#endif
 
 //#define DEBUG_GDB
 
@@ -69,7 +79,7 @@ static int get_char(GDBState *s)
     int ret;
 
     for(;;) {
-        ret = read(s->fd, &ch, 1);
+        ret = recv(s->fd, &ch, 1, 0);
         if (ret < 0) {
             if (errno != EINTR && errno != EAGAIN)
                 return -1;
@@ -87,7 +97,7 @@ static void put_buffer(GDBState *s, cons
     int ret;
 
     while (len > 0) {
-        ret = write(s->fd, buf, len);
+        ret = send(s->fd, buf, len, 0);
         if (ret < 0) {
             if (errno != EINTR && errno != EAGAIN)
                 return;
@@ -305,11 +315,11 @@ static int cpu_gdb_read_registers(CPUSta
     for(i = 0; i < 24; i++) {
         registers[i + 8] = tswapl(env->regwptr[i]);
     }
+#ifndef TARGET_SPARC64
     /* fill in fprs */
     for (i = 0; i < 32; i++) {
         registers[i + 32] = tswapl(*((uint32_t *)&env->fpr[i]));
     }
-#ifndef TARGET_SPARC64
     /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
     registers[64] = tswapl(env->y);
     {
@@ -327,16 +337,21 @@ static int cpu_gdb_read_registers(CPUSta
     registers[72] = 0;
     return 73 * sizeof(target_ulong);
 #else
-    for (i = 0; i < 32; i += 2) {
-        registers[i/2 + 64] = tswapl(*((uint64_t *)&env->fpr[i]));
-    }
-    registers[81] = tswapl(env->pc);
-    registers[82] = tswapl(env->npc);
-    registers[83] = tswapl(env->tstate[env->tl]);
-    registers[84] = tswapl(env->fsr);
-    registers[85] = tswapl(env->fprs);
-    registers[86] = tswapl(env->y);
-    return 87 * sizeof(target_ulong);
+    /* fill in fprs */
+    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;
+    }
+    registers[64] = tswapl(env->pc);
+    registers[65] = tswapl(env->npc);
+    registers[66] = tswapl(env->tstate[env->tl]);
+    registers[67] = tswapl(env->fsr);
+    registers[68] = tswapl(env->fprs);
+    registers[69] = tswapl(env->y);
+    return 70 * sizeof(target_ulong);
 #endif
 }
 
@@ -353,11 +368,11 @@ static void cpu_gdb_write_registers(CPUS
     for(i = 0; i < 24; i++) {
         env->regwptr[i] = tswapl(registers[i + 8]);
     }
+#ifndef TARGET_SPARC64
     /* fill in fprs */
     for (i = 0; i < 32; i++) {
         *((uint32_t *)&env->fpr[i]) = tswapl(registers[i + 32]);
     }
-#ifndef TARGET_SPARC64
     /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
     env->y = tswapl(registers[64]);
     PUT_PSR(env, tswapl(registers[65]));
@@ -367,18 +382,16 @@ static void cpu_gdb_write_registers(CPUS
     env->npc = tswapl(registers[69]);
     env->fsr = tswapl(registers[70]);
 #else
-    for (i = 0; i < 32; i += 2) {
-       uint64_t tmp;
-       tmp = tswapl(registers[i/2 + 64]) << 32;
-       tmp |= tswapl(registers[i/2 + 64 + 1]);
-        *((uint64_t *)&env->fpr[i]) = tmp;
-    }
-    env->pc = tswapl(registers[81]);
-    env->npc = tswapl(registers[82]);
-    env->tstate[env->tl] = tswapl(registers[83]);
-    env->fsr = tswapl(registers[84]);
-    env->fprs = tswapl(registers[85]);
-    env->y = tswapl(registers[86]);
+    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);
+    }
+    env->pc = tswapl(registers[64]);
+    env->npc = tswapl(registers[65]);
+    env->tstate[env->tl] = tswapl(registers[66]);
+    env->fsr = tswapl(registers[67]);
+    env->fprs = tswapl(registers[68]);
+    env->y = tswapl(registers[69]);
 #endif
 }
 #elif defined (TARGET_ARM)
@@ -494,7 +507,12 @@ static int cpu_gdb_read_registers(CPUSta
   int i;
 
 #define SAVE(x) *ptr++=tswapl(x)
-  for (i = 0; i < 16; i++) SAVE(env->gregs[i]);
+  if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) {
+      for (i = 0; i < 8; i++) SAVE(env->gregs[i + 16]);
+  } else {
+      for (i = 0; i < 8; i++) SAVE(env->gregs[i]);
+  }
+  for (i = 8; i < 16; i++) SAVE(env->gregs[i]);
   SAVE (env->pc);
   SAVE (env->pr);
   SAVE (env->gbr);
@@ -517,7 +535,12 @@ static void cpu_gdb_write_registers(CPUS
   int i;
 
 #define LOAD(x) (x)=*ptr++;
-  for (i = 0; i < 16; i++) LOAD(env->gregs[i]);
+  if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) {
+      for (i = 0; i < 8; i++) LOAD(env->gregs[i + 16]);
+  } else {
+      for (i = 0; i < 8; i++) LOAD(env->gregs[i]);
+  }
+  for (i = 8; i < 16; i++) LOAD(env->gregs[i]);
   LOAD (env->pc);
   LOAD (env->pr);
   LOAD (env->gbr);
@@ -545,7 +568,7 @@ static int gdb_handle_packet(GDBState *s
     char buf[4096];
     uint8_t mem_buf[2000];
     uint32_t *registers;
-    uint32_t addr, len;
+    target_ulong addr, len;
     
 #ifdef DEBUG_GDB
     printf("command='%s'\n", line_buf);
@@ -560,7 +583,7 @@ static int gdb_handle_packet(GDBState *s
         break;
     case 'c':
         if (*p != '\0') {
-            addr = strtoul(p, (char **)&p, 16);
+            addr = strtoull(p, (char **)&p, 16);
 #if defined(TARGET_I386)
             env->eip = addr;
 #elif defined (TARGET_PPC)
@@ -616,10 +639,10 @@ static int gdb_handle_packet(GDBState *s
         put_packet(s, "OK");
         break;
     case 'm':
-        addr = strtoul(p, (char **)&p, 16);
+        addr = strtoull(p, (char **)&p, 16);
         if (*p == ',')
             p++;
-        len = strtoul(p, NULL, 16);
+        len = strtoull(p, NULL, 16);
         if (cpu_memory_rw_debug(env, addr, mem_buf, len, 0) != 0) {
             put_packet (s, "E14");
         } else {
@@ -628,10 +651,10 @@ static int gdb_handle_packet(GDBState *s
         }
         break;
     case 'M':
-        addr = strtoul(p, (char **)&p, 16);
+        addr = strtoull(p, (char **)&p, 16);
         if (*p == ',')
             p++;
-        len = strtoul(p, (char **)&p, 16);
+        len = strtoull(p, (char **)&p, 16);
         if (*p == ':')
             p++;
         hextomem(mem_buf, p, len);
@@ -644,10 +667,10 @@ static int gdb_handle_packet(GDBState *s
         type = strtoul(p, (char **)&p, 16);
         if (*p == ',')
             p++;
-        addr = strtoul(p, (char **)&p, 16);
+        addr = strtoull(p, (char **)&p, 16);
         if (*p == ',')
             p++;
-        len = strtoul(p, (char **)&p, 16);
+        len = strtoull(p, (char **)&p, 16);
         if (type == 0 || type == 1) {
             if (cpu_breakpoint_insert(env, addr) < 0)
                 goto breakpoint_error;
@@ -661,10 +684,10 @@ static int gdb_handle_packet(GDBState *s
         type = strtoul(p, (char **)&p, 16);
         if (*p == ',')
             p++;
-        addr = strtoul(p, (char **)&p, 16);
+        addr = strtoull(p, (char **)&p, 16);
         if (*p == ',')
             p++;
-        len = strtoul(p, (char **)&p, 16);
+        len = strtoull(p, (char **)&p, 16);
         if (type == 0 || type == 1) {
             cpu_breakpoint_remove(env, addr);
             put_packet(s, "OK");
@@ -672,6 +695,18 @@ static int gdb_handle_packet(GDBState *s
             goto breakpoint_error;
         }
         break;
+#ifdef CONFIG_USER_ONLY
+    case 'q':
+        if (strncmp(p, "Offsets", 7) == 0) {
+            TaskState *ts = env->opaque;
+
+            sprintf(buf, "Text=%x;Data=%x;Bss=%x", ts->info->code_offset,
+                ts->info->data_offset, ts->info->data_offset);
+            put_packet(s, buf);
+            break;
+        }
+        /* Fall through.  */
+#endif
     default:
         //        unknown_command:
         /* put empty packet */
@@ -829,7 +864,7 @@ static void gdb_read(void *opaque)
     int i, size;
     uint8_t buf[4096];
 
-    size = read(s->fd, buf, sizeof(buf));
+    size = recv(s->fd, buf, sizeof(buf), 0);
     if (size < 0)
         return;
     if (size == 0) {
@@ -866,7 +901,7 @@ static void gdb_accept(void *opaque)
 
     /* set short latency */
     val = 1;
-    setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
+    setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
     
 #ifdef CONFIG_USER_ONLY
     s = &gdbserver_state;
@@ -881,9 +916,11 @@ static void gdb_accept(void *opaque)
     s->env = first_cpu; /* XXX: allow to change CPU */
     s->fd = fd;
 
+#ifdef CONFIG_USER_ONLY
     fcntl(fd, F_SETFL, O_NONBLOCK);
-
-#ifndef CONFIG_USER_ONLY
+#else
+    socket_set_nonblock(fd);
+
     /* stop the VM */
     vm_stop(EXCP_INTERRUPT);
 
@@ -907,7 +944,7 @@ static int gdbserver_open(int port)
 
     /* allow fast reuse */
     val = 1;
-    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
+    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
 
     sockaddr.sin_family = AF_INET;
     sockaddr.sin_port = htons(port);
@@ -923,7 +960,7 @@ static int gdbserver_open(int port)
         return -1;
     }
 #ifndef CONFIG_USER_ONLY
-    fcntl(fd, F_SETFL, O_NONBLOCK);
+    socket_set_nonblock(fd);
 #endif
     return fd;
 }
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/adlib.c
--- a/tools/ioemu/hw/adlib.c    Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/adlib.c    Mon Aug 07 18:25:30 2006 +0100
@@ -301,6 +301,7 @@ int Adlib_init (AudioState *audio)
     as.freq = conf.freq;
     as.nchannels = SHIFT;
     as.fmt = AUD_FMT_S16;
+    as.endianness = AUDIO_HOST_ENDIANNESS;
 
     AUD_register_card (audio, "adlib", &s->card);
 
@@ -310,8 +311,7 @@ int Adlib_init (AudioState *audio)
         "adlib",
         s,
         adlib_callback,
-        &as,
-        0                       /* XXX: little endian? */
+        &as
         );
     if (!s->voice) {
         Adlib_fini (s);
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/apic.c
--- a/tools/ioemu/hw/apic.c     Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/apic.c     Mon Aug 07 18:25:30 2006 +0100
@@ -239,7 +239,7 @@ void cpu_set_apic_base(CPUState *env, ui
 {
     APICState *s = env->apic_state;
 #ifdef DEBUG_APIC
-    printf("cpu_set_apic_base: %016llx\n", val);
+    printf("cpu_set_apic_base: %016" PRIx64 "\n", val);
 #endif
     s->apicbase = (val & 0xfffff000) | 
         (s->apicbase & (MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE));
@@ -255,7 +255,7 @@ uint64_t cpu_get_apic_base(CPUState *env
 {
     APICState *s = env->apic_state;
 #ifdef DEBUG_APIC
-    printf("cpu_get_apic_base: %016llx\n", (uint64_t)s->apicbase);
+    printf("cpu_get_apic_base: %016" PRIx64 "\n", (uint64_t)s->apicbase);
 #endif
     return s->apicbase;
 }
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/cuda.c
--- a/tools/ioemu/hw/cuda.c     Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/cuda.c     Mon Aug 07 18:25:30 2006 +0100
@@ -209,7 +209,7 @@ static int64_t get_next_irq_time(CUDATim
     }
 #if 0
 #ifdef DEBUG_CUDA
-    printf("latch=%d counter=%lld delta_next=%lld\n", 
+    printf("latch=%d counter=%" PRId64 " delta_next=%" PRId64 "\n", 
            s->latch, d, next_time - d);
 #endif
 #endif
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/es1370.c
--- a/tools/ioemu/hw/es1370.c   Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/es1370.c   Mon Aug 07 18:25:30 2006 +0100
@@ -423,6 +423,7 @@ static void es1370_update_voices (ES1370
                 as.freq = new_freq;
                 as.nchannels = 1 << (new_fmt & 1);
                 as.fmt = (new_fmt & 2) ? AUD_FMT_S16 : AUD_FMT_U8;
+                as.endianness = 0;
 
                 if (i == ADC_CHANNEL) {
                     s->adc_voice =
@@ -432,8 +433,7 @@ static void es1370_update_voices (ES1370
                             "es1370.adc",
                             s,
                             es1370_adc_callback,
-                            &as,
-                            0   /* little endian */
+                            &as
                             );
                 }
                 else {
@@ -444,8 +444,7 @@ static void es1370_update_voices (ES1370
                             i ? "es1370.dac2" : "es1370.dac1",
                             s,
                             i ? es1370_dac2_callback : es1370_dac1_callback,
-                            &as,
-                            0   /* litle endian */
+                            &as
                             );
                 }
             }
@@ -479,8 +478,9 @@ IO_WRITE_PROTO (es1370_writeb)
 IO_WRITE_PROTO (es1370_writeb)
 {
     ES1370State *s = opaque;
+    uint32_t shift, mask;
+
     addr = es1370_fixup (s, addr);
-    uint32_t shift, mask;
 
     switch (addr) {
     case ES1370_REG_CONTROL:
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/esp.c
--- a/tools/ioemu/hw/esp.c      Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/esp.c      Mon Aug 07 18:25:30 2006 +0100
@@ -38,16 +38,13 @@ do { printf("ESP: set_irq(%d): %d\n", (i
 #define ESPDMA_REGS 4
 #define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)
 #define ESP_MAXREG 0x3f
-#define TI_BUFSZ 1024*1024 // XXX
+#define TI_BUFSZ 32
 #define DMA_VER 0xa0000000
 #define DMA_INTR 1
 #define DMA_INTREN 0x10
+#define DMA_WRITE_MEM 0x100
 #define DMA_LOADED 0x04000000
 typedef struct ESPState ESPState;
-
-typedef int ESPDMAFunc(ESPState *s, 
-                       target_phys_addr_t phys_addr, 
-                       int transfer_size1);
 
 struct ESPState {
     BlockDriverState **bd;
@@ -57,12 +54,14 @@ struct ESPState {
     uint32_t espdmaregs[ESPDMA_REGS];
     uint32_t ti_size;
     uint32_t ti_rptr, ti_wptr;
-    int ti_dir;
     uint8_t ti_buf[TI_BUFSZ];
+    int sense;
     int dma;
-    ESPDMAFunc *dma_cb;
-    int64_t offset, len;
-    int target;
+    SCSIDevice *scsi_dev[MAX_DISKS];
+    SCSIDevice *current_dev;
+    uint8_t cmdbuf[TI_BUFSZ];
+    int cmdlen;
+    int do_cmd;
 };
 
 #define STAT_DO 0x00
@@ -83,394 +82,200 @@ struct ESPState {
 #define SEQ_0 0x0
 #define SEQ_CD 0x4
 
-/* XXX: stolen from ide.c, move to common ATAPI/SCSI library */
-static void lba_to_msf(uint8_t *buf, int lba)
-{
-    lba += 150;
-    buf[0] = (lba / 75) / 60;
-    buf[1] = (lba / 75) % 60;
-    buf[2] = lba % 75;
-}
-
-static inline void cpu_to_ube16(uint8_t *buf, int val)
-{
-    buf[0] = val >> 8;
-    buf[1] = val;
-}
-
-static inline void cpu_to_ube32(uint8_t *buf, unsigned int val)
-{
-    buf[0] = val >> 24;
-    buf[1] = val >> 16;
-    buf[2] = val >> 8;
-    buf[3] = val;
-}
-
-/* same toc as bochs. Return -1 if error or the toc length */
-/* XXX: check this */
-static int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int 
start_track)
-{
-    uint8_t *q;
-    int len;
-    
-    if (start_track > 1 && start_track != 0xaa)
-        return -1;
-    q = buf + 2;
-    *q++ = 1; /* first session */
-    *q++ = 1; /* last session */
-    if (start_track <= 1) {
-        *q++ = 0; /* reserved */
-        *q++ = 0x14; /* ADR, control */
-        *q++ = 1;    /* track number */
-        *q++ = 0; /* reserved */
-        if (msf) {
-            *q++ = 0; /* reserved */
-            lba_to_msf(q, 0);
-            q += 3;
-        } else {
-            /* sector 0 */
-            cpu_to_ube32(q, 0);
-            q += 4;
-        }
-    }
-    /* lead out track */
-    *q++ = 0; /* reserved */
-    *q++ = 0x16; /* ADR, control */
-    *q++ = 0xaa; /* track number */
-    *q++ = 0; /* reserved */
-    if (msf) {
-        *q++ = 0; /* reserved */
-        lba_to_msf(q, nb_sectors);
-        q += 3;
-    } else {
-        cpu_to_ube32(q, nb_sectors);
-        q += 4;
-    }
-    len = q - buf;
-    cpu_to_ube16(buf, len - 2);
-    return len;
-}
-
-/* mostly same info as PearPc */
-static int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, 
-                              int session_num)
-{
-    uint8_t *q;
-    int len;
-    
-    q = buf + 2;
-    *q++ = 1; /* first session */
-    *q++ = 1; /* last session */
-
-    *q++ = 1; /* session number */
-    *q++ = 0x14; /* data track */
-    *q++ = 0; /* track number */
-    *q++ = 0xa0; /* lead-in */
-    *q++ = 0; /* min */
-    *q++ = 0; /* sec */
-    *q++ = 0; /* frame */
-    *q++ = 0;
-    *q++ = 1; /* first track */
-    *q++ = 0x00; /* disk type */
-    *q++ = 0x00;
-    
-    *q++ = 1; /* session number */
-    *q++ = 0x14; /* data track */
-    *q++ = 0; /* track number */
-    *q++ = 0xa1;
-    *q++ = 0; /* min */
-    *q++ = 0; /* sec */
-    *q++ = 0; /* frame */
-    *q++ = 0;
-    *q++ = 1; /* last track */
-    *q++ = 0x00;
-    *q++ = 0x00;
-    
-    *q++ = 1; /* session number */
-    *q++ = 0x14; /* data track */
-    *q++ = 0; /* track number */
-    *q++ = 0xa2; /* lead-out */
-    *q++ = 0; /* min */
-    *q++ = 0; /* sec */
-    *q++ = 0; /* frame */
-    if (msf) {
-        *q++ = 0; /* reserved */
-        lba_to_msf(q, nb_sectors);
-        q += 3;
-    } else {
-        cpu_to_ube32(q, nb_sectors);
-        q += 4;
-    }
-
-    *q++ = 1; /* session number */
-    *q++ = 0x14; /* ADR, control */
-    *q++ = 0;    /* track number */
-    *q++ = 1;    /* point */
-    *q++ = 0; /* min */
-    *q++ = 0; /* sec */
-    *q++ = 0; /* frame */
-    if (msf) {
-        *q++ = 0; 
-        lba_to_msf(q, 0);
-        q += 3;
-    } else {
-        *q++ = 0; 
-        *q++ = 0; 
-        *q++ = 0; 
-        *q++ = 0; 
-    }
-
-    len = q - buf;
-    cpu_to_ube16(buf, len - 2);
-    return len;
-}
-
-static int esp_write_dma_cb(ESPState *s, 
-                            target_phys_addr_t phys_addr, 
-                            int transfer_size1)
-{
-    DPRINTF("Write callback (offset %lld len %lld size %d trans_size %d)\n",
-            s->offset, s->len, s->ti_size, transfer_size1);
-    bdrv_write(s->bd[s->target], s->offset, s->ti_buf, s->len);
-    s->offset = 0;
-    s->len = 0;
-    s->target = 0;
-    return 0;
-}
-
-static void handle_satn(ESPState *s)
-{
-    uint8_t buf[32];
+static int get_cmd(ESPState *s, uint8_t *buf)
+{
     uint32_t dmaptr, dmalen;
-    unsigned int i;
-    int64_t nb_sectors;
     int target;
 
     dmalen = s->wregs[0] | (s->wregs[1] << 8);
     target = s->wregs[4] & 7;
-    DPRINTF("Select with ATN len %d target %d\n", dmalen, target);
+    DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
     if (s->dma) {
        dmaptr = iommu_translate(s->espdmaregs[1]);
-       DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 
'w': 'r', dmaptr);
+       DPRINTF("DMA Direction: %c, addr 0x%8.8x\n",
+                s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', dmaptr);
        cpu_physical_memory_read(dmaptr, buf, dmalen);
     } else {
        buf[0] = 0;
        memcpy(&buf[1], s->ti_buf, dmalen);
        dmalen++;
     }
-    for (i = 0; i < dmalen; i++) {
-       DPRINTF("Command %2.2x\n", buf[i]);
-    }
-    s->ti_dir = 0;
+
     s->ti_size = 0;
     s->ti_rptr = 0;
     s->ti_wptr = 0;
 
-    if (target >= 4 || !s->bd[target]) { // No such drive
+    if (target >= 4 || !s->scsi_dev[target]) {
+        // No such drive
        s->rregs[4] = STAT_IN;
        s->rregs[5] = INTR_DC;
        s->rregs[6] = SEQ_0;
        s->espdmaregs[0] |= DMA_INTR;
        pic_set_irq(s->irq, 1);
-       return;
-    }
-    switch (buf[1]) {
-    case 0x0:
-       DPRINTF("Test Unit Ready (len %d)\n", buf[5]);
-       break;
-    case 0x12:
-       DPRINTF("Inquiry (len %d)\n", buf[5]);
-       memset(s->ti_buf, 0, 36);
-       if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {
-           s->ti_buf[0] = 5;
-           memcpy(&s->ti_buf[16], "QEMU CDROM     ", 16);
-       } else {
-           s->ti_buf[0] = 0;
-           memcpy(&s->ti_buf[16], "QEMU HARDDISK  ", 16);
-       }
-       memcpy(&s->ti_buf[8], "QEMU   ", 8);
-       s->ti_buf[2] = 1;
-       s->ti_buf[3] = 2;
-       s->ti_buf[4] = 32;
-       s->ti_dir = 1;
-       s->ti_size = 36;
-       break;
-    case 0x1a:
-       DPRINTF("Mode Sense(6) (page %d, len %d)\n", buf[3], buf[5]);
-       break;
-    case 0x25:
-       DPRINTF("Read Capacity (len %d)\n", buf[5]);
-       memset(s->ti_buf, 0, 8);
-       bdrv_get_geometry(s->bd[target], &nb_sectors);
-       s->ti_buf[0] = (nb_sectors >> 24) & 0xff;
-       s->ti_buf[1] = (nb_sectors >> 16) & 0xff;
-       s->ti_buf[2] = (nb_sectors >> 8) & 0xff;
-       s->ti_buf[3] = nb_sectors & 0xff;
-       s->ti_buf[4] = 0;
-       s->ti_buf[5] = 0;
-       if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM)
-           s->ti_buf[6] = 8; // sector size 2048
-       else
-           s->ti_buf[6] = 2; // sector size 512
-       s->ti_buf[7] = 0;
-       s->ti_dir = 1;
-       s->ti_size = 8;
-       break;
-    case 0x28:
-       {
-           int64_t offset, len;
-
-           if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {
-               offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | 
buf[6]) * 4;
-               len = ((buf[8] << 8) | buf[9]) * 4;
-               s->ti_size = len * 2048;
-           } else {
-               offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | 
buf[6];
-               len = (buf[8] << 8) | buf[9];
-               s->ti_size = len * 512;
-           }
-           DPRINTF("Read (10) (offset %lld len %lld)\n", offset, len);
-            if (s->ti_size > TI_BUFSZ) {
-                DPRINTF("size too large %d\n", s->ti_size);
-            }
-           bdrv_read(s->bd[target], offset, s->ti_buf, len);
-           // XXX error handling
-           s->ti_dir = 1;
-           break;
-       }
-    case 0x2a:
-       {
-           int64_t offset, len;
-
-           if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {
-               offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | 
buf[6]) * 4;
-               len = ((buf[8] << 8) | buf[9]) * 4;
-               s->ti_size = len * 2048;
-           } else {
-               offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | 
buf[6];
-               len = (buf[8] << 8) | buf[9];
-               s->ti_size = len * 512;
-           }
-           DPRINTF("Write (10) (offset %lld len %lld)\n", offset, len);
-            if (s->ti_size > TI_BUFSZ) {
-                DPRINTF("size too large %d\n", s->ti_size);
-            }
-            s->dma_cb = esp_write_dma_cb;
-            s->offset = offset;
-            s->len = len;
-            s->target = target;
-           // XXX error handling
-           s->ti_dir = 0;
-           break;
-       }
-    case 0x43:
-        {
-            int start_track, format, msf, len;
-
-            msf = buf[2] & 2;
-            format = buf[3] & 0xf;
-            start_track = buf[7];
-            bdrv_get_geometry(s->bd[target], &nb_sectors);
-            DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, 
format, msf >> 1);
-            switch(format) {
-            case 0:
-                len = cdrom_read_toc(nb_sectors, buf, msf, start_track);
-                if (len < 0)
-                    goto error_cmd;
-                s->ti_size = len;
-                break;
-            case 1:
-                /* multi session : only a single session defined */
-                memset(buf, 0, 12);
-                buf[1] = 0x0a;
-                buf[2] = 0x01;
-                buf[3] = 0x01;
-                s->ti_size = 12;
-                break;
-            case 2:
-                len = cdrom_read_toc_raw(nb_sectors, buf, msf, start_track);
-                if (len < 0)
-                    goto error_cmd;
-                s->ti_size = len;
-                break;
-            default:
-            error_cmd:
-                DPRINTF("Read TOC error\n");
-                // XXX error handling
-                break;
-            }
-           s->ti_dir = 1;
-            break;
-        }
-    default:
-       DPRINTF("Unknown SCSI command (%2.2x)\n", buf[1]);
-       break;
-    }
-    s->rregs[4] = STAT_IN | STAT_TC | STAT_DI;
+       return 0;
+    }
+    s->current_dev = s->scsi_dev[target];
+    return dmalen;
+}
+
+static void do_cmd(ESPState *s, uint8_t *buf)
+{
+    int32_t datalen;
+    int lun;
+
+    DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
+    lun = buf[0] & 7;
+    datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun);
+    if (datalen == 0) {
+        s->ti_size = 0;
+    } else {
+        s->rregs[4] = STAT_IN | STAT_TC;
+        if (datalen > 0) {
+            s->rregs[4] |= STAT_DI;
+            s->ti_size = datalen;
+        } else {
+            s->rregs[4] |= STAT_DO;
+            s->ti_size = -datalen;
+        }
+    }
     s->rregs[5] = INTR_BS | INTR_FC;
     s->rregs[6] = SEQ_CD;
     s->espdmaregs[0] |= DMA_INTR;
     pic_set_irq(s->irq, 1);
 }
 
-static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len)
-{
-    uint32_t dmaptr, dmalen;
-
-    dmalen = s->wregs[0] | (s->wregs[1] << 8);
-    DPRINTF("Transfer status len %d\n", dmalen);
+static void handle_satn(ESPState *s)
+{
+    uint8_t buf[32];
+    int len;
+
+    len = get_cmd(s, buf);
+    if (len)
+        do_cmd(s, buf);
+}
+
+static void handle_satn_stop(ESPState *s)
+{
+    s->cmdlen = get_cmd(s, s->cmdbuf);
+    if (s->cmdlen) {
+        DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
+        s->do_cmd = 1;
+        s->espdmaregs[1] += s->cmdlen;
+        s->rregs[4] = STAT_IN | STAT_TC | STAT_CD;
+        s->rregs[5] = INTR_BS | INTR_FC;
+        s->rregs[6] = SEQ_CD;
+        s->espdmaregs[0] |= DMA_INTR;
+        pic_set_irq(s->irq, 1);
+    }
+}
+
+static void write_response(ESPState *s)
+{
+    uint32_t dmaptr;
+
+    DPRINTF("Transfer status (sense=%d)\n", s->sense);
+    s->ti_buf[0] = s->sense;
+    s->ti_buf[1] = 0;
     if (s->dma) {
        dmaptr = iommu_translate(s->espdmaregs[1]);
-       DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');
-       cpu_physical_memory_write(dmaptr, buf, len);
+       DPRINTF("DMA Direction: %c\n",
+                s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r');
+       cpu_physical_memory_write(dmaptr, s->ti_buf, 2);
        s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
        s->rregs[5] = INTR_BS | INTR_FC;
        s->rregs[6] = SEQ_CD;
     } else {
-       memcpy(s->ti_buf, buf, len);
-       s->ti_size = dmalen;
+       s->ti_size = 2;
        s->ti_rptr = 0;
        s->ti_wptr = 0;
-       s->rregs[7] = dmalen;
+       s->rregs[7] = 2;
     }
     s->espdmaregs[0] |= DMA_INTR;
     pic_set_irq(s->irq, 1);
 
 }
 
-static const uint8_t okbuf[] = {0, 0};
+static void esp_command_complete(void *opaque, uint32_t tag, int sense)
+{
+    ESPState *s = (ESPState *)opaque;
+
+    DPRINTF("SCSI Command complete\n");
+    if (s->ti_size != 0)
+        DPRINTF("SCSI command completed unexpectedly\n");
+    s->ti_size = 0;
+    if (sense)
+        DPRINTF("Command failed\n");
+    s->sense = sense;
+    s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
+}
 
 static void handle_ti(ESPState *s)
 {
-    uint32_t dmaptr, dmalen;
+    uint32_t dmaptr, dmalen, minlen, len, from, to;
     unsigned int i;
+    int to_device;
+    uint8_t buf[TARGET_PAGE_SIZE];
 
     dmalen = s->wregs[0] | (s->wregs[1] << 8);
-    DPRINTF("Transfer Information len %d\n", dmalen);
+    if (dmalen==0) {
+      dmalen=0x10000;
+    }
+
+    if (s->do_cmd)
+        minlen = (dmalen < 32) ? dmalen : 32;
+    else
+        minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
+    DPRINTF("Transfer Information len %d\n", minlen);
     if (s->dma) {
        dmaptr = iommu_translate(s->espdmaregs[1]);
-       DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 
'w': 'r', dmaptr);
-       for (i = 0; i < s->ti_size; i++) {
+        /* Check if the transfer writes to to reads from the device.  */
+        to_device = (s->espdmaregs[0] & DMA_WRITE_MEM) == 0;
+       DPRINTF("DMA Direction: %c, addr 0x%8.8x %08x\n",
+                to_device ? 'r': 'w', dmaptr, s->ti_size);
+       from = s->espdmaregs[1];
+       to = from + minlen;
+       for (i = 0; i < minlen; i += len, from += len) {
            dmaptr = iommu_translate(s->espdmaregs[1] + i);
-           if (s->ti_dir)
-               cpu_physical_memory_write(dmaptr, &s->ti_buf[i], 1);
-           else
-               cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1);
-       }
-        if (s->dma_cb) {
-            s->dma_cb(s, s->espdmaregs[1], dmalen);
-            s->dma_cb = NULL;
-        }
-       s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
-       s->rregs[5] = INTR_BS;
+           if ((from & TARGET_PAGE_MASK) != (to & TARGET_PAGE_MASK)) {
+               len = TARGET_PAGE_SIZE - (from & ~TARGET_PAGE_MASK);
+            } else {
+              len = to - from;
+            }
+            DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to 
%08x\n", dmaptr, s->espdmaregs[1] + i, len, from, to);
+            s->ti_size -= len;
+            if (s->do_cmd) {
+                DPRINTF("command len %d + %d\n", s->cmdlen, len);
+                cpu_physical_memory_read(dmaptr, &s->cmdbuf[s->cmdlen], len);
+                s->ti_size = 0;
+                s->cmdlen = 0;
+                s->do_cmd = 0;
+                do_cmd(s, s->cmdbuf);
+                return;
+            } else {
+                if (to_device) {
+                    cpu_physical_memory_read(dmaptr, buf, len);
+                    scsi_write_data(s->current_dev, buf, len);
+                } else {
+                    scsi_read_data(s->current_dev, buf, len);
+                    cpu_physical_memory_write(dmaptr, buf, len);
+                }
+            }
+        }
+        if (s->ti_size) {
+           s->rregs[4] = STAT_IN | STAT_TC | (to_device ? STAT_DO : STAT_DI);
+        }
+        s->rregs[5] = INTR_BS;
        s->rregs[6] = 0;
+       s->rregs[7] = 0;
        s->espdmaregs[0] |= DMA_INTR;
-    } else {
-       s->ti_size = dmalen;
-       s->ti_rptr = 0;
-       s->ti_wptr = 0;
-       s->rregs[7] = dmalen;
-    }  
+    } else if (s->do_cmd) {
+        DPRINTF("command len %d\n", s->cmdlen);
+        s->ti_size = 0;
+        s->cmdlen = 0;
+        s->do_cmd = 0;
+        do_cmd(s, s->cmdbuf);
+        return;
+    }
     pic_set_irq(s->irq, 1);
 }
 
@@ -484,9 +289,8 @@ static void esp_reset(void *opaque)
     s->ti_size = 0;
     s->ti_rptr = 0;
     s->ti_wptr = 0;
-    s->ti_dir = 0;
     s->dma = 0;
-    s->dma_cb = NULL;
+    s->do_cmd = 0;
 }
 
 static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
@@ -501,7 +305,12 @@ static uint32_t esp_mem_readb(void *opaq
        // FIFO
        if (s->ti_size > 0) {
            s->ti_size--;
-           s->rregs[saddr] = s->ti_buf[s->ti_rptr++];
+            if ((s->rregs[4] & 6) == 0) {
+                /* Data in/out.  */
+                scsi_read_data(s->current_dev, &s->rregs[2], 0);
+            } else {
+                s->rregs[2] = s->ti_buf[s->ti_rptr++];
+            }
            pic_set_irq(s->irq, 1);
        }
        if (s->ti_size == 0) {
@@ -536,8 +345,17 @@ static void esp_mem_writeb(void *opaque,
         break;
     case 2:
        // FIFO
-       s->ti_size++;
-       s->ti_buf[s->ti_wptr++] = val & 0xff;
+        if (s->do_cmd) {
+            s->cmdbuf[s->cmdlen++] = val & 0xff;
+        } else if ((s->rregs[4] & 6) == 0) {
+            uint8_t buf;
+            buf = val & 0xff;
+            s->ti_size--;
+            scsi_write_data(s->current_dev, &buf, 0);
+        } else {
+            s->ti_size++;
+            s->ti_buf[s->ti_wptr++] = val & 0xff;
+        }
        break;
     case 3:
         s->rregs[saddr] = val;
@@ -574,11 +392,11 @@ static void esp_mem_writeb(void *opaque,
            break;
        case 0x11:
            DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
-           dma_write(s, okbuf, 2);
+           write_response(s);
            break;
        case 0x12:
            DPRINTF("Message Accepted (%2.2x)\n", val);
-           dma_write(s, okbuf, 2);
+           write_response(s);
            s->rregs[5] = INTR_DC;
            s->rregs[6] = 0;
            break;
@@ -586,11 +404,12 @@ static void esp_mem_writeb(void *opaque,
            DPRINTF("Set ATN (%2.2x)\n", val);
            break;
        case 0x42:
+           DPRINTF("Set ATN (%2.2x)\n", val);
            handle_satn(s);
            break;
        case 0x43:
            DPRINTF("Set ATN & stop (%2.2x)\n", val);
-           handle_satn(s);
+           handle_satn_stop(s);
            break;
        default:
            DPRINTF("Unhandled ESP command (%2.2x)\n", val);
@@ -660,7 +479,7 @@ static void espdma_mem_writel(void *opaq
         val |= DMA_VER;
        break;
     case 1:
-        s->espdmaregs[0] = DMA_LOADED;
+        s->espdmaregs[0] |= DMA_LOADED;
         break;
     default:
        break;
@@ -693,7 +512,6 @@ static void esp_save(QEMUFile *f, void *
     qemu_put_be32s(f, &s->ti_size);
     qemu_put_be32s(f, &s->ti_rptr);
     qemu_put_be32s(f, &s->ti_wptr);
-    qemu_put_be32s(f, &s->ti_dir);
     qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
     qemu_put_be32s(f, &s->dma);
 }
@@ -714,7 +532,6 @@ static int esp_load(QEMUFile *f, void *o
     qemu_get_be32s(f, &s->ti_size);
     qemu_get_be32s(f, &s->ti_rptr);
     qemu_get_be32s(f, &s->ti_wptr);
-    qemu_get_be32s(f, &s->ti_dir);
     qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
     qemu_get_be32s(f, &s->dma);
 
@@ -725,6 +542,7 @@ void esp_init(BlockDriverState **bd, int
 {
     ESPState *s;
     int esp_io_memory, espdma_io_memory;
+    int i;
 
     s = qemu_mallocz(sizeof(ESPState));
     if (!s)
@@ -743,5 +561,11 @@ void esp_init(BlockDriverState **bd, int
 
     register_savevm("esp", espaddr, 1, esp_save, esp_load, s);
     qemu_register_reset(esp_reset, s);
-}
-
+    for (i = 0; i < MAX_DISKS; i++) {
+        if (bs_table[i]) {
+            s->scsi_dev[i] =
+                scsi_disk_init(bs_table[i], esp_command_complete, s);
+        }
+    }
+}
+
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/i8259.c
--- a/tools/ioemu/hw/i8259.c    Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/i8259.c    Mon Aug 07 18:25:30 2006 +0100
@@ -531,7 +531,7 @@ void irq_info(void)
     for (i = 0; i < 16; i++) {
         count = irq_count[i];
         if (count > 0)
-            term_printf("%2d: %lld\n", i, count);
+            term_printf("%2d: %" PRId64 "\n", i, count);
     }
 #endif
 }
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/ide.c
--- a/tools/ioemu/hw/ide.c      Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/ide.c      Mon Aug 07 18:25:30 2006 +0100
@@ -1133,127 +1133,6 @@ static void ide_atapi_cmd_read(IDEState 
     }
 }
 
-/* same toc as bochs. Return -1 if error or the toc length */
-/* XXX: check this */
-static int cdrom_read_toc(IDEState *s, uint8_t *buf, int msf, int start_track)
-{
-    uint8_t *q;
-    int nb_sectors, len;
-    
-    if (start_track > 1 && start_track != 0xaa)
-        return -1;
-    q = buf + 2;
-    *q++ = 1; /* first session */
-    *q++ = 1; /* last session */
-    if (start_track <= 1) {
-        *q++ = 0; /* reserved */
-        *q++ = 0x14; /* ADR, control */
-        *q++ = 1;    /* track number */
-        *q++ = 0; /* reserved */
-        if (msf) {
-            *q++ = 0; /* reserved */
-            lba_to_msf(q, 0);
-            q += 3;
-        } else {
-            /* sector 0 */
-            cpu_to_ube32(q, 0);
-            q += 4;
-        }
-    }
-    /* lead out track */
-    *q++ = 0; /* reserved */
-    *q++ = 0x16; /* ADR, control */
-    *q++ = 0xaa; /* track number */
-    *q++ = 0; /* reserved */
-    nb_sectors = s->nb_sectors >> 2;
-    if (msf) {
-        *q++ = 0; /* reserved */
-        lba_to_msf(q, nb_sectors);
-        q += 3;
-    } else {
-        cpu_to_ube32(q, nb_sectors);
-        q += 4;
-    }
-    len = q - buf;
-    cpu_to_ube16(buf, len - 2);
-    return len;
-}
-
-/* mostly same info as PearPc */
-static int cdrom_read_toc_raw(IDEState *s, uint8_t *buf, int msf, 
-                              int session_num)
-{
-    uint8_t *q;
-    int nb_sectors, len;
-    
-    q = buf + 2;
-    *q++ = 1; /* first session */
-    *q++ = 1; /* last session */
-
-    *q++ = 1; /* session number */
-    *q++ = 0x14; /* data track */
-    *q++ = 0; /* track number */
-    *q++ = 0xa0; /* lead-in */
-    *q++ = 0; /* min */
-    *q++ = 0; /* sec */
-    *q++ = 0; /* frame */
-    *q++ = 0;
-    *q++ = 1; /* first track */
-    *q++ = 0x00; /* disk type */
-    *q++ = 0x00;
-    
-    *q++ = 1; /* session number */
-    *q++ = 0x14; /* data track */
-    *q++ = 0; /* track number */
-    *q++ = 0xa1;
-    *q++ = 0; /* min */
-    *q++ = 0; /* sec */
-    *q++ = 0; /* frame */
-    *q++ = 0;
-    *q++ = 1; /* last track */
-    *q++ = 0x00;
-    *q++ = 0x00;
-    
-    *q++ = 1; /* session number */
-    *q++ = 0x14; /* data track */
-    *q++ = 0; /* track number */
-    *q++ = 0xa2; /* lead-out */
-    *q++ = 0; /* min */
-    *q++ = 0; /* sec */
-    *q++ = 0; /* frame */
-    nb_sectors = s->nb_sectors >> 2;
-    if (msf) {
-        *q++ = 0; /* reserved */
-        lba_to_msf(q, nb_sectors);
-        q += 3;
-    } else {
-        cpu_to_ube32(q, nb_sectors);
-        q += 4;
-    }
-
-    *q++ = 1; /* session number */
-    *q++ = 0x14; /* ADR, control */
-    *q++ = 0;    /* track number */
-    *q++ = 1;    /* point */
-    *q++ = 0; /* min */
-    *q++ = 0; /* sec */
-    *q++ = 0; /* frame */
-    if (msf) {
-        *q++ = 0; 
-        lba_to_msf(q, 0);
-        q += 3;
-    } else {
-        *q++ = 0; 
-        *q++ = 0; 
-        *q++ = 0; 
-        *q++ = 0; 
-    }
-
-    len = q - buf;
-    cpu_to_ube16(buf, len - 2);
-    return len;
-}
-
 static void ide_atapi_cmd(IDEState *s)
 {
     const uint8_t *packet;
@@ -1501,7 +1380,7 @@ static void ide_atapi_cmd(IDEState *s)
             start_track = packet[6];
             switch(format) {
             case 0:
-                len = cdrom_read_toc(s, buf, msf, start_track);
+                len = cdrom_read_toc(s->nb_sectors >> 2, buf, msf, 
start_track);
                 if (len < 0)
                     goto error_cmd;
                 ide_atapi_cmd_reply(s, len, max_len);
@@ -1515,7 +1394,7 @@ static void ide_atapi_cmd(IDEState *s)
                 ide_atapi_cmd_reply(s, 12, max_len);
                 break;
             case 2:
-                len = cdrom_read_toc_raw(s, buf, msf, start_track);
+                len = cdrom_read_toc_raw(s->nb_sectors >> 2, buf, msf, 
start_track);
                 if (len < 0)
                     goto error_cmd;
                 ide_atapi_cmd_reply(s, len, max_len);
@@ -1829,6 +1708,11 @@ static void ide_ioport_write(void *opaqu
             break;
         case WIN_FLUSH_CACHE:
         case WIN_FLUSH_CACHE_EXT:
+            if (s->bs)
+                bdrv_flush(s->bs);
+           s->status = READY_STAT;
+            ide_set_irq(s);
+            break;
        case WIN_STANDBYNOW1:
         case WIN_IDLEIMMEDIATE:
            s->status = READY_STAT;
@@ -2563,7 +2447,7 @@ void pci_cmd646_ide_init(PCIBus *bus, Bl
 
 /* 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)
+void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn)
 {
     PCIIDEState *d;
     uint8_t *pci_conf;
@@ -2571,7 +2455,7 @@ void pci_piix3_ide_init(PCIBus *bus, Blo
     /* register a function 1 of PIIX3 */
     d = (PCIIDEState *)pci_register_device(bus, "PIIX3 IDE", 
                                            sizeof(PCIIDEState),
-                                           ((PCIDevice *)piix3_state)->devfn + 
1, 
+                                           devfn,
                                            NULL, NULL);
     d->type = IDE_TYPE_PIIX3;
 
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/m48t59.c
--- a/tools/ioemu/hw/m48t59.c   Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/m48t59.c   Mon Aug 07 18:25:30 2006 +0100
@@ -332,7 +332,10 @@ void m48t59_write (m48t59_t *NVRAM, uint
        tmp = fromBCD(val);
        if (tmp >= 0 && tmp <= 99) {
            get_time(NVRAM, &tm);
-           tm.tm_year = fromBCD(val);
+            if (NVRAM->type == 8)
+                tm.tm_year = fromBCD(val) + 68; // Base year is 1968
+            else
+                tm.tm_year = fromBCD(val);
            set_time(NVRAM, &tm);
        }
         break;
@@ -421,7 +424,10 @@ uint32_t m48t59_read (m48t59_t *NVRAM, u
     case 0x1FFF:
         /* year */
         get_time(NVRAM, &tm);
-        retval = toBCD(tm.tm_year);
+        if (NVRAM->type == 8) 
+            retval = toBCD(tm.tm_year - 68); // Base year is 1968
+        else
+            retval = toBCD(tm.tm_year);
         break;
     default:
         /* Check lock registers state */
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/mips_r4k.c
--- a/tools/ioemu/hw/mips_r4k.c Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/mips_r4k.c Mon Aug 07 18:25:30 2006 +0100
@@ -60,7 +60,7 @@ static void cpu_mips_update_count (CPUSt
        next++;
 #if 0
     if (logfile) {
-        fprintf(logfile, "%s: 0x%08llx %08x %08x => 0x%08llx\n",
+        fprintf(logfile, "%s: 0x%08" PRIx64 " %08x %08x => 0x%08" PRIx64 "\n",
                 __func__, now, count, compare, next - now);
     }
 #endif
@@ -214,14 +214,10 @@ void mips_r4k_init (int ram_size, int vg
        run. */
     bios_offset = ram_size + vga_ram_size;
     snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
-    printf("%s: load BIOS '%s' size %d\n", __func__, buf, BIOS_SIZE);
     ret = load_image(buf, phys_ram_base + bios_offset);
     if (ret == BIOS_SIZE) {
        cpu_register_physical_memory((uint32_t)(0x1fc00000),
                                     BIOS_SIZE, bios_offset | IO_MEM_ROM);
-       env->PC = 0xBFC00000;
-       if (!kernel_filename)
-           return;
     } else {
        /* not fatal */
         fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/ne2000.c
--- a/tools/ioemu/hw/ne2000.c   Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/ne2000.c   Mon Aug 07 18:25:30 2006 +0100
@@ -206,7 +206,7 @@ static int ne2000_buffer_full(NE2000Stat
 
     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);
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/pc.c
--- a/tools/ioemu/hw/pc.c       Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/pc.c       Mon Aug 07 18:25:30 2006 +0100
@@ -44,7 +44,6 @@ static PITState *pit;
 #ifndef CONFIG_DM
 static IOAPICState *ioapic;
 #endif /* !CONFIG_DM */
-static USBPort *usb_root_ports[2];
 
 static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
 {
@@ -63,10 +62,19 @@ static void ioportF0_write(void *opaque,
 }
 
 /* TSC handling */
-
 uint64_t cpu_get_tsc(CPUX86State *env)
 {
-    return qemu_get_clock(vm_clock);
+    /* Note: when using kqemu, it is more logical to return the host TSC
+       because kqemu does not trap the RDTSC instruction for
+       performance reasons */
+#if USE_KQEMU
+    if (env->kqemu_enabled) {
+        return cpu_get_real_ticks();
+    } else 
+#endif
+    {
+        return cpu_get_ticks();
+    }
 }
 
 #ifndef CONFIG_DM
@@ -201,6 +209,8 @@ static void cmos_init(uint64_t ram_size,
     case 'a':
     case 'b':
         rtc_set_memory(s, 0x3d, 0x01); /* floppy boot */
+        if (!fd_bootchk)
+            rtc_set_memory(s, 0x38, 0x01); /* disable signature check */
         break;
     default:
     case 'c':
@@ -272,10 +282,6 @@ static void cmos_init(uint64_t ram_size,
         }
     }
     rtc_set_memory(s, 0x39, val);
-
-    /* Disable check of 0x55AA signature on the last two bytes of
-       first sector of disk. XXX: make it the default ? */
-    //    rtc_set_memory(s, 0x38, 1);
 }
 
 void ioport_set_a20(int enable)
@@ -567,7 +573,7 @@ static int parallel_irq[MAX_PARALLEL_POR
 static int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
 
 /* PIIX4 acpi pci configuration space, func 3 */
-extern void pci_piix4_acpi_init(PCIBus *bus);
+extern void pci_piix4_acpi_init(PCIBus *bus, int devfn);
 
 #ifdef HAS_AUDIO
 static void audio_init (PCIBus *pci_bus)
@@ -630,6 +636,7 @@ static void pc_init1(uint64_t ram_size, 
     int bios_size, isa_bios_size;
 #endif /* !NOBIOS */
     PCIBus *pci_bus;
+    int piix3_devfn = -1;
     CPUState *env;
     NICInfo *nd;
 
@@ -774,7 +781,7 @@ static void pc_init1(uint64_t ram_size, 
 
     if (pci_enabled) {
         pci_bus = i440fx_init();
-        piix3_init(pci_bus);
+        piix3_devfn = piix3_init(pci_bus);
     } else {
         pci_bus = NULL;
     }
@@ -852,7 +859,7 @@ static void pc_init1(uint64_t ram_size, 
     }
 
     if (pci_enabled) {
-        pci_piix3_ide_init(pci_bus, bs_table);
+        pci_piix3_ide_init(pci_bus, bs_table, piix3_devfn + 1);
     } else {
         for(i = 0; i < 2; i++) {
             isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
@@ -872,17 +879,39 @@ static void pc_init1(uint64_t ram_size, 
 
     /* using PIIX4 acpi model */
     if (pci_enabled && acpi_enabled)
-        pci_piix4_acpi_init(pci_bus);
+        pci_piix4_acpi_init(pci_bus, piix3_devfn + 3);
 
     if (pci_enabled && usb_enabled) {
-        usb_uhci_init(pci_bus, usb_root_ports);
-        usb_attach(usb_root_ports[0], vm_usb_hub);
-    }
-
+        usb_uhci_init(pci_bus, piix3_devfn + 2);
+    }
+
+    if (pci_enabled && acpi_enabled && 0) {
+        piix4_pm_init(pci_bus, piix3_devfn + 3);
+    }
+
+#if 0
+    /* ??? Need to figure out some way for the user to
+       specify SCSI devices.  */
+    if (pci_enabled) {
+        void *scsi;
+        BlockDriverState *bdrv;
+
+        scsi = lsi_scsi_init(pci_bus, -1);
+        bdrv = bdrv_new("scsidisk");
+        bdrv_open(bdrv, "scsi_disk.img", 0);
+        lsi_scsi_attach(scsi, bdrv, -1);
+        bdrv = bdrv_new("scsicd");
+        bdrv_open(bdrv, "scsi_cd.iso", 0);
+        bdrv_set_type_hint(bdrv, BDRV_TYPE_CDROM);
+        lsi_scsi_attach(scsi, bdrv, -1);
+    }
+#endif
     /* must be done after all PCI devices are instanciated */
     /* XXX: should be done in the Bochs BIOS */
     if (pci_enabled) {
         pci_bios_init();
+        if (acpi_enabled)
+            acpi_bios_init();
     }
 }
 
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/pci.c
--- a/tools/ioemu/hw/pci.c      Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/pci.c      Mon Aug 07 18:25:30 2006 +0100
@@ -25,25 +25,10 @@
 
 //#define DEBUG_PCI
 
-#define PCI_VENDOR_ID          0x00    /* 16 bits */
-#define PCI_DEVICE_ID          0x02    /* 16 bits */
-#define PCI_COMMAND            0x04    /* 16 bits */
-#define  PCI_COMMAND_IO                0x1     /* Enable response in I/O space 
*/
-#define  PCI_COMMAND_MEMORY    0x2     /* Enable response in Memory space */
-#define PCI_CLASS_DEVICE        0x0a    /* Device class */
-#define PCI_INTERRUPT_LINE     0x3c    /* 8 bits */
-#define PCI_INTERRUPT_PIN      0x3d    /* 8 bits */
-#define PCI_MIN_GNT            0x3e    /* 8 bits */
-#define PCI_MAX_LAT            0x3f    /* 8 bits */
-
-/* just used for simpler irq handling. */
-#define PCI_DEVICES_MAX 64
-#define PCI_IRQ_WORDS   ((PCI_DEVICES_MAX + 31) / 32)
-
 struct PCIBus {
     int bus_num;
     int devfn_min;
-    void (*set_irq)(PCIDevice *pci_dev, int irq_num, int level);
+    pci_set_irq_fn set_irq;
     uint32_t config_reg; /* XXX: suppress */
     /* low level pic */
     SetIRQFunc *low_set_irq;
@@ -53,15 +38,22 @@ struct PCIBus {
 
 target_phys_addr_t pci_mem_base;
 static int pci_irq_index;
-static uint32_t pci_irq_levels[4][PCI_IRQ_WORDS];
 static PCIBus *first_bus;
 
-static PCIBus *pci_register_bus(void)
+PCIBus *pci_register_bus(pci_set_irq_fn set_irq, void *pic, int devfn_min)
 {
     PCIBus *bus;
     bus = qemu_mallocz(sizeof(PCIBus));
+    bus->set_irq = set_irq;
+    bus->irq_opaque = pic;
+    bus->devfn_min = devfn_min;
     first_bus = bus;
     return bus;
+}
+
+int pci_bus_num(PCIBus *s)
+{
+    return s->bus_num;
 }
 
 void generic_pci_save(QEMUFile* f, void *opaque)
@@ -141,16 +133,9 @@ void pci_register_io_region(PCIDevice *p
     *(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type);
 }
 
-static void pci_addr_writel(void* opaque, uint32_t addr, uint32_t val)
-{
-    PCIBus *s = opaque;
-    s->config_reg = val;
-}
-
-static uint32_t pci_addr_readl(void* opaque, uint32_t addr)
-{
-    PCIBus *s = opaque;
-    return s->config_reg;
+target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
+{
+    return addr + pci_mem_base;
 }
 
 static void pci_update_mappings(PCIDevice *d)
@@ -218,7 +203,7 @@ static void pci_update_mappings(PCIDevic
                             isa_unassign_ioport(r->addr, r->size);
                         }
                     } else {
-                        cpu_register_physical_memory(r->addr + pci_mem_base, 
+                        cpu_register_physical_memory(pci_to_cpu_addr(r->addr),
                                                      r->size, 
                                                      IO_MEM_UNASSIGNED);
                     }
@@ -346,8 +331,7 @@ void pci_default_write_config(PCIDevice 
     }
 }
 
-static void pci_data_write(void *opaque, uint32_t addr, 
-                           uint32_t val, int len)
+void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
 {
     PCIBus *s = opaque;
     PCIDevice *pci_dev;
@@ -355,18 +339,15 @@ static void pci_data_write(void *opaque,
     
 #if defined(DEBUG_PCI) && 0
     printf("pci_data_write: addr=%08x val=%08x len=%d\n",
-           s->config_reg, val, len);
+           addr, val, len);
 #endif
-    if (!(s->config_reg & (1 << 31))) {
-        return;
-    }
-    bus_num = (s->config_reg >> 16) & 0xff;
+    bus_num = (addr >> 16) & 0xff;
     if (bus_num != 0)
         return;
-    pci_dev = s->devices[(s->config_reg >> 8) & 0xff];
+    pci_dev = s->devices[(addr >> 8) & 0xff];
     if (!pci_dev)
         return;
-    config_addr = (s->config_reg & 0xfc) | (addr & 3);
+    config_addr = addr & 0xff;
 #if defined(DEBUG_PCI)
     printf("pci_config_write: %s: addr=%02x val=%08x len=%d\n",
            pci_dev->name, config_addr, val, len);
@@ -374,20 +355,17 @@ static void pci_data_write(void *opaque,
     pci_dev->config_write(pci_dev, config_addr, val, len);
 }
 
-static uint32_t pci_data_read(void *opaque, uint32_t addr, 
-                              int len)
+uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
 {
     PCIBus *s = opaque;
     PCIDevice *pci_dev;
     int config_addr, bus_num;
     uint32_t val;
 
-    if (!(s->config_reg & (1 << 31)))
-        goto fail;
-    bus_num = (s->config_reg >> 16) & 0xff;
+    bus_num = (addr >> 16) & 0xff;
     if (bus_num != 0)
         goto fail;
-    pci_dev = s->devices[(s->config_reg >> 8) & 0xff];
+    pci_dev = s->devices[(addr >> 8) & 0xff];
     if (!pci_dev) {
     fail:
         switch(len) {
@@ -404,7 +382,7 @@ static uint32_t pci_data_read(void *opaq
         }
         goto the_end;
     }
-    config_addr = (s->config_reg & 0xfc) | (addr & 3);
+    config_addr = addr & 0xff;
     val = pci_dev->config_read(pci_dev, config_addr, len);
 #if defined(DEBUG_PCI)
     printf("pci_config_read: %s: addr=%02x val=%08x len=%d\n",
@@ -413,1133 +391,11 @@ static uint32_t pci_data_read(void *opaq
  the_end:
 #if defined(DEBUG_PCI) && 0
     printf("pci_data_read: addr=%08x val=%08x len=%d\n",
-           s->config_reg, val, len);
+           addr, val, len);
 #endif
     return val;
 }
 
-static void pci_data_writeb(void* opaque, uint32_t addr, uint32_t val)
-{
-    pci_data_write(opaque, addr, val, 1);
-}
-
-static void pci_data_writew(void* opaque, uint32_t addr, uint32_t val)
-{
-    pci_data_write(opaque, addr, val, 2);
-}
-
-static void pci_data_writel(void* opaque, uint32_t addr, uint32_t val)
-{
-    pci_data_write(opaque, addr, val, 4);
-}
-
-static uint32_t pci_data_readb(void* opaque, uint32_t addr)
-{
-    return pci_data_read(opaque, addr, 1);
-}
-
-static uint32_t pci_data_readw(void* opaque, uint32_t addr)
-{
-    return pci_data_read(opaque, addr, 2);
-}
-
-static uint32_t pci_data_readl(void* opaque, uint32_t addr)
-{
-    return pci_data_read(opaque, addr, 4);
-}
-
-/* i440FX PCI bridge */
-
-static void piix3_set_irq(PCIDevice *pci_dev, int irq_num, int level);
-
-PCIBus *i440fx_init(void)
-{
-    PCIBus *s;
-    PCIDevice *d;
-
-    s = pci_register_bus();
-    s->set_irq = piix3_set_irq;
-
-    register_ioport_write(0xcf8, 4, 4, pci_addr_writel, s);
-    register_ioport_read(0xcf8, 4, 4, pci_addr_readl, s);
-
-    register_ioport_write(0xcfc, 4, 1, pci_data_writeb, s);
-    register_ioport_write(0xcfc, 4, 2, pci_data_writew, s);
-    register_ioport_write(0xcfc, 4, 4, pci_data_writel, s);
-    register_ioport_read(0xcfc, 4, 1, pci_data_readb, s);
-    register_ioport_read(0xcfc, 4, 2, pci_data_readw, s);
-    register_ioport_read(0xcfc, 4, 4, pci_data_readl, s);
-
-    d = pci_register_device(s, "i440FX", sizeof(PCIDevice), 0, 
-                            NULL, NULL);
-
-    d->config[0x00] = 0x86; // vendor_id
-    d->config[0x01] = 0x80;
-    d->config[0x02] = 0x37; // device_id
-    d->config[0x03] = 0x12;
-    d->config[0x08] = 0x02; // revision
-    d->config[0x0a] = 0x00; // class_sub = host2pci
-    d->config[0x0b] = 0x06; // class_base = PCI_bridge
-    d->config[0x0e] = 0x00; // header_type
-    return s;
-}
-
-/* PIIX3 PCI to ISA bridge */
-
-typedef struct PIIX3State {
-    PCIDevice dev;
-} PIIX3State;
-
-PIIX3State *piix3_state;
-
-/* return the global irq number corresponding to a given device irq
-   pin. We could also use the bus number to have a more precise
-   mapping. */
-static inline int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
-{
-    int slot_addend;
-    slot_addend = (pci_dev->devfn >> 3) - 1;
-    return (irq_num + slot_addend) & 3;
-}
-
-static inline int get_pci_irq_level(int irq_num)
-{
-    int pic_level;
-#if (PCI_IRQ_WORDS == 2)
-    pic_level = ((pci_irq_levels[irq_num][0] | 
-                  pci_irq_levels[irq_num][1]) != 0);
-#else
-    {
-        int i;
-        pic_level = 0;
-        for(i = 0; i < PCI_IRQ_WORDS; i++) {
-            if (pci_irq_levels[irq_num][i]) {
-                pic_level = 1;
-                break;
-            }
-        }
-    }
-#endif
-    return pic_level;
-}
-
-static void piix3_set_irq(PCIDevice *pci_dev, int irq_num, int level)
-{
-    int irq_index, shift, pic_irq, pic_level;
-    uint32_t *p;
-
-    irq_num = pci_slot_get_pirq(pci_dev, irq_num);
-    irq_index = pci_dev->irq_index;
-    p = &pci_irq_levels[irq_num][irq_index >> 5];
-    shift = (irq_index & 0x1f);
-    *p = (*p & ~(1 << shift)) | (level << shift);
-
-    /* now we change the pic irq level according to the piix irq mappings */
-    /* XXX: optimize */
-    pic_irq = piix3_state->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;
-        if (pic_irq == piix3_state->dev.config[0x60])
-            pic_level |= get_pci_irq_level(0);
-        if (pic_irq == piix3_state->dev.config[0x61])
-            pic_level |= get_pci_irq_level(1);
-        if (pic_irq == piix3_state->dev.config[0x62])
-            pic_level |= get_pci_irq_level(2);
-        if (pic_irq == piix3_state->dev.config[0x63])
-            pic_level |= get_pci_irq_level(3);
-        pic_set_irq(pic_irq, pic_level);
-    }
-}
-
-static void piix3_reset(PIIX3State *d)
-{
-    uint8_t *pci_conf = d->dev.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] = 0x80;
-    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[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;
-}
-
-void piix3_init(PCIBus *bus)
-{
-    PIIX3State *d;
-    uint8_t *pci_conf;
-
-    d = (PIIX3State *)pci_register_device(bus, "PIIX3", sizeof(PIIX3State),
-                                          -1, NULL, NULL);
-    register_savevm("PIIX3", 0, 1, generic_pci_save, generic_pci_load, d);
-
-    piix3_state = d;
-    pci_conf = d->dev.config;
-
-    pci_conf[0x00] = 0x86; // Intel
-    pci_conf[0x01] = 0x80;
-    pci_conf[0x02] = 0x00; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
-    pci_conf[0x03] = 0x70;
-    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);
-}
-
-/* PREP pci init */
-
-static inline void set_config(PCIBus *s, target_phys_addr_t addr)
-{
-    int devfn, i;
-
-    for(i = 0; i < 11; i++) {
-        if ((addr & (1 << (11 + i))) != 0)
-            break;
-    }
-    devfn = ((addr >> 8) & 7) | (i << 3);
-    s->config_reg = 0x80000000 | (addr & 0xfc) | (devfn << 8);
-}
-
-static void PPC_PCIIO_writeb (void *opaque, target_phys_addr_t addr, uint32_t 
val)
-{
-    PCIBus *s = opaque;
-    set_config(s, addr);
-    pci_data_write(s, addr, val, 1);
-}
-
-static void PPC_PCIIO_writew (void *opaque, target_phys_addr_t addr, uint32_t 
val)
-{
-    PCIBus *s = opaque;
-    set_config(s, addr);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap16(val);
-#endif
-    pci_data_write(s, addr, val, 2);
-}
-
-static void PPC_PCIIO_writel (void *opaque, target_phys_addr_t addr, uint32_t 
val)
-{
-    PCIBus *s = opaque;
-    set_config(s, addr);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    pci_data_write(s, addr, val, 4);
-}
-
-static uint32_t PPC_PCIIO_readb (void *opaque, target_phys_addr_t addr)
-{
-    PCIBus *s = opaque;
-    uint32_t val;
-    set_config(s, addr);
-    val = pci_data_read(s, addr, 1);
-    return val;
-}
-
-static uint32_t PPC_PCIIO_readw (void *opaque, target_phys_addr_t addr)
-{
-    PCIBus *s = opaque;
-    uint32_t val;
-    set_config(s, addr);
-    val = pci_data_read(s, addr, 2);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap16(val);
-#endif
-    return val;
-}
-
-static uint32_t PPC_PCIIO_readl (void *opaque, target_phys_addr_t addr)
-{
-    PCIBus *s = opaque;
-    uint32_t val;
-    set_config(s, addr);
-    val = pci_data_read(s, addr, 4);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    return val;
-}
-
-static CPUWriteMemoryFunc *PPC_PCIIO_write[] = {
-    &PPC_PCIIO_writeb,
-    &PPC_PCIIO_writew,
-    &PPC_PCIIO_writel,
-};
-
-static CPUReadMemoryFunc *PPC_PCIIO_read[] = {
-    &PPC_PCIIO_readb,
-    &PPC_PCIIO_readw,
-    &PPC_PCIIO_readl,
-};
-
-static void prep_set_irq(PCIDevice *d, int irq_num, int level)
-{
-    /* XXX: we do not simulate the hardware - we rely on the BIOS to
-       set correctly for irq line field */
-    pic_set_irq(d->config[PCI_INTERRUPT_LINE], level);
-}
-
-PCIBus *pci_prep_init(void)
-{
-    PCIBus *s;
-    PCIDevice *d;
-    int PPC_io_memory;
-
-    s = pci_register_bus();
-    s->set_irq = prep_set_irq;
-
-    register_ioport_write(0xcf8, 4, 4, pci_addr_writel, s);
-    register_ioport_read(0xcf8, 4, 4, pci_addr_readl, s);
-
-    register_ioport_write(0xcfc, 4, 1, pci_data_writeb, s);
-    register_ioport_write(0xcfc, 4, 2, pci_data_writew, s);
-    register_ioport_write(0xcfc, 4, 4, pci_data_writel, s);
-    register_ioport_read(0xcfc, 4, 1, pci_data_readb, s);
-    register_ioport_read(0xcfc, 4, 2, pci_data_readw, s);
-    register_ioport_read(0xcfc, 4, 4, pci_data_readl, s);
-
-    PPC_io_memory = cpu_register_io_memory(0, PPC_PCIIO_read, 
-                                           PPC_PCIIO_write, s);
-    cpu_register_physical_memory(0x80800000, 0x00400000, PPC_io_memory);
-
-    /* PCI host bridge */ 
-    d = pci_register_device(s, "PREP Host Bridge - Motorola Raven", 
-                            sizeof(PCIDevice), 0, NULL, NULL);
-    d->config[0x00] = 0x57; // vendor_id : Motorola
-    d->config[0x01] = 0x10;
-    d->config[0x02] = 0x01; // device_id : Raven
-    d->config[0x03] = 0x48;
-    d->config[0x08] = 0x00; // revision
-    d->config[0x0A] = 0x00; // class_sub = pci host
-    d->config[0x0B] = 0x06; // class_base = PCI_bridge
-    d->config[0x0C] = 0x08; // cache_line_size
-    d->config[0x0D] = 0x10; // latency_timer
-    d->config[0x0E] = 0x00; // header_type
-    d->config[0x34] = 0x00; // capabilities_pointer
-
-    return s;
-}
-
-
-/* Grackle PCI host */
-static void pci_grackle_config_writel (void *opaque, target_phys_addr_t addr,
-                                       uint32_t val)
-{
-    PCIBus *s = opaque;
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    s->config_reg = val;
-}
-
-static uint32_t pci_grackle_config_readl (void *opaque, target_phys_addr_t 
addr)
-{
-    PCIBus *s = opaque;
-    uint32_t val;
-
-    val = s->config_reg;
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    return val;
-}
-
-static CPUWriteMemoryFunc *pci_grackle_config_write[] = {
-    &pci_grackle_config_writel,
-    &pci_grackle_config_writel,
-    &pci_grackle_config_writel,
-};
-
-static CPUReadMemoryFunc *pci_grackle_config_read[] = {
-    &pci_grackle_config_readl,
-    &pci_grackle_config_readl,
-    &pci_grackle_config_readl,
-};
-
-static void pci_grackle_writeb (void *opaque, target_phys_addr_t addr,
-                                uint32_t val)
-{
-    PCIBus *s = opaque;
-    pci_data_write(s, addr, val, 1);
-}
-
-static void pci_grackle_writew (void *opaque, target_phys_addr_t addr,
-                                uint32_t val)
-{
-    PCIBus *s = opaque;
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap16(val);
-#endif
-    pci_data_write(s, addr, val, 2);
-}
-
-static void pci_grackle_writel (void *opaque, target_phys_addr_t addr,
-                                uint32_t val)
-{
-    PCIBus *s = opaque;
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    pci_data_write(s, addr, val, 4);
-}
-
-static uint32_t pci_grackle_readb (void *opaque, target_phys_addr_t addr)
-{
-    PCIBus *s = opaque;
-    uint32_t val;
-    val = pci_data_read(s, addr, 1);
-    return val;
-}
-
-static uint32_t pci_grackle_readw (void *opaque, target_phys_addr_t addr)
-{
-    PCIBus *s = opaque;
-    uint32_t val;
-    val = pci_data_read(s, addr, 2);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap16(val);
-#endif
-    return val;
-}
-
-static uint32_t pci_grackle_readl (void *opaque, target_phys_addr_t addr)
-{
-    PCIBus *s = opaque;
-    uint32_t val;
-
-    val = pci_data_read(s, addr, 4);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    return val;
-}
-
-static CPUWriteMemoryFunc *pci_grackle_write[] = {
-    &pci_grackle_writeb,
-    &pci_grackle_writew,
-    &pci_grackle_writel,
-};
-
-static CPUReadMemoryFunc *pci_grackle_read[] = {
-    &pci_grackle_readb,
-    &pci_grackle_readw,
-    &pci_grackle_readl,
-};
-
-void pci_set_pic(PCIBus *bus, SetIRQFunc *set_irq, void *irq_opaque)
-{
-    bus->low_set_irq = set_irq;
-    bus->irq_opaque = irq_opaque;
-}
-
-/* XXX: we do not simulate the hardware - we rely on the BIOS to
-   set correctly for irq line field */
-static void pci_set_irq_simple(PCIDevice *d, int irq_num, int level)
-{
-    PCIBus *s = d->bus;
-    s->low_set_irq(s->irq_opaque, d->config[PCI_INTERRUPT_LINE], level);
-}
-
-PCIBus *pci_grackle_init(uint32_t base)
-{
-    PCIBus *s;
-    PCIDevice *d;
-    int pci_mem_config, pci_mem_data;
-
-    s = pci_register_bus();
-    s->set_irq = pci_set_irq_simple;
-
-    pci_mem_config = cpu_register_io_memory(0, pci_grackle_config_read, 
-                                            pci_grackle_config_write, s);
-    pci_mem_data = cpu_register_io_memory(0, pci_grackle_read,
-                                          pci_grackle_write, s);
-    cpu_register_physical_memory(base, 0x1000, pci_mem_config);
-    cpu_register_physical_memory(base + 0x00200000, 0x1000, pci_mem_data);
-    d = pci_register_device(s, "Grackle host bridge", sizeof(PCIDevice), 
-                            0, NULL, NULL);
-    d->config[0x00] = 0x57; // vendor_id
-    d->config[0x01] = 0x10;
-    d->config[0x02] = 0x02; // device_id
-    d->config[0x03] = 0x00;
-    d->config[0x08] = 0x00; // revision
-    d->config[0x09] = 0x01;
-    d->config[0x0a] = 0x00; // class_sub = host
-    d->config[0x0b] = 0x06; // class_base = PCI_bridge
-    d->config[0x0e] = 0x00; // header_type
-
-    d->config[0x18] = 0x00;  // primary_bus
-    d->config[0x19] = 0x01;  // secondary_bus
-    d->config[0x1a] = 0x00;  // subordinate_bus
-    d->config[0x1c] = 0x00;
-    d->config[0x1d] = 0x00;
-    
-    d->config[0x20] = 0x00; // memory_base
-    d->config[0x21] = 0x00;
-    d->config[0x22] = 0x01; // memory_limit
-    d->config[0x23] = 0x00;
-    
-    d->config[0x24] = 0x00; // prefetchable_memory_base
-    d->config[0x25] = 0x00;
-    d->config[0x26] = 0x00; // prefetchable_memory_limit
-    d->config[0x27] = 0x00;
-
-#if 0
-    /* PCI2PCI bridge same values as PearPC - check this */
-    d->config[0x00] = 0x11; // vendor_id
-    d->config[0x01] = 0x10;
-    d->config[0x02] = 0x26; // device_id
-    d->config[0x03] = 0x00;
-    d->config[0x08] = 0x02; // revision
-    d->config[0x0a] = 0x04; // class_sub = pci2pci
-    d->config[0x0b] = 0x06; // class_base = PCI_bridge
-    d->config[0x0e] = 0x01; // header_type
-
-    d->config[0x18] = 0x0;  // primary_bus
-    d->config[0x19] = 0x1;  // secondary_bus
-    d->config[0x1a] = 0x1;  // subordinate_bus
-    d->config[0x1c] = 0x10; // io_base
-    d->config[0x1d] = 0x20; // io_limit
-    
-    d->config[0x20] = 0x80; // memory_base
-    d->config[0x21] = 0x80;
-    d->config[0x22] = 0x90; // memory_limit
-    d->config[0x23] = 0x80;
-    
-    d->config[0x24] = 0x00; // prefetchable_memory_base
-    d->config[0x25] = 0x84;
-    d->config[0x26] = 0x00; // prefetchable_memory_limit
-    d->config[0x27] = 0x85;
-#endif
-    return s;
-}
-
-/* Uninorth PCI host (for all Mac99 and newer machines */
-static void pci_unin_main_config_writel (void *opaque, target_phys_addr_t addr,
-                                         uint32_t val)
-{
-    PCIBus *s = opaque;
-    int i;
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-
-    for (i = 11; i < 32; i++) {
-        if ((val & (1 << i)) != 0)
-            break;
-    }
-#if 0
-    s->config_reg = 0x80000000 | (1 << 16) | (val & 0x7FC) | (i << 11);
-#else
-    s->config_reg = 0x80000000 | (0 << 16) | (val & 0x7FC) | (i << 11);
-#endif
-}
-
-static uint32_t pci_unin_main_config_readl (void *opaque,
-                                            target_phys_addr_t addr)
-{
-    PCIBus *s = opaque;
-    uint32_t val;
-    int devfn;
-
-    devfn = (s->config_reg >> 8) & 0xFF;
-    val = (1 << (devfn >> 3)) | ((devfn & 0x07) << 8) | (s->config_reg & 0xFC);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-
-    return val;
-}
-
-static CPUWriteMemoryFunc *pci_unin_main_config_write[] = {
-    &pci_unin_main_config_writel,
-    &pci_unin_main_config_writel,
-    &pci_unin_main_config_writel,
-};
-
-static CPUReadMemoryFunc *pci_unin_main_config_read[] = {
-    &pci_unin_main_config_readl,
-    &pci_unin_main_config_readl,
-    &pci_unin_main_config_readl,
-};
-
-static void pci_unin_main_writeb (void *opaque, target_phys_addr_t addr,
-                                  uint32_t val)
-{
-    PCIBus *s = opaque;
-    pci_data_write(s, addr & 7, val, 1);
-}
-
-static void pci_unin_main_writew (void *opaque, target_phys_addr_t addr,
-                                  uint32_t val)
-{
-    PCIBus *s = opaque;
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap16(val);
-#endif
-    pci_data_write(s, addr & 7, val, 2);
-}
-
-static void pci_unin_main_writel (void *opaque, target_phys_addr_t addr,
-                                uint32_t val)
-{
-    PCIBus *s = opaque;
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    pci_data_write(s, addr & 7, val, 4);
-}
-
-static uint32_t pci_unin_main_readb (void *opaque, target_phys_addr_t addr)
-{
-    PCIBus *s = opaque;
-    uint32_t val;
-
-    val = pci_data_read(s, addr & 7, 1);
-
-    return val;
-}
-
-static uint32_t pci_unin_main_readw (void *opaque, target_phys_addr_t addr)
-{
-    PCIBus *s = opaque;
-    uint32_t val;
-
-    val = pci_data_read(s, addr & 7, 2);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap16(val);
-#endif
-
-    return val;
-}
-
-static uint32_t pci_unin_main_readl (void *opaque, target_phys_addr_t addr)
-{
-    PCIBus *s = opaque;
-    uint32_t val;
-
-    val = pci_data_read(s, addr, 4);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-
-    return val;
-}
-
-static CPUWriteMemoryFunc *pci_unin_main_write[] = {
-    &pci_unin_main_writeb,
-    &pci_unin_main_writew,
-    &pci_unin_main_writel,
-};
-
-static CPUReadMemoryFunc *pci_unin_main_read[] = {
-    &pci_unin_main_readb,
-    &pci_unin_main_readw,
-    &pci_unin_main_readl,
-};
-
-#if 0
-
-static void pci_unin_config_writel (void *opaque, target_phys_addr_t addr,
-                                    uint32_t val)
-{
-    PCIBus *s = opaque;
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    s->config_reg = 0x80000000 | (val & ~0x00000001);
-}
-
-static uint32_t pci_unin_config_readl (void *opaque,
-                                       target_phys_addr_t addr)
-{
-    PCIBus *s = opaque;
-    uint32_t val;
-
-    val = (s->config_reg | 0x00000001) & ~0x80000000;
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-
-    return val;
-}
-
-static CPUWriteMemoryFunc *pci_unin_config_write[] = {
-    &pci_unin_config_writel,
-    &pci_unin_config_writel,
-    &pci_unin_config_writel,
-};
-
-static CPUReadMemoryFunc *pci_unin_config_read[] = {
-    &pci_unin_config_readl,
-    &pci_unin_config_readl,
-    &pci_unin_config_readl,
-};
-
-static void pci_unin_writeb (void *opaque, target_phys_addr_t addr,
-                             uint32_t val)
-{
-    PCIBus *s = opaque;
-    pci_data_write(s, addr & 3, val, 1);
-}
-
-static void pci_unin_writew (void *opaque, target_phys_addr_t addr,
-                             uint32_t val)
-{
-    PCIBus *s = opaque;
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap16(val);
-#endif
-    pci_data_write(s, addr & 3, val, 2);
-}
-
-static void pci_unin_writel (void *opaque, target_phys_addr_t addr,
-                             uint32_t val)
-{
-    PCIBus *s = opaque;
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    pci_data_write(s, addr & 3, val, 4);
-}
-
-static uint32_t pci_unin_readb (void *opaque, target_phys_addr_t addr)
-{
-    PCIBus *s = opaque;
-    uint32_t val;
-
-    val = pci_data_read(s, addr & 3, 1);
-
-    return val;
-}
-
-static uint32_t pci_unin_readw (void *opaque, target_phys_addr_t addr)
-{
-    PCIBus *s = opaque;
-    uint32_t val;
-
-    val = pci_data_read(s, addr & 3, 2);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap16(val);
-#endif
-
-    return val;
-}
-
-static uint32_t pci_unin_readl (void *opaque, target_phys_addr_t addr)
-{
-    PCIBus *s = opaque;
-    uint32_t val;
-
-    val = pci_data_read(s, addr & 3, 4);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-
-    return val;
-}
-
-static CPUWriteMemoryFunc *pci_unin_write[] = {
-    &pci_unin_writeb,
-    &pci_unin_writew,
-    &pci_unin_writel,
-};
-
-static CPUReadMemoryFunc *pci_unin_read[] = {
-    &pci_unin_readb,
-    &pci_unin_readw,
-    &pci_unin_readl,
-};
-#endif
-
-PCIBus *pci_pmac_init(void)
-{
-    PCIBus *s;
-    PCIDevice *d;
-    int pci_mem_config, pci_mem_data;
-
-    /* Use values found on a real PowerMac */
-    /* Uninorth main bus */
-    s = pci_register_bus();
-    s->set_irq = pci_set_irq_simple;
-
-    pci_mem_config = cpu_register_io_memory(0, pci_unin_main_config_read, 
-                                            pci_unin_main_config_write, s);
-    pci_mem_data = cpu_register_io_memory(0, pci_unin_main_read,
-                                          pci_unin_main_write, s);
-    cpu_register_physical_memory(0xf2800000, 0x1000, pci_mem_config);
-    cpu_register_physical_memory(0xf2c00000, 0x1000, pci_mem_data);
-    s->devfn_min = 11 << 3;
-    d = pci_register_device(s, "Uni-north main", sizeof(PCIDevice), 
-                            11 << 3, NULL, NULL);
-    d->config[0x00] = 0x6b; // vendor_id : Apple
-    d->config[0x01] = 0x10;
-    d->config[0x02] = 0x1F; // device_id
-    d->config[0x03] = 0x00;
-    d->config[0x08] = 0x00; // revision
-    d->config[0x0A] = 0x00; // class_sub = pci host
-    d->config[0x0B] = 0x06; // class_base = PCI_bridge
-    d->config[0x0C] = 0x08; // cache_line_size
-    d->config[0x0D] = 0x10; // latency_timer
-    d->config[0x0E] = 0x00; // header_type
-    d->config[0x34] = 0x00; // capabilities_pointer
-
-#if 0 // XXX: not activated as PPC BIOS doesn't handle mutiple buses properly
-    /* pci-to-pci bridge */
-    d = pci_register_device("Uni-north bridge", sizeof(PCIDevice), 0, 13 << 3,
-                            NULL, NULL);
-    d->config[0x00] = 0x11; // vendor_id : TI
-    d->config[0x01] = 0x10;
-    d->config[0x02] = 0x26; // device_id
-    d->config[0x03] = 0x00;
-    d->config[0x08] = 0x05; // revision
-    d->config[0x0A] = 0x04; // class_sub = pci2pci
-    d->config[0x0B] = 0x06; // class_base = PCI_bridge
-    d->config[0x0C] = 0x08; // cache_line_size
-    d->config[0x0D] = 0x20; // latency_timer
-    d->config[0x0E] = 0x01; // header_type
-
-    d->config[0x18] = 0x01; // primary_bus
-    d->config[0x19] = 0x02; // secondary_bus
-    d->config[0x1A] = 0x02; // subordinate_bus
-    d->config[0x1B] = 0x20; // secondary_latency_timer
-    d->config[0x1C] = 0x11; // io_base
-    d->config[0x1D] = 0x01; // io_limit
-    d->config[0x20] = 0x00; // memory_base
-    d->config[0x21] = 0x80;
-    d->config[0x22] = 0x00; // memory_limit
-    d->config[0x23] = 0x80;
-    d->config[0x24] = 0x01; // prefetchable_memory_base
-    d->config[0x25] = 0x80;
-    d->config[0x26] = 0xF1; // prefectchable_memory_limit
-    d->config[0x27] = 0x7F;
-    // d->config[0x34] = 0xdc // capabilities_pointer
-#endif
-#if 0 // XXX: not needed for now
-    /* Uninorth AGP bus */
-    s = &pci_bridge[1];
-    pci_mem_config = cpu_register_io_memory(0, pci_unin_config_read, 
-                                            pci_unin_config_write, s);
-    pci_mem_data = cpu_register_io_memory(0, pci_unin_read,
-                                          pci_unin_write, s);
-    cpu_register_physical_memory(0xf0800000, 0x1000, pci_mem_config);
-    cpu_register_physical_memory(0xf0c00000, 0x1000, pci_mem_data);
-
-    d = pci_register_device("Uni-north AGP", sizeof(PCIDevice), 0, 11 << 3,
-                            NULL, NULL);
-    d->config[0x00] = 0x6b; // vendor_id : Apple
-    d->config[0x01] = 0x10;
-    d->config[0x02] = 0x20; // device_id
-    d->config[0x03] = 0x00;
-    d->config[0x08] = 0x00; // revision
-    d->config[0x0A] = 0x00; // class_sub = pci host
-    d->config[0x0B] = 0x06; // class_base = PCI_bridge
-    d->config[0x0C] = 0x08; // cache_line_size
-    d->config[0x0D] = 0x10; // latency_timer
-    d->config[0x0E] = 0x00; // header_type
-    //    d->config[0x34] = 0x80; // capabilities_pointer
-#endif
-
-#if 0 // XXX: not needed for now
-    /* Uninorth internal bus */
-    s = &pci_bridge[2];
-    pci_mem_config = cpu_register_io_memory(0, pci_unin_config_read, 
-                                            pci_unin_config_write, s);
-    pci_mem_data = cpu_register_io_memory(0, pci_unin_read,
-                                          pci_unin_write, s);
-    cpu_register_physical_memory(0xf4800000, 0x1000, pci_mem_config);
-    cpu_register_physical_memory(0xf4c00000, 0x1000, pci_mem_data);
-
-    d = pci_register_device("Uni-north internal", sizeof(PCIDevice),
-                            3, 11 << 3, NULL, NULL);
-    d->config[0x00] = 0x6b; // vendor_id : Apple
-    d->config[0x01] = 0x10;
-    d->config[0x02] = 0x1E; // device_id
-    d->config[0x03] = 0x00;
-    d->config[0x08] = 0x00; // revision
-    d->config[0x0A] = 0x00; // class_sub = pci host
-    d->config[0x0B] = 0x06; // class_base = PCI_bridge
-    d->config[0x0C] = 0x08; // cache_line_size
-    d->config[0x0D] = 0x10; // latency_timer
-    d->config[0x0E] = 0x00; // header_type
-    d->config[0x34] = 0x00; // capabilities_pointer
-#endif
-    return s;
-}
-
-/* Ultrasparc APB PCI host */
-static void pci_apb_config_writel (void *opaque, target_phys_addr_t addr,
-                                         uint32_t val)
-{
-    PCIBus *s = opaque;
-    int i;
-
-    for (i = 11; i < 32; i++) {
-        if ((val & (1 << i)) != 0)
-            break;
-    }
-    s->config_reg = 0x80000000 | (1 << 16) | (val & 0x7FC) | (i << 11);
-}
-
-static uint32_t pci_apb_config_readl (void *opaque,
-                                            target_phys_addr_t addr)
-{
-    PCIBus *s = opaque;
-    uint32_t val;
-    int devfn;
-
-    devfn = (s->config_reg >> 8) & 0xFF;
-    val = (1 << (devfn >> 3)) | ((devfn & 0x07) << 8) | (s->config_reg & 0xFC);
-    return val;
-}
-
-static CPUWriteMemoryFunc *pci_apb_config_write[] = {
-    &pci_apb_config_writel,
-    &pci_apb_config_writel,
-    &pci_apb_config_writel,
-};
-
-static CPUReadMemoryFunc *pci_apb_config_read[] = {
-    &pci_apb_config_readl,
-    &pci_apb_config_readl,
-    &pci_apb_config_readl,
-};
-
-static void apb_config_writel (void *opaque, target_phys_addr_t addr,
-                              uint32_t val)
-{
-    //PCIBus *s = opaque;
-
-    switch (addr & 0x3f) {
-    case 0x00: // Control/Status
-    case 0x10: // AFSR
-    case 0x18: // AFAR
-    case 0x20: // Diagnostic
-    case 0x28: // Target address space
-       // XXX
-    default:
-       break;
-    }
-}
-
-static uint32_t apb_config_readl (void *opaque,
-                                 target_phys_addr_t addr)
-{
-    //PCIBus *s = opaque;
-    uint32_t val;
-
-    switch (addr & 0x3f) {
-    case 0x00: // Control/Status
-    case 0x10: // AFSR
-    case 0x18: // AFAR
-    case 0x20: // Diagnostic
-    case 0x28: // Target address space
-       // XXX
-    default:
-       val = 0;
-       break;
-    }
-    return val;
-}
-
-static CPUWriteMemoryFunc *apb_config_write[] = {
-    &apb_config_writel,
-    &apb_config_writel,
-    &apb_config_writel,
-};
-
-static CPUReadMemoryFunc *apb_config_read[] = {
-    &apb_config_readl,
-    &apb_config_readl,
-    &apb_config_readl,
-};
-
-static void pci_apb_writeb (void *opaque, target_phys_addr_t addr,
-                                  uint32_t val)
-{
-    PCIBus *s = opaque;
-
-    pci_data_write(s, addr & 7, val, 1);
-}
-
-static void pci_apb_writew (void *opaque, target_phys_addr_t addr,
-                                  uint32_t val)
-{
-    PCIBus *s = opaque;
-
-    pci_data_write(s, addr & 7, val, 2);
-}
-
-static void pci_apb_writel (void *opaque, target_phys_addr_t addr,
-                                uint32_t val)
-{
-    PCIBus *s = opaque;
-
-    pci_data_write(s, addr & 7, val, 4);
-}
-
-static uint32_t pci_apb_readb (void *opaque, target_phys_addr_t addr)
-{
-    PCIBus *s = opaque;
-    uint32_t val;
-
-    val = pci_data_read(s, addr & 7, 1);
-    return val;
-}
-
-static uint32_t pci_apb_readw (void *opaque, target_phys_addr_t addr)
-{
-    PCIBus *s = opaque;
-    uint32_t val;
-
-    val = pci_data_read(s, addr & 7, 2);
-    return val;
-}
-
-static uint32_t pci_apb_readl (void *opaque, target_phys_addr_t addr)
-{
-    PCIBus *s = opaque;
-    uint32_t val;
-
-    val = pci_data_read(s, addr, 4);
-    return val;
-}
-
-static CPUWriteMemoryFunc *pci_apb_write[] = {
-    &pci_apb_writeb,
-    &pci_apb_writew,
-    &pci_apb_writel,
-};
-
-static CPUReadMemoryFunc *pci_apb_read[] = {
-    &pci_apb_readb,
-    &pci_apb_readw,
-    &pci_apb_readl,
-};
-
-static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
-                                  uint32_t val)
-{
-    cpu_outb(NULL, addr & 0xffff, val);
-}
-
-static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
-                                  uint32_t val)
-{
-    cpu_outw(NULL, addr & 0xffff, val);
-}
-
-static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
-                                uint32_t val)
-{
-    cpu_outl(NULL, addr & 0xffff, val);
-}
-
-static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
-{
-    uint32_t val;
-
-    val = cpu_inb(NULL, addr & 0xffff);
-    return val;
-}
-
-static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
-{
-    uint32_t val;
-
-    val = cpu_inw(NULL, addr & 0xffff);
-    return val;
-}
-
-static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
-{
-    uint32_t val;
-
-    val = cpu_inl(NULL, addr & 0xffff);
-    return val;
-}
-
-static CPUWriteMemoryFunc *pci_apb_iowrite[] = {
-    &pci_apb_iowriteb,
-    &pci_apb_iowritew,
-    &pci_apb_iowritel,
-};
-
-static CPUReadMemoryFunc *pci_apb_ioread[] = {
-    &pci_apb_ioreadb,
-    &pci_apb_ioreadw,
-    &pci_apb_ioreadl,
-};
-
-PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base)
-{
-    PCIBus *s;
-    PCIDevice *d;
-    int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
-
-    /* Ultrasparc APB main bus */
-    s = pci_register_bus();
-    s->set_irq = pci_set_irq_simple;
-
-    pci_mem_config = cpu_register_io_memory(0, pci_apb_config_read,
-                                            pci_apb_config_write, s);
-    apb_config = cpu_register_io_memory(0, apb_config_read,
-                                       apb_config_write, s);
-    pci_mem_data = cpu_register_io_memory(0, pci_apb_read,
-                                          pci_apb_write, s);
-    pci_ioport = cpu_register_io_memory(0, pci_apb_ioread,
-                                          pci_apb_iowrite, s);
-
-    cpu_register_physical_memory(special_base + 0x2000ULL, 0x40, apb_config);
-    cpu_register_physical_memory(special_base + 0x1000000ULL, 0x10, 
pci_mem_config);
-    cpu_register_physical_memory(special_base + 0x2000000ULL, 0x10000, 
pci_ioport);
-    cpu_register_physical_memory(mem_base, 0x10000000, pci_mem_data); // XXX 
size should be 4G-prom
-
-    d = pci_register_device(s, "Advanced PCI Bus", sizeof(PCIDevice), 
-                            -1, NULL, NULL);
-    d->config[0x00] = 0x8e; // vendor_id : Sun
-    d->config[0x01] = 0x10;
-    d->config[0x02] = 0x00; // device_id
-    d->config[0x03] = 0xa0;
-    d->config[0x04] = 0x06; // command = bus master, pci mem
-    d->config[0x05] = 0x00;
-    d->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
-    d->config[0x07] = 0x03; // status = medium devsel
-    d->config[0x08] = 0x00; // revision
-    d->config[0x09] = 0x00; // programming i/f
-    d->config[0x0A] = 0x00; // class_sub = pci host
-    d->config[0x0B] = 0x06; // class_base = PCI_bridge
-    d->config[0x0D] = 0x10; // latency_timer
-    d->config[0x0E] = 0x00; // header_type
-    return s;
-}
-
 /***********************************************************/
 /* generic PCI irq support */
 
@@ -1547,34 +403,46 @@ void pci_set_irq(PCIDevice *pci_dev, int
 void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level)
 {
     PCIBus *bus = pci_dev->bus;
-    bus->set_irq(pci_dev, irq_num, level);
+    bus->set_irq(pci_dev, bus->irq_opaque, irq_num, level);
 }
 
 /***********************************************************/
 /* monitor info on PCI */
 
+typedef struct {
+    uint16_t class;
+    const char *desc;
+} pci_class_desc;
+
+static pci_class_desc pci_class_descriptions[] = 
+{
+    { 0x0101, "IDE controller"},
+    { 0x0200, "Ethernet controller"},
+    { 0x0300, "VGA controller"},
+    { 0x0600, "Host bridge"},
+    { 0x0601, "ISA bridge"},
+    { 0x0604, "PCI bridge"},
+    { 0x0c03, "USB controller"},
+    { 0, NULL}
+};
+
 static void pci_info_device(PCIDevice *d)
 {
     int i, class;
     PCIIORegion *r;
+    pci_class_desc *desc;
 
     term_printf("  Bus %2d, device %3d, function %d:\n",
            d->bus->bus_num, d->devfn >> 3, d->devfn & 7);
     class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE)));
     term_printf("    ");
-    switch(class) {
-    case 0x0101:
-        term_printf("IDE controller");
-        break;
-    case 0x0200:
-        term_printf("Ethernet controller");
-        break;
-    case 0x0300:
-        term_printf("VGA controller");
-        break;
-    default:
+    desc = pci_class_descriptions;
+    while (desc->desc && class != desc->class)
+        desc++;
+    if (desc->desc) {
+        term_printf("%s", desc->desc);
+    } else {
         term_printf("Class %04x", class);
-        break;
     }
     term_printf(": PCI device %04x:%04x\n",
            le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))),
@@ -1598,7 +466,7 @@ static void pci_info_device(PCIDevice *d
     }
 }
 
-void pci_info(void)
+void pci_for_each_device(void (*fn)(PCIDevice *d))
 {
     PCIBus *bus = first_bus;
     PCIDevice *d;
@@ -1608,253 +476,14 @@ void pci_info(void)
         for(devfn = 0; devfn < 256; devfn++) {
             d = bus->devices[devfn];
             if (d)
-                pci_info_device(d);
-        }
-    }
-}
-
-/***********************************************************/
-/* XXX: the following should be moved to the PC BIOS */
-
-static __attribute__((unused)) uint32_t isa_inb(uint32_t addr)
-{
-    return cpu_inb(NULL, addr);
-}
-
-static void isa_outb(uint32_t val, uint32_t addr)
-{
-    cpu_outb(NULL, addr, val);
-}
-
-static __attribute__((unused)) uint32_t isa_inw(uint32_t addr)
-{
-    return cpu_inw(NULL, addr);
-}
-
-static __attribute__((unused)) void isa_outw(uint32_t val, uint32_t addr)
-{
-    cpu_outw(NULL, addr, val);
-}
-
-static __attribute__((unused)) uint32_t isa_inl(uint32_t addr)
-{
-    return cpu_inl(NULL, addr);
-}
-
-static __attribute__((unused)) void isa_outl(uint32_t val, uint32_t addr)
-{
-    cpu_outl(NULL, addr, val);
-}
-
-static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)
-{
-    PCIBus *s = d->bus;
-    s->config_reg = 0x80000000 | (s->bus_num << 16) | 
-        (d->devfn << 8) | addr;
-    pci_data_write(s, 0, val, 4);
-}
-
-static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val)
-{
-    PCIBus *s = d->bus;
-    s->config_reg = 0x80000000 | (s->bus_num << 16) | 
-        (d->devfn << 8) | (addr & ~3);
-    pci_data_write(s, addr & 3, val, 2);
-}
-
-static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val)
-{
-    PCIBus *s = d->bus;
-    s->config_reg = 0x80000000 | (s->bus_num << 16) | 
-        (d->devfn << 8) | (addr & ~3);
-    pci_data_write(s, addr & 3, val, 1);
-}
-
-static __attribute__((unused)) uint32_t pci_config_readl(PCIDevice *d, 
uint32_t addr)
-{
-    PCIBus *s = d->bus;
-    s->config_reg = 0x80000000 | (s->bus_num << 16) | 
-        (d->devfn << 8) | addr;
-    return pci_data_read(s, 0, 4);
-}
-
-static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr)
-{
-    PCIBus *s = d->bus;
-    s->config_reg = 0x80000000 | (s->bus_num << 16) | 
-        (d->devfn << 8) | (addr & ~3);
-    return pci_data_read(s, addr & 3, 2);
-}
-
-static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr)
-{
-    PCIBus *s = d->bus;
-    s->config_reg = 0x80000000 | (s->bus_num << 16) | 
-        (d->devfn << 8) | (addr & ~3);
-    return pci_data_read(s, addr & 3, 1);
-}
-
-static uint32_t pci_bios_io_addr;
-static uint32_t pci_bios_mem_addr;
-/* host irqs corresponding to PCI irqs A-D */
-static uint8_t pci_irqs[4] = { 10, 11, 10, 11 };
-
-static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr)
-{
-    PCIIORegion *r;
-    uint16_t cmd;
-    uint32_t ofs;
-
-    if ( region_num == PCI_ROM_SLOT ) {
-        ofs = 0x30;
-    }else{
-        ofs = 0x10 + region_num * 4;
-    }
-
-    pci_config_writel(d, ofs, addr);
-    r = &d->io_regions[region_num];
-
-    /* enable memory mappings */
-    cmd = pci_config_readw(d, PCI_COMMAND);
-    if ( region_num == PCI_ROM_SLOT )
-        cmd |= 2;
-    else if (r->type & PCI_ADDRESS_SPACE_IO)
-        cmd |= 1;
-    else
-        cmd |= 2;
-    pci_config_writew(d, PCI_COMMAND, cmd);
-}
-
-static void pci_bios_init_device(PCIDevice *d)
-{
-    int class;
-    PCIIORegion *r;
-    uint32_t *paddr;
-    int i, pin, pic_irq, vendor_id, device_id;
-
-    class = pci_config_readw(d, PCI_CLASS_DEVICE);
-    vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
-    device_id = pci_config_readw(d, PCI_DEVICE_ID);
-    switch(class) {
-    case 0x0101:
-        if (vendor_id == 0x8086 && device_id == 0x7010) {
-            /* PIIX3 IDE */
-            pci_config_writew(d, 0x40, 0x8000); // enable IDE0
-            pci_config_writew(d, 0x42, 0x8000); // enable IDE1
-            goto default_map;
-        } else {
-            /* IDE: we map it as in ISA mode */
-            pci_set_io_region_addr(d, 0, 0x1f0);
-            pci_set_io_region_addr(d, 1, 0x3f4);
-            pci_set_io_region_addr(d, 2, 0x170);
-            pci_set_io_region_addr(d, 3, 0x374);
-        }
-        break;
-       case 0x0680:
-       if (vendor_id == 0x8086 && device_id == 0x7113) {
-          // PIIX4 ACPI PM 
-        pci_config_writew(d, 0x20, 0x0000); // NO smb bus IO enable in PIIX4
-        pci_config_writew(d, 0x22, 0x0000); 
-        goto default_map;
-       }
-         break;
-
-    case 0x0300:
-        if (vendor_id != 0x1234)
-            goto default_map;
-        /* VGA: map frame buffer to default Bochs VBE address */
-        pci_set_io_region_addr(d, 0, 0xE0000000);
-        break;
-
-    case 0x0800:
-        /* PIC */
-        vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
-        device_id = pci_config_readw(d, PCI_DEVICE_ID);
-        if (vendor_id == 0x1014) {
-            /* IBM */
-            if (device_id == 0x0046 || device_id == 0xFFFF) {
-                /* MPIC & MPIC2 */
-                pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000);
-            }
-        }
-        break;
-    case 0xff00:
-        if (vendor_id == 0x0106b &&
-            (device_id == 0x0017 || device_id == 0x0022)) {
-            /* macio bridge */
-            pci_set_io_region_addr(d, 0, 0x80800000);
-        }
-        break;
-    default:
-    default_map:
-        /* default memory mappings */
-        for(i = 0; i < PCI_NUM_REGIONS; i++) {
-            r = &d->io_regions[i];
-            if (r->size) {
-                if (r->type & PCI_ADDRESS_SPACE_IO)
-                    paddr = &pci_bios_io_addr;
-                else
-                    paddr = &pci_bios_mem_addr;
-                *paddr = (*paddr + r->size - 1) & ~(r->size - 1);
-                pci_set_io_region_addr(d, i, *paddr);
-                *paddr += r->size;
-            }
-        }
-        break;
-    }
-
-    /* map the interrupt */
-    pin = pci_config_readb(d, PCI_INTERRUPT_PIN);
-    if (pin != 0) {
-        pin = pci_slot_get_pirq(d, pin - 1);
-        pic_irq = pci_irqs[pin];
-        pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);
-    }
-    if (class== 0x0680&& vendor_id == 0x8086 && device_id == 0x7113) {
-         // PIIX4 ACPI PM
-       pci_config_writew(d, 0x20, 0x0000); // NO smb bus IO enable in PIIX4
-       pci_config_writew(d, 0x22, 0x0000);
-       pci_config_writew(d, 0x3c, 0x0009); // Hardcodeed IRQ9
-       pci_config_writew(d, 0x3d, 0x0001);
-    }
-}
-
-/*
- * This function initializes the PCI devices as a normal PCI BIOS
- * would do. It is provided just in case the BIOS has no support for
- * PCI.
- */
-void pci_bios_init(void)
-{
-    PCIBus *bus;
-    PCIDevice *d;
-    int devfn, i, irq;
-    uint8_t elcr[2];
-
-    pci_bios_io_addr = 0xc000;
-    pci_bios_mem_addr = 0xf0000000;
-
-    /* activate IRQ mappings */
-    elcr[0] = 0x00;
-    elcr[1] = 0x00;
-    for(i = 0; i < 4; i++) {
-        irq = pci_irqs[i];
-        /* set to trigger level */
-        elcr[irq >> 3] |= (1 << (irq & 7));
-        /* activate irq remapping in PIIX */
-        pci_config_writeb((PCIDevice *)piix3_state, 0x60 + i, irq);
-    }
-    isa_outb(elcr[0], 0x4d0);
-    isa_outb(elcr[1], 0x4d1);
-
-    bus = first_bus;
-    if (bus) {
-        for(devfn = 0; devfn < 256; devfn++) {
-            d = bus->devices[devfn];
-            if (d)
-                pci_bios_init_device(d);
-        }
-    }
+                fn(d);
+        }
+    }
+}
+
+void pci_info(void)
+{
+    pci_for_each_device(pci_info_device);
 }
 
 /* Initialize a PCI NIC.  */
@@ -1864,6 +493,8 @@ void pci_nic_init(PCIBus *bus, NICInfo *
         pci_ne2000_init(bus, nd);
     } else if (strcmp(nd->model, "rtl8139") == 0) {
         pci_rtl8139_init(bus, nd);
+    } else if (strcmp(nd->model, "pcnet") == 0) {
+        pci_pcnet_init(bus, nd);
     } else {
         fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
         exit (1);
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/pcspk.c
--- a/tools/ioemu/hw/pcspk.c    Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/pcspk.c    Mon Aug 07 18:25:30 2006 +0100
@@ -95,7 +95,7 @@ int pcspk_audio_init(AudioState *audio)
 int pcspk_audio_init(AudioState *audio)
 {
     PCSpkState *s = &pcspk_state;
-    audsettings_t as = {PCSPK_SAMPLE_RATE, 1, AUD_FMT_U8};
+    audsettings_t as = {PCSPK_SAMPLE_RATE, 1, AUD_FMT_U8, 0};
 
     if (!audio) {
         AUD_log(s_spk, "No audio state\n");
@@ -103,7 +103,7 @@ int pcspk_audio_init(AudioState *audio)
     }
     AUD_register_card(audio, s_spk, &s->card);
 
-    s->voice = AUD_open_out(&s->card, s->voice, s_spk, s, pcspk_callback, &as, 
0);
+    s->voice = AUD_open_out(&s->card, s->voice, s_spk, s, pcspk_callback, &as);
     if (!s->voice) {
         AUD_log(s_spk, "Could not open voice\n");
         return -1;
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/piix4acpi.c
--- a/tools/ioemu/hw/piix4acpi.c        Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/piix4acpi.c        Mon Aug 07 18:25:30 2006 +0100
@@ -375,7 +375,7 @@ static void acpi_map(PCIDevice *pci_dev,
 }
 
 /* PIIX4 acpi pci configuration space, func 3 */
-void pci_piix4_acpi_init(PCIBus *bus)
+void pci_piix4_acpi_init(PCIBus *bus, int devfn)
 {
     PCIAcpiState *d;
     uint8_t *pci_conf;
@@ -383,7 +383,7 @@ void pci_piix4_acpi_init(PCIBus *bus)
     /* register a function 3 of PIIX4 */
     d = (PCIAcpiState *)pci_register_device(
         bus, "PIIX4 ACPI", sizeof(PCIAcpiState),
-        ((PCIDevice *)piix3_state)->devfn + 3, NULL, NULL);
+        devfn, NULL, NULL);
 
     acpi_state = d;
     pci_conf = d->dev.config;
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/pl050.c
--- a/tools/ioemu/hw/pl050.c    Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/pl050.c    Mon Aug 07 18:25:30 2006 +0100
@@ -1,5 +1,5 @@
 /* 
- * Arm PrimeCell PL050 Kyeboard / Mouse Interface
+ * Arm PrimeCell PL050 Keyboard / Mouse Interface
  *
  * Copyright (c) 2006 CodeSourcery.
  * Written by Paul Brook
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/ppc_chrp.c
--- a/tools/ioemu/hw/ppc_chrp.c Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/ppc_chrp.c Mon Aug 07 18:25:30 2006 +0100
@@ -415,19 +415,18 @@ static void ppc_chrp_init(int ram_size, 
 
     if (is_heathrow) {
         isa_mem_base = 0x80000000;
-        pci_bus = pci_grackle_init(0xfec00000);
         
         /* Register 2 MB of ISA IO space */
         PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write, 
NULL);
         cpu_register_physical_memory(0xfe000000, 0x00200000, PPC_io_memory);
         
         /* init basic PC hardware */
+        pic = heathrow_pic_init(&heathrow_pic_mem_index);
+        set_irq = heathrow_pic_set_irq;
+        pci_bus = pci_grackle_init(0xfec00000, pic);
         vga_initialize(pci_bus, ds, phys_ram_base + ram_size, 
                        ram_size, vga_ram_size,
                        vga_bios_offset, vga_bios_size);
-        pic = heathrow_pic_init(&heathrow_pic_mem_index);
-        set_irq = heathrow_pic_set_irq;
-        pci_set_pic(pci_bus, set_irq, pic);
 
         /* XXX: suppress that */
         isa_pic = pic_init(pic_irq_request, NULL);
@@ -462,7 +461,6 @@ static void ppc_chrp_init(int ram_size, 
         arch_name = "HEATHROW";
     } else {
         isa_mem_base = 0x80000000;
-        pci_bus = pci_pmac_init();
         
         /* Register 8 MB of ISA IO space */
         PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write, 
NULL);
@@ -472,13 +470,13 @@ static void ppc_chrp_init(int ram_size, 
         unin_memory = cpu_register_io_memory(0, unin_read, unin_write, NULL);
         cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory);
 
+        pic = openpic_init(NULL, &openpic_mem_index, 1, &env);
+        set_irq = openpic_set_irq;
+        pci_bus = pci_pmac_init(pic);
         /* init basic PC hardware */
         vga_initialize(pci_bus, ds, phys_ram_base + ram_size,
                        ram_size, vga_ram_size,
                        vga_bios_offset, vga_bios_size);
-        pic = openpic_init(NULL, &openpic_mem_index, 1, &env);
-        set_irq = openpic_set_irq;
-        pci_set_pic(pci_bus, set_irq, pic);
 
         /* XXX: suppress that */
         isa_pic = pic_init(pic_irq_request, NULL);
@@ -508,7 +506,11 @@ static void ppc_chrp_init(int ram_size, 
         
         arch_name = "MAC99";
     }
-    
+
+    if (usb_enabled) {
+        usb_ohci_init(pci_bus, 3, -1);
+    }
+
     if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
         graphic_depth = 15;
 
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/ppc_prep.c
--- a/tools/ioemu/hw/ppc_prep.c Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/ppc_prep.c Mon Aug 07 18:25:30 2006 +0100
@@ -665,6 +665,10 @@ static void ppc_prep_init(int ram_size, 
     cpu_register_physical_memory(0xFEFF0000, 0x1000, PPC_io_memory);
 #endif
 
+    if (usb_enabled) {
+        usb_ohci_init(pci_bus, 3, -1);
+    }
+
     nvram = m48t59_init(8, 0, 0x0074, NVRAM_SIZE, 59);
     if (nvram == NULL)
         return;
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/rtl8139.c
--- a/tools/ioemu/hw/rtl8139.c  Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/rtl8139.c  Mon Aug 07 18:25:30 2006 +0100
@@ -23,14 +23,32 @@
  
  * Modifications:
  *  2006-Jan-28  Mark Malakanov :   TSAD and CSCR implementation (for Windows 
driver)
- *                 
+ * 
+ *  2006-Apr-28  Juergen Lock   :   EEPROM emulation changes for FreeBSD driver
+ *                                  HW revision ID changes for FreeBSD driver
+ * 
+ *  2006-Jul-01  Igor Kovalenko :   Implemented loopback mode for FreeBSD 
driver
+ *                                  Corrected packet transfer reassembly 
routine for 8139C+ mode
+ *                                  Rearranged debugging print statements
+ *                                  Implemented PCI timer interrupt (disabled 
by default)
+ *                                  Implemented Tally Counters, increased VM 
load/save version
+ *                                  Implemented IP/TCP/UDP checksum task 
offloading
+ *
+ *  2006-Jul-04  Igor Kovalenko :   Implemented TCP segmentation offloading
+ *                                  Fixed MTU=1500 for produced ethernet frames
+ *
+ *  2006-Jul-09  Igor Kovalenko :   Fixed TCP header length calculation while 
processing
+ *                                  segmentation offloading
+ *                                  Removed slirp.h dependency
+ *                                  Added rx/tx buffer reset when enabling 
rx/tx operation
  */
 
 #include "vl.h"
-
 
 /* debug RTL8139 card */
 //#define DEBUG_RTL8139 1
+
+#define PCI_FREQUENCY 33000000L
 
 /* debug RTL8139 card C+ mode only */
 //#define DEBUG_RTL8139CP 1
@@ -39,6 +57,8 @@
    ignored by most drivers, disabled by default */
 //#define RTL8139_CALCULATE_RXCRC 1
 
+/* Uncomment to enable on-board timer interrupts */
+//#define RTL8139_ONBOARD_TIMER 1
 
 #if defined(RTL8139_CALCULATE_RXCRC)
 /* For crc32 */
@@ -52,12 +72,19 @@
 #define MOD2(input, size) \
     ( ( input ) & ( size - 1 )  )
 
+#if defined (DEBUG_RTL8139)
+#  define DEBUG_PRINT(x) do { printf x ; } while (0)
+#else
+#  define DEBUG_PRINT(x)
+#endif
+
 /* Symbolic offsets to registers. */
 enum RTL8139_registers {
     MAC0 = 0,        /* Ethernet hardware address. */
     MAR0 = 8,        /* Multicast filter. */
-    TxStatus0 = 0x10,    /* Transmit status (Four 32bit registers). */
-    TxAddr0 = 0x20,        /* Tx descriptors (also four 32bit). */
+    TxStatus0 = 0x10,/* Transmit status (Four 32bit registers). C mode only */
+                     /* Dump Tally Conter control register(64bit). C+ mode 
only */
+    TxAddr0 = 0x20,  /* Tx descriptors (also four 32bit). */
     RxBuf = 0x30,
     ChipCmd = 0x37,
     RxBufPtr = 0x38,
@@ -115,8 +142,10 @@ enum ChipCmdBits {
 
 /* C+ mode */
 enum CplusCmdBits {
-    CPlusRxEnb = 0x0002,
-    CPlusTxEnb = 0x0001,
+    CPlusRxVLAN   = 0x0040, /* enable receive VLAN detagging */
+    CPlusRxChkSum = 0x0020, /* enable receive checksum offloading */
+    CPlusRxEnb    = 0x0002,
+    CPlusTxEnb    = 0x0001,
 };
 
 /* Interrupt register bits, using my own meaningful names. */
@@ -315,6 +344,11 @@ enum chip_flags {
     (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22)
 #define HW_REVID_MASK    HW_REVID(1, 1, 1, 1, 1, 1, 1)
 
+#define RTL8139_PCI_REVID_8139      0x10
+#define RTL8139_PCI_REVID_8139CPLUS 0x20
+
+#define RTL8139_PCI_REVID           RTL8139_PCI_REVID_8139CPLUS
+
 /* Size is 64 * 16bit words */
 #define EEPROM_9346_ADDR_BITS 6
 #define EEPROM_9346_SIZE  (1 << EEPROM_9346_ADDR_BITS)
@@ -356,11 +390,41 @@ typedef struct EEprom9346
     uint8_t eedo;
 } EEprom9346;
 
+typedef struct RTL8139TallyCounters
+{
+    /* Tally counters */
+    uint64_t   TxOk;
+    uint64_t   RxOk;
+    uint64_t   TxERR;
+    uint32_t   RxERR;
+    uint16_t   MissPkt;
+    uint16_t   FAE;
+    uint32_t   Tx1Col;
+    uint32_t   TxMCol;
+    uint64_t   RxOkPhy;
+    uint64_t   RxOkBrd;
+    uint32_t   RxOkMul;
+    uint16_t   TxAbt;
+    uint16_t   TxUndrn;
+} RTL8139TallyCounters;
+
+/* Clears all tally counters */
+static void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters);
+
+/* Writes tally counters to specified physical memory address */
+static void RTL8139TallyCounters_physical_memory_write(target_phys_addr_t 
tc_addr, RTL8139TallyCounters* counters);
+
+/* Loads values of tally counters from VM state file */
+static void RTL8139TallyCounters_load(QEMUFile* f, RTL8139TallyCounters 
*tally_counters);
+
+/* Saves values of tally counters to VM state file */
+static void RTL8139TallyCounters_save(QEMUFile* f, RTL8139TallyCounters 
*tally_counters);
+
 typedef struct RTL8139State {
     uint8_t phys[8]; /* mac address */
     uint8_t mult[8]; /* multicast mask array */
 
-    uint32_t TxStatus[4]; /* TxStatus0 */
+    uint32_t TxStatus[4]; /* TxStatus0 in C mode*/ /* also DTCCR[0] and 
DTCCR[1] in C+ mode */
     uint32_t TxAddr[4];   /* TxAddr0 */
     uint32_t RxBuf;       /* Receive buffer */
     uint32_t RxBufferSize;/* internal variable, receive ring buffer size in C 
mode */
@@ -414,14 +478,27 @@ typedef struct RTL8139State {
     uint32_t   RxRingAddrHI;
 
     EEprom9346 eeprom;
-    
+
+    uint32_t   TCTR;
+    uint32_t   TimerInt;
+    int64_t    TCTR_base;
+
+    /* Tally counters */
+    RTL8139TallyCounters tally_counters;
+
+    /* Non-persistent data */
+    uint8_t   *cplus_txbuffer;
+    int        cplus_txbuffer_len;
+    int        cplus_txbuffer_offset;
+
+    /* PCI interrupt timer */
+    QEMUTimer *timer;
+
 } RTL8139State;
 
 void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command)
 {
-#if defined(DEBUG_RTL8139)
-    printf("RTL8139: eeprom command 0x%02x\n", command);
-#endif
+    DEBUG_PRINT(("RTL8139: eeprom command 0x%02x\n", command));
 
     switch (command & Chip9346_op_mask)
     {
@@ -432,10 +509,8 @@ void prom9346_decode_command(EEprom9346 
             eeprom->eedo = 0;
             eeprom->tick = 0;
             eeprom->mode = Chip9346_data_read;
-#if defined(DEBUG_RTL8139)
-            printf("RTL8139: eeprom read from address 0x%02x data=0x%04x\n",
-                   eeprom->address, eeprom->output);
-#endif
+            DEBUG_PRINT(("RTL8139: eeprom read from address 0x%02x 
data=0x%04x\n",
+                   eeprom->address, eeprom->output));
         }
         break;
 
@@ -445,10 +520,8 @@ void prom9346_decode_command(EEprom9346 
             eeprom->input = 0;
             eeprom->tick = 0;
             eeprom->mode = Chip9346_none; /* Chip9346_data_write */
-#if defined(DEBUG_RTL8139)
-            printf("RTL8139: eeprom begin write to address 0x%02x\n",
-                   eeprom->address);
-#endif
+            DEBUG_PRINT(("RTL8139: eeprom begin write to address 0x%02x\n",
+                   eeprom->address));
         }
         break;
         default:
@@ -456,19 +529,13 @@ void prom9346_decode_command(EEprom9346 
             switch (command & Chip9346_op_ext_mask)
             {
                 case Chip9346_op_write_enable:
-#if defined(DEBUG_RTL8139)
-                    printf("RTL8139: eeprom write enabled\n");
-#endif
+                    DEBUG_PRINT(("RTL8139: eeprom write enabled\n"));
                     break;
                 case Chip9346_op_write_all:
-#if defined(DEBUG_RTL8139)
-                    printf("RTL8139: eeprom begin write all\n");
-#endif
+                    DEBUG_PRINT(("RTL8139: eeprom begin write all\n"));
                     break;
                 case Chip9346_op_write_disable:
-#if defined(DEBUG_RTL8139)
-                    printf("RTL8139: eeprom write disabled\n");
-#endif
+                    DEBUG_PRINT(("RTL8139: eeprom write disabled\n"));
                     break;
             }
             break;
@@ -481,9 +548,7 @@ void prom9346_shift_clock(EEprom9346 *ee
 
     ++ eeprom->tick;
 
-#if defined(DEBUG_RTL8139)
-    printf("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi, 
eeprom->eedo);
-#endif
+    DEBUG_PRINT(("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, 
eeprom->eedi, eeprom->eedo));
 
     switch (eeprom->mode)
     {
@@ -493,9 +558,7 @@ void prom9346_shift_clock(EEprom9346 *ee
                 eeprom->mode = Chip9346_read_command;
                 eeprom->tick = 0;
                 eeprom->input = 0;
-#if defined(DEBUG_RTL8139)
-                printf("eeprom: +++ synchronized, begin command read\n");
-#endif
+                DEBUG_PRINT(("eeprom: +++ synchronized, begin command 
read\n"));
             }
             break;
 
@@ -512,14 +575,24 @@ void prom9346_shift_clock(EEprom9346 *ee
             eeprom->output <<= 1;
             if (eeprom->tick == 16)
             {
+#if 1
+        // the FreeBSD drivers (rl and re) don't explicitly toggle
+        // CS between reads (or does setting Cfg9346 to 0 count too?),
+        // so we need to enter wait-for-command state here
+                eeprom->mode = Chip9346_enter_command_mode;
+                eeprom->input = 0;
+                eeprom->tick = 0;
+
+                DEBUG_PRINT(("eeprom: +++ end of read, awaiting next 
command\n"));
+#else
+        // original behaviour
                 ++eeprom->address;
                 eeprom->address &= EEPROM_9346_ADDR_MASK;
                 eeprom->output = eeprom->contents[eeprom->address];
                 eeprom->tick = 0;
 
-#if defined(DEBUG_RTL8139)
-                printf("eeprom: +++ read next address 0x%02x data=0x%04x\n",
-                       eeprom->address, eeprom->output);
+                DEBUG_PRINT(("eeprom: +++ read next address 0x%02x 
data=0x%04x\n",
+                       eeprom->address, eeprom->output));
 #endif
             }
             break;
@@ -528,10 +601,9 @@ void prom9346_shift_clock(EEprom9346 *ee
             eeprom->input = (eeprom->input << 1) | (bit & 1);
             if (eeprom->tick == 16)
             {
-#if defined(DEBUG_RTL8139)
-            printf("RTL8139: eeprom write to address 0x%02x data=0x%04x\n",
-                   eeprom->address, eeprom->input);
-#endif
+                DEBUG_PRINT(("RTL8139: eeprom write to address 0x%02x 
data=0x%04x\n",
+                       eeprom->address, eeprom->input));
+
                 eeprom->contents[eeprom->address] = eeprom->input;
                 eeprom->mode = Chip9346_none; /* waiting for next command 
after CS cycle */
                 eeprom->tick = 0;
@@ -548,10 +620,9 @@ void prom9346_shift_clock(EEprom9346 *ee
                 {
                     eeprom->contents[i] = eeprom->input;
                 }
-#if defined(DEBUG_RTL8139)
-                printf("RTL8139: eeprom filled with data=0x%04x\n",
-                       eeprom->input);
-#endif
+                DEBUG_PRINT(("RTL8139: eeprom filled with data=0x%04x\n",
+                       eeprom->input));
+
                 eeprom->mode = Chip9346_enter_command_mode;
                 eeprom->tick = 0;
                 eeprom->input = 0;
@@ -582,9 +653,8 @@ void prom9346_set_wire(RTL8139State *s, 
     eeprom->eesk = eesk;
     eeprom->eedi = eedi;
 
-#if defined(DEBUG_RTL8139)
-    printf("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n", eeprom->eecs, 
eeprom->eesk, eeprom->eedi, eeprom->eedo);
-#endif
+    DEBUG_PRINT(("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n",
+                 eeprom->eecs, eeprom->eesk, eeprom->eedi, eeprom->eedo));
 
     if (!old_eecs && eecs)
     {
@@ -594,17 +664,12 @@ void prom9346_set_wire(RTL8139State *s, 
         eeprom->output = 0;
         eeprom->mode = Chip9346_enter_command_mode;
 
-#if defined(DEBUG_RTL8139)
-        printf("=== eeprom: begin access, enter command mode\n");
-#endif
-
+        DEBUG_PRINT(("=== eeprom: begin access, enter command mode\n"));
     }
 
     if (!eecs)
     {
-#if defined(DEBUG_RTL8139)
-        printf("=== eeprom: end access\n");
-#endif
+        DEBUG_PRINT(("=== eeprom: end access\n"));
         return;
     }
 
@@ -619,10 +684,10 @@ static void rtl8139_update_irq(RTL8139St
 {
     int isr;
     isr = (s->IntrStatus & s->IntrMask) & 0xffff;
-#if defined(DEBUG_RTL8139)
-    printf("RTL8139: Set IRQ line %d to %d (%04x %04x)\n",
-       s->irq, isr ? 1 : 0, s->IntrStatus, s->IntrMask);
-#endif
+
+    DEBUG_PRINT(("RTL8139: Set IRQ line %d to %d (%04x %04x)\n",
+       s->irq, isr ? 1 : 0, s->IntrStatus, s->IntrMask));
+
     if (s->irq == 16) {
         /* PCI irq */
         pci_set_irq(s->pci_dev, 0, (isr != 0));
@@ -691,9 +756,7 @@ static void rtl8139_write_buffer(RTL8139
         /* write packet data */
         if (wrapped && s->RxBufferSize < 65536 && !rtl8139_RxWrap(s))
         {
-    #if defined(DEBUG_RTL8139)
-            printf(">>> RTL8139: rx packet wrapped in buffer at %d\n", 
size-wrapped);
-    #endif
+            DEBUG_PRINT((">>> RTL8139: rx packet wrapped in buffer at %d\n", 
size-wrapped));
 
             if (size > wrapped)
             {
@@ -751,7 +814,7 @@ static int rtl8139_can_receive(void *opa
     }
 }
 
-static void rtl8139_receive(void *opaque, const uint8_t *buf, int size)
+static void rtl8139_do_receive(void *opaque, const uint8_t *buf, int size, int 
do_interrupt)
 {
     RTL8139State *s = opaque;
 
@@ -761,16 +824,12 @@ static void rtl8139_receive(void *opaque
     static const uint8_t broadcast_macaddr[6] = 
         { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
-#if defined(DEBUG_RTL8139)
-    printf(">>> RTL8139: received len=%d\n", size);
-#endif
+    DEBUG_PRINT((">>> RTL8139: received len=%d\n", size));
 
     /* test if board clock is stopped */
     if (!s->clock_enabled)
     {
-#if defined(DEBUG_RTL8139)
-        printf("RTL8139: stopped ==========================\n");
-#endif
+        DEBUG_PRINT(("RTL8139: stopped ==========================\n"));
         return;
     }
 
@@ -778,42 +837,44 @@ static void rtl8139_receive(void *opaque
 
     if (!rtl8139_receiver_enabled(s))
     {
-#if defined(DEBUG_RTL8139)
-        printf("RTL8139: receiver disabled ================\n");
-#endif
+        DEBUG_PRINT(("RTL8139: receiver disabled ================\n"));
         return;
     }
 
     /* XXX: check this */
     if (s->RxConfig & AcceptAllPhys) {
         /* promiscuous: receive all */
-#if defined(DEBUG_RTL8139)
-        printf(">>> RTL8139: packet received in promiscuous mode\n");
-#endif
+        DEBUG_PRINT((">>> RTL8139: packet received in promiscuous mode\n"));
 
     } else {
         if (!memcmp(buf,  broadcast_macaddr, 6)) {
             /* broadcast address */
             if (!(s->RxConfig & AcceptBroadcast))
             {
-#if defined(DEBUG_RTL8139)
-                printf(">>> RTL8139: broadcast packet rejected\n");
-#endif
+                DEBUG_PRINT((">>> RTL8139: broadcast packet rejected\n"));
+
+                /* update tally counter */
+                ++s->tally_counters.RxERR;
+
                 return;
             }
 
             packet_header |= RxBroadcast;
 
-#if defined(DEBUG_RTL8139)
-            printf(">>> RTL8139: broadcast packet received\n");
-#endif
+            DEBUG_PRINT((">>> RTL8139: broadcast packet received\n"));
+
+            /* update tally counter */
+            ++s->tally_counters.RxOkBrd;
+
         } else if (buf[0] & 0x01) {
             /* multicast */
             if (!(s->RxConfig & AcceptMulticast))
             {
-#if defined(DEBUG_RTL8139)
-                printf(">>> RTL8139: multicast packet rejected\n");
-#endif
+                DEBUG_PRINT((">>> RTL8139: multicast packet rejected\n"));
+
+                /* update tally counter */
+                ++s->tally_counters.RxERR;
+
                 return;
             }
 
@@ -821,17 +882,21 @@ static void rtl8139_receive(void *opaque
 
             if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
             {
-#if defined(DEBUG_RTL8139)
-                printf(">>> RTL8139: multicast address mismatch\n");
-#endif
+                DEBUG_PRINT((">>> RTL8139: multicast address mismatch\n"));
+
+                /* update tally counter */
+                ++s->tally_counters.RxERR;
+
                 return;
             }
 
             packet_header |= RxMulticast;
 
-#if defined(DEBUG_RTL8139)
-            printf(">>> RTL8139: multicast packet received\n");
-#endif
+            DEBUG_PRINT((">>> RTL8139: multicast packet received\n"));
+
+            /* update tally counter */
+            ++s->tally_counters.RxOkMul;
+
         } else if (s->phys[0] == buf[0] &&
                    s->phys[1] == buf[1] &&                   
                    s->phys[2] == buf[2] &&            
@@ -841,23 +906,28 @@ static void rtl8139_receive(void *opaque
             /* match */
             if (!(s->RxConfig & AcceptMyPhys))
             {
-#if defined(DEBUG_RTL8139)
-                printf(">>> RTL8139: rejecting physical address matching 
packet\n");
-#endif
+                DEBUG_PRINT((">>> RTL8139: rejecting physical address matching 
packet\n"));
+
+                /* update tally counter */
+                ++s->tally_counters.RxERR;
+
                 return;
             }
 
             packet_header |= RxPhysical;
 
-#if defined(DEBUG_RTL8139)
-            printf(">>> RTL8139: physical address matching packet received\n");
-#endif
+            DEBUG_PRINT((">>> RTL8139: physical address matching packet 
received\n"));
+
+            /* update tally counter */
+            ++s->tally_counters.RxOkPhy;
 
         } else {
 
-#if defined(DEBUG_RTL8139)
-                printf(">>> RTL8139: unknown packet\n");
-#endif
+            DEBUG_PRINT((">>> RTL8139: unknown packet\n"));
+
+            /* update tally counter */
+            ++s->tally_counters.RxERR;
+
             return;
         }
     }
@@ -872,9 +942,7 @@ static void rtl8139_receive(void *opaque
 
     if (rtl8139_cp_receiver_enabled(s))
     {
-#if defined(DEBUG_RTL8139)
-        printf("RTL8139: in C+ Rx mode ================\n");
-#endif
+        DEBUG_PRINT(("RTL8139: in C+ Rx mode ================\n"));
 
         /* begin C+ receiver mode */
 
@@ -897,10 +965,8 @@ static void rtl8139_receive(void *opaque
         cplus_rx_ring_desc = rtl8139_addr64(s->RxRingAddrLO, s->RxRingAddrHI);
         cplus_rx_ring_desc += 16 * descriptor;
 
-#ifdef DEBUG_RTL8139
-        printf("RTL8139: +++ C+ mode reading RX descriptor %d from host memory 
at %08x %08x = 0x%8lx\n",
-               descriptor, s->RxRingAddrHI, s->RxRingAddrLO, 
cplus_rx_ring_desc);
-#endif
+        DEBUG_PRINT(("RTL8139: +++ C+ mode reading RX descriptor %d from host 
memory at %08x %08x = %016" PRIx64 "\n",
+               descriptor, s->RxRingAddrHI, s->RxRingAddrLO, 
(uint64_t)cplus_rx_ring_desc));
 
         uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI;
 
@@ -913,33 +979,41 @@ static void rtl8139_receive(void *opaque
         cpu_physical_memory_read(cplus_rx_ring_desc+12, (uint8_t *)&val, 4);
         rxbufHI = le32_to_cpu(val);
 
-#ifdef DEBUG_RTL8139
-        printf("RTL8139: +++ C+ mode RX descriptor %d %08x %08x %08x %08x\n",
+        DEBUG_PRINT(("RTL8139: +++ C+ mode RX descriptor %d %08x %08x %08x 
%08x\n",
                descriptor,
-               rxdw0, rxdw1, rxbufLO, rxbufHI);
-#endif
+               rxdw0, rxdw1, rxbufLO, rxbufHI));
 
         if (!(rxdw0 & CP_RX_OWN))
         {
-#if defined(DEBUG_RTL8139)
-            printf("RTL8139: C+ Rx mode : descriptor %d is owned by host\n", 
descriptor);
-#endif
+            DEBUG_PRINT(("RTL8139: C+ Rx mode : descriptor %d is owned by 
host\n", descriptor));
+
             s->IntrStatus |= RxOverflow;
             ++s->RxMissed;
+
+            /* update tally counter */
+            ++s->tally_counters.RxERR;
+            ++s->tally_counters.MissPkt;
+
             rtl8139_update_irq(s);
             return;
         }
 
         uint32_t rx_space = rxdw0 & CP_RX_BUFFER_SIZE_MASK;
 
+        /* TODO: scatter the packet over available receive ring descriptors 
space */
+
         if (size+4 > rx_space)
         {
-#if defined(DEBUG_RTL8139)
-            printf("RTL8139: C+ Rx mode : descriptor %d size %d received %d + 
4\n",
-                   descriptor, rx_space, size);
-#endif
+            DEBUG_PRINT(("RTL8139: C+ Rx mode : descriptor %d size %d received 
%d + 4\n",
+                   descriptor, rx_space, size));
+
             s->IntrStatus |= RxOverflow;
             ++s->RxMissed;
+
+            /* update tally counter */
+            ++s->tally_counters.RxERR;
+            ++s->tally_counters.MissPkt;
+
             rtl8139_update_irq(s);
             return;
         }
@@ -948,6 +1022,11 @@ static void rtl8139_receive(void *opaque
 
         /* receive/copy to target memory */
         cpu_physical_memory_write( rx_addr, buf, size );
+
+        if (s->CpCmd & CPlusRxChkSum)
+        {
+            /* do some packet checksumming */
+        }
 
         /* write checksum */
 #if defined (RTL8139_CALCULATE_RXCRC)
@@ -1008,6 +1087,9 @@ static void rtl8139_receive(void *opaque
         val = cpu_to_le32(rxdw1);
         cpu_physical_memory_write(cplus_rx_ring_desc+4,  (uint8_t *)&val, 4);
 
+        /* update tally counter */
+        ++s->tally_counters.RxOk;
+
         /* seek to next Rx descriptor */
         if (rxdw0 & CP_RX_EOR)
         {
@@ -1018,16 +1100,13 @@ static void rtl8139_receive(void *opaque
             ++s->currCPlusRxDesc;
         }
 
-#if defined(DEBUG_RTL8139)
-        printf("RTL8139: done C+ Rx mode ----------------\n");
-#endif
+        DEBUG_PRINT(("RTL8139: done C+ Rx mode ----------------\n"));
 
     }
     else
     {
-#if defined(DEBUG_RTL8139)
-        printf("RTL8139: in ring Rx mode ================\n");
-#endif
+        DEBUG_PRINT(("RTL8139: in ring Rx mode ================\n"));
+
         /* begin ring receiver mode */
         int avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, 
s->RxBufferSize);
 
@@ -1035,10 +1114,9 @@ static void rtl8139_receive(void *opaque
 
         if (avail != 0 && size + 8 >= avail)
         {
-#if defined(DEBUG_RTL8139)
-            printf("rx overflow: rx buffer length %d head 0x%04x read 0x%04x 
=== available 0x%04x need 0x%04x\n",
-                   s->RxBufferSize, s->RxBufAddr, s->RxBufPtr, avail, size + 
8);
-#endif
+            DEBUG_PRINT(("rx overflow: rx buffer length %d head 0x%04x read 
0x%04x === available 0x%04x need 0x%04x\n",
+                   s->RxBufferSize, s->RxBufAddr, s->RxBufPtr, avail, size + 
8));
+
             s->IntrStatus |= RxOverflow;
             ++s->RxMissed;
             rtl8139_update_irq(s);
@@ -1070,15 +1148,21 @@ static void rtl8139_receive(void *opaque
 
         /* now we can signal we have received something */
 
-#if defined(DEBUG_RTL8139)
-        printf("   received: rx buffer length %d head 0x%04x read 0x%04x\n",
-               s->RxBufferSize, s->RxBufAddr, s->RxBufPtr);
-#endif
-
+        DEBUG_PRINT(("   received: rx buffer length %d head 0x%04x read 
0x%04x\n",
+               s->RxBufferSize, s->RxBufAddr, s->RxBufPtr));
     }
 
     s->IntrStatus |= RxOK;
-    rtl8139_update_irq(s);
+
+    if (do_interrupt)
+    {
+        rtl8139_update_irq(s);
+    }
+}
+
+static void rtl8139_receive(void *opaque, const uint8_t *buf, int size)
+{
+    rtl8139_do_receive(opaque, buf, size, 1);
 }
 
 static void rtl8139_reset_rxring(RTL8139State *s, uint32_t bufferSize)
@@ -1103,6 +1187,11 @@ static void rtl8139_reset(RTL8139State *
 
     /* prepare eeprom */
     s->eeprom.contents[0] = 0x8129;
+#if 1
+    // PCI vendor and device ID should be mirrored here
+    s->eeprom.contents[1] = 0x10ec;
+    s->eeprom.contents[2] = 0x8139;
+#endif
     memcpy(&s->eeprom.contents[7], s->macaddr, 6);
 
     /* mark all status registers as owned by host */
@@ -1129,7 +1218,7 @@ static void rtl8139_reset(RTL8139State *
 //    s->TxConfig |= HW_REVID(1, 0, 0, 0, 0, 0, 0); // RTL-8139  HasHltClk
     s->clock_enabled = 0;
 #else
-    s->TxConfig |= HW_REVID(1, 1, 1, 0, 1, 0, 0); // RTL-8139C HasLWake
+    s->TxConfig |= HW_REVID(1, 1, 1, 0, 1, 1, 0); // RTL-8139C+ HasLWake
     s->clock_enabled = 1;
 #endif
 
@@ -1157,34 +1246,137 @@ static void rtl8139_reset(RTL8139State *
     s->NWayAdvert    = 0x05e1; /* all modes, full duplex */
     s->NWayLPAR      = 0x05e1; /* all modes, full duplex */
     s->NWayExpansion = 0x0001; /* autonegotiation supported */
+
+    /* also reset timer and disable timer interrupt */
+    s->TCTR = 0;
+    s->TimerInt = 0;
+    s->TCTR_base = 0;
+
+    /* reset tally counters */
+    RTL8139TallyCounters_clear(&s->tally_counters);
+}
+
+void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters)
+{
+    counters->TxOk = 0;
+    counters->RxOk = 0;
+    counters->TxERR = 0;
+    counters->RxERR = 0;
+    counters->MissPkt = 0;
+    counters->FAE = 0;
+    counters->Tx1Col = 0;
+    counters->TxMCol = 0;
+    counters->RxOkPhy = 0;
+    counters->RxOkBrd = 0;
+    counters->RxOkMul = 0;
+    counters->TxAbt = 0;
+    counters->TxUndrn = 0;
+}
+
+static void RTL8139TallyCounters_physical_memory_write(target_phys_addr_t 
tc_addr, RTL8139TallyCounters* tally_counters)
+{
+    uint16_t val16;
+    uint32_t val32;
+    uint64_t val64;
+
+    val64 = cpu_to_le64(tally_counters->TxOk);
+    cpu_physical_memory_write(tc_addr + 0,    (uint8_t *)&val64, 8);
+
+    val64 = cpu_to_le64(tally_counters->RxOk);
+    cpu_physical_memory_write(tc_addr + 8,    (uint8_t *)&val64, 8);
+
+    val64 = cpu_to_le64(tally_counters->TxERR);
+    cpu_physical_memory_write(tc_addr + 16,    (uint8_t *)&val64, 8);
+
+    val32 = cpu_to_le32(tally_counters->RxERR);
+    cpu_physical_memory_write(tc_addr + 24,    (uint8_t *)&val32, 4);
+
+    val16 = cpu_to_le16(tally_counters->MissPkt);
+    cpu_physical_memory_write(tc_addr + 28,    (uint8_t *)&val16, 2);
+
+    val16 = cpu_to_le16(tally_counters->FAE);
+    cpu_physical_memory_write(tc_addr + 30,    (uint8_t *)&val16, 2);
+
+    val32 = cpu_to_le32(tally_counters->Tx1Col);
+    cpu_physical_memory_write(tc_addr + 32,    (uint8_t *)&val32, 4);
+
+    val32 = cpu_to_le32(tally_counters->TxMCol);
+    cpu_physical_memory_write(tc_addr + 36,    (uint8_t *)&val32, 4);
+
+    val64 = cpu_to_le64(tally_counters->RxOkPhy);
+    cpu_physical_memory_write(tc_addr + 40,    (uint8_t *)&val64, 8);
+
+    val64 = cpu_to_le64(tally_counters->RxOkBrd);
+    cpu_physical_memory_write(tc_addr + 48,    (uint8_t *)&val64, 8);
+
+    val32 = cpu_to_le32(tally_counters->RxOkMul);
+    cpu_physical_memory_write(tc_addr + 56,    (uint8_t *)&val32, 4);
+
+    val16 = cpu_to_le16(tally_counters->TxAbt);
+    cpu_physical_memory_write(tc_addr + 60,    (uint8_t *)&val16, 2);
+
+    val16 = cpu_to_le16(tally_counters->TxUndrn);
+    cpu_physical_memory_write(tc_addr + 62,    (uint8_t *)&val16, 2);
+}
+
+/* Loads values of tally counters from VM state file */
+static void RTL8139TallyCounters_load(QEMUFile* f, RTL8139TallyCounters 
*tally_counters)
+{
+    qemu_get_be64s(f, &tally_counters->TxOk);
+    qemu_get_be64s(f, &tally_counters->RxOk);
+    qemu_get_be64s(f, &tally_counters->TxERR);
+    qemu_get_be32s(f, &tally_counters->RxERR);
+    qemu_get_be16s(f, &tally_counters->MissPkt);
+    qemu_get_be16s(f, &tally_counters->FAE);
+    qemu_get_be32s(f, &tally_counters->Tx1Col);
+    qemu_get_be32s(f, &tally_counters->TxMCol);
+    qemu_get_be64s(f, &tally_counters->RxOkPhy);
+    qemu_get_be64s(f, &tally_counters->RxOkBrd);
+    qemu_get_be32s(f, &tally_counters->RxOkMul);
+    qemu_get_be16s(f, &tally_counters->TxAbt);
+    qemu_get_be16s(f, &tally_counters->TxUndrn);
+}
+
+/* Saves values of tally counters to VM state file */
+static void RTL8139TallyCounters_save(QEMUFile* f, RTL8139TallyCounters 
*tally_counters)
+{
+    qemu_put_be64s(f, &tally_counters->TxOk);
+    qemu_put_be64s(f, &tally_counters->RxOk);
+    qemu_put_be64s(f, &tally_counters->TxERR);
+    qemu_put_be32s(f, &tally_counters->RxERR);
+    qemu_put_be16s(f, &tally_counters->MissPkt);
+    qemu_put_be16s(f, &tally_counters->FAE);
+    qemu_put_be32s(f, &tally_counters->Tx1Col);
+    qemu_put_be32s(f, &tally_counters->TxMCol);
+    qemu_put_be64s(f, &tally_counters->RxOkPhy);
+    qemu_put_be64s(f, &tally_counters->RxOkBrd);
+    qemu_put_be32s(f, &tally_counters->RxOkMul);
+    qemu_put_be16s(f, &tally_counters->TxAbt);
+    qemu_put_be16s(f, &tally_counters->TxUndrn);
 }
 
 static void rtl8139_ChipCmd_write(RTL8139State *s, uint32_t val)
 {
     val &= 0xff;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: ChipCmd write val=0x%08x\n", val);
-#endif
+    DEBUG_PRINT(("RTL8139: ChipCmd write val=0x%08x\n", val));
 
     if (val & CmdReset)
     {
-#ifdef DEBUG_RTL8139
-        printf("RTL8139: ChipCmd reset\n");
-#endif
+        DEBUG_PRINT(("RTL8139: ChipCmd reset\n"));
         rtl8139_reset(s);
     }
     if (val & CmdRxEnb)
     {
-#ifdef DEBUG_RTL8139
-        printf("RTL8139: ChipCmd enable receiver\n");
-#endif
+        DEBUG_PRINT(("RTL8139: ChipCmd enable receiver\n"));
+
+        s->currCPlusRxDesc = 0;
     }
     if (val & CmdTxEnb)
     {
-#ifdef DEBUG_RTL8139
-        printf("RTL8139: ChipCmd enable transmitter\n");
-#endif
+        DEBUG_PRINT(("RTL8139: ChipCmd enable transmitter\n"));
+
+        s->currCPlusTxDesc = 0;
     }
 
     /* mask unwriteable bits */
@@ -1202,15 +1394,11 @@ static int rtl8139_RxBufferEmpty(RTL8139
 
     if (unread != 0)
     {
-#ifdef DEBUG_RTL8139
-        printf("RTL8139: receiver buffer data available 0x%04x\n", unread);
-#endif
+        DEBUG_PRINT(("RTL8139: receiver buffer data available 0x%04x\n", 
unread));
         return 0;
     }
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: receiver buffer is empty\n");
-#endif
+    DEBUG_PRINT(("RTL8139: receiver buffer is empty\n"));
 
     return 1;
 }
@@ -1222,9 +1410,7 @@ static uint32_t rtl8139_ChipCmd_read(RTL
     if (rtl8139_RxBufferEmpty(s))
         ret |= RxBufEmpty;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: ChipCmd read val=0x%04x\n", ret);
-#endif
+    DEBUG_PRINT(("RTL8139: ChipCmd read val=0x%04x\n", ret));
 
     return ret;
 }
@@ -1233,9 +1419,7 @@ static void rtl8139_CpCmd_write(RTL8139S
 {
     val &= 0xffff;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139C+ command register write(w) val=0x%04x\n", val);
-#endif
+    DEBUG_PRINT(("RTL8139C+ command register write(w) val=0x%04x\n", val));
 
     /* mask unwriteable bits */
     val = SET_MASKED(val, 0xff84, s->CpCmd);
@@ -1247,13 +1431,25 @@ static uint32_t rtl8139_CpCmd_read(RTL81
 {
     uint32_t ret = s->CpCmd;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139C+ command register read(w) val=0x%04x\n", ret);
-#endif
+    DEBUG_PRINT(("RTL8139C+ command register read(w) val=0x%04x\n", ret));
 
     return ret;
 }
 
+static void rtl8139_IntrMitigate_write(RTL8139State *s, uint32_t val)
+{
+    DEBUG_PRINT(("RTL8139C+ IntrMitigate register write(w) val=0x%04x\n", 
val));
+}
+
+static uint32_t rtl8139_IntrMitigate_read(RTL8139State *s)
+{
+    uint32_t ret = 0;
+
+    DEBUG_PRINT(("RTL8139C+ IntrMitigate register read(w) val=0x%04x\n", ret));
+
+    return ret;
+}
+
 int rtl8139_config_writeable(RTL8139State *s)
 {
     if (s->Cfg9346 & Cfg9346_Unlock)
@@ -1261,9 +1457,7 @@ int rtl8139_config_writeable(RTL8139Stat
         return 1;
     }
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: Configuration registers are write-protected\n");
-#endif
+    DEBUG_PRINT(("RTL8139: Configuration registers are write-protected\n"));
 
     return 0;
 }
@@ -1272,9 +1466,7 @@ static void rtl8139_BasicModeCtrl_write(
 {
     val &= 0xffff;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: BasicModeCtrl register write(w) val=0x%04x\n", val);
-#endif
+    DEBUG_PRINT(("RTL8139: BasicModeCtrl register write(w) val=0x%04x\n", 
val));
 
     /* mask unwriteable bits */
     uint32 mask = 0x4cff;
@@ -1296,9 +1488,7 @@ static uint32_t rtl8139_BasicModeCtrl_re
 {
     uint32_t ret = s->BasicModeCtrl;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: BasicModeCtrl register read(w) val=0x%04x\n", ret);
-#endif
+    DEBUG_PRINT(("RTL8139: BasicModeCtrl register read(w) val=0x%04x\n", ret));
 
     return ret;
 }
@@ -1307,9 +1497,7 @@ static void rtl8139_BasicModeStatus_writ
 {
     val &= 0xffff;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: BasicModeStatus register write(w) val=0x%04x\n", val);
-#endif
+    DEBUG_PRINT(("RTL8139: BasicModeStatus register write(w) val=0x%04x\n", 
val));
 
     /* mask unwriteable bits */
     val = SET_MASKED(val, 0xff3f, s->BasicModeStatus);
@@ -1321,9 +1509,7 @@ static uint32_t rtl8139_BasicModeStatus_
 {
     uint32_t ret = s->BasicModeStatus;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: BasicModeStatus register read(w) val=0x%04x\n", ret);
-#endif
+    DEBUG_PRINT(("RTL8139: BasicModeStatus register read(w) val=0x%04x\n", 
ret));
 
     return ret;
 }
@@ -1332,9 +1518,7 @@ static void rtl8139_Cfg9346_write(RTL813
 {
     val &= 0xff;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: Cfg9346 write val=0x%02x\n", val);
-#endif
+    DEBUG_PRINT(("RTL8139: Cfg9346 write val=0x%02x\n", val));
 
     /* mask unwriteable bits */
     val = SET_MASKED(val, 0x31, s->Cfg9346);
@@ -1377,9 +1561,7 @@ static uint32_t rtl8139_Cfg9346_read(RTL
         }
     }
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: Cfg9346 read val=0x%02x\n", ret);
-#endif
+    DEBUG_PRINT(("RTL8139: Cfg9346 read val=0x%02x\n", ret));
 
     return ret;
 }
@@ -1388,9 +1570,7 @@ static void rtl8139_Config0_write(RTL813
 {
     val &= 0xff;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: Config0 write val=0x%02x\n", val);
-#endif
+    DEBUG_PRINT(("RTL8139: Config0 write val=0x%02x\n", val));
 
     if (!rtl8139_config_writeable(s))
         return;
@@ -1405,9 +1585,7 @@ static uint32_t rtl8139_Config0_read(RTL
 {
     uint32_t ret = s->Config0;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: Config0 read val=0x%02x\n", ret);
-#endif
+    DEBUG_PRINT(("RTL8139: Config0 read val=0x%02x\n", ret));
 
     return ret;
 }
@@ -1416,9 +1594,7 @@ static void rtl8139_Config1_write(RTL813
 {
     val &= 0xff;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: Config1 write val=0x%02x\n", val);
-#endif
+    DEBUG_PRINT(("RTL8139: Config1 write val=0x%02x\n", val));
 
     if (!rtl8139_config_writeable(s))
         return;
@@ -1433,9 +1609,7 @@ static uint32_t rtl8139_Config1_read(RTL
 {
     uint32_t ret = s->Config1;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: Config1 read val=0x%02x\n", ret);
-#endif
+    DEBUG_PRINT(("RTL8139: Config1 read val=0x%02x\n", ret));
 
     return ret;
 }
@@ -1444,9 +1618,7 @@ static void rtl8139_Config3_write(RTL813
 {
     val &= 0xff;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: Config3 write val=0x%02x\n", val);
-#endif
+    DEBUG_PRINT(("RTL8139: Config3 write val=0x%02x\n", val));
 
     if (!rtl8139_config_writeable(s))
         return;
@@ -1461,9 +1633,7 @@ static uint32_t rtl8139_Config3_read(RTL
 {
     uint32_t ret = s->Config3;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: Config3 read val=0x%02x\n", ret);
-#endif
+    DEBUG_PRINT(("RTL8139: Config3 read val=0x%02x\n", ret));
 
     return ret;
 }
@@ -1472,9 +1642,7 @@ static void rtl8139_Config4_write(RTL813
 {
     val &= 0xff;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: Config4 write val=0x%02x\n", val);
-#endif
+    DEBUG_PRINT(("RTL8139: Config4 write val=0x%02x\n", val));
 
     if (!rtl8139_config_writeable(s))
         return;
@@ -1489,9 +1657,7 @@ static uint32_t rtl8139_Config4_read(RTL
 {
     uint32_t ret = s->Config4;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: Config4 read val=0x%02x\n", ret);
-#endif
+    DEBUG_PRINT(("RTL8139: Config4 read val=0x%02x\n", ret));
 
     return ret;
 }
@@ -1500,9 +1666,7 @@ static void rtl8139_Config5_write(RTL813
 {
     val &= 0xff;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: Config5 write val=0x%02x\n", val);
-#endif
+    DEBUG_PRINT(("RTL8139: Config5 write val=0x%02x\n", val));
 
     /* mask unwriteable bits */
     val = SET_MASKED(val, 0x80, s->Config5);
@@ -1514,9 +1678,7 @@ static uint32_t rtl8139_Config5_read(RTL
 {
     uint32_t ret = s->Config5;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: Config5 read val=0x%02x\n", ret);
-#endif
+    DEBUG_PRINT(("RTL8139: Config5 read val=0x%02x\n", ret));
 
     return ret;
 }
@@ -1525,15 +1687,11 @@ static void rtl8139_TxConfig_write(RTL81
 {
     if (!rtl8139_transmitter_enabled(s))
     {
-#ifdef DEBUG_RTL8139
-        printf("RTL8139: transmitter disabled; no TxConfig write 
val=0x%08x\n", val);
-#endif
+        DEBUG_PRINT(("RTL8139: transmitter disabled; no TxConfig write 
val=0x%08x\n", val));
         return;
     }
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: TxConfig write val=0x%08x\n", val);
-#endif
+    DEBUG_PRINT(("RTL8139: TxConfig write val=0x%08x\n", val));
 
     val = SET_MASKED(val, TxVersionMask | 0x8070f80f, s->TxConfig);
 
@@ -1542,31 +1700,26 @@ static void rtl8139_TxConfig_write(RTL81
 
 static void rtl8139_TxConfig_writeb(RTL8139State *s, uint32_t val)
 {
-#ifdef DEBUG_RTL8139
-                printf("RTL8139C TxConfig via write(b) val=0x%02x\n", val);
-#endif
-            uint32_t tc = s->TxConfig;
-            tc &= 0xFFFFFF00;
-            tc |= (val & 0x000000FF);
-            rtl8139_TxConfig_write(s, tc);
+    DEBUG_PRINT(("RTL8139C TxConfig via write(b) val=0x%02x\n", val));
+
+    uint32_t tc = s->TxConfig;
+    tc &= 0xFFFFFF00;
+    tc |= (val & 0x000000FF);
+    rtl8139_TxConfig_write(s, tc);
 }
 
 static uint32_t rtl8139_TxConfig_read(RTL8139State *s)
 {
     uint32_t ret = s->TxConfig;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: TxConfig read val=0x%04x\n", ret);
-#endif
+    DEBUG_PRINT(("RTL8139: TxConfig read val=0x%04x\n", ret));
 
     return ret;
 }
 
 static void rtl8139_RxConfig_write(RTL8139State *s, uint32_t val)
 {
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: RxConfig write val=0x%08x\n", val);
-#endif
+    DEBUG_PRINT(("RTL8139: RxConfig write val=0x%08x\n", val));
 
     /* mask unwriteable bits */
     val = SET_MASKED(val, 0xf0fc0040, s->RxConfig);
@@ -1576,61 +1729,70 @@ static void rtl8139_RxConfig_write(RTL81
     /* reset buffer size and read/write pointers */
     rtl8139_reset_rxring(s, 8192 << ((s->RxConfig >> 11) & 0x3));
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: RxConfig write reset buffer size to %d\n", 
s->RxBufferSize);
-#endif
+    DEBUG_PRINT(("RTL8139: RxConfig write reset buffer size to %d\n", 
s->RxBufferSize));
 }
 
 static uint32_t rtl8139_RxConfig_read(RTL8139State *s)
 {
     uint32_t ret = s->RxConfig;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: RxConfig read val=0x%08x\n", ret);
-#endif
+    DEBUG_PRINT(("RTL8139: RxConfig read val=0x%08x\n", ret));
 
     return ret;
 }
 
+static void rtl8139_transfer_frame(RTL8139State *s, const uint8_t *buf, int 
size, int do_interrupt)
+{
+    if (!size)
+    {
+        DEBUG_PRINT(("RTL8139: +++ empty ethernet frame\n"));
+        return;
+    }
+
+    if (TxLoopBack == (s->TxConfig & TxLoopBack))
+    {
+        DEBUG_PRINT(("RTL8139: +++ transmit loopback mode\n"));
+        rtl8139_do_receive(s, buf, size, do_interrupt);
+    }
+    else
+    {
+        qemu_send_packet(s->vc, buf, size);
+    }
+}
+
 static int rtl8139_transmit_one(RTL8139State *s, int descriptor)
 {
     if (!rtl8139_transmitter_enabled(s))
     {
-#ifdef DEBUG_RTL8139
-        printf("RTL8139: +++ cannot transmit from descriptor %d: transmitter 
disabled\n", descriptor);
-#endif
+        DEBUG_PRINT(("RTL8139: +++ cannot transmit from descriptor %d: 
transmitter disabled\n",
+                     descriptor));
         return 0;
     }
 
     if (s->TxStatus[descriptor] & TxHostOwns)
     {
-#ifdef DEBUG_RTL8139
-        printf("RTL8139: +++ cannot transmit from descriptor %d: owned by host 
(%08x)\n", descriptor, s->TxStatus[descriptor]);
-#endif
+        DEBUG_PRINT(("RTL8139: +++ cannot transmit from descriptor %d: owned 
by host (%08x)\n",
+                     descriptor, s->TxStatus[descriptor]));
         return 0;
     }
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: +++ transmitting from descriptor %d\n", descriptor);
-#endif
+    DEBUG_PRINT(("RTL8139: +++ transmitting from descriptor %d\n", 
descriptor));
 
     int txsize = s->TxStatus[descriptor] & 0x1fff;
     uint8_t txbuffer[0x2000];
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: +++ transmit reading %d bytes from host memory at 
0x%08x\n", txsize, s->TxAddr[descriptor]);
-#endif
+    DEBUG_PRINT(("RTL8139: +++ transmit reading %d bytes from host memory at 
0x%08x\n",
+                 txsize, s->TxAddr[descriptor]));
+
     cpu_physical_memory_read(s->TxAddr[descriptor], txbuffer, txsize);
-
-    qemu_send_packet(s->vc, txbuffer, txsize);
 
     /* Mark descriptor as transferred */
     s->TxStatus[descriptor] |= TxHostOwns;
     s->TxStatus[descriptor] |= TxStatOK;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: +++ transmitted %d bytes from descriptor %d\n", txsize, 
descriptor);
-#endif
+    rtl8139_transfer_frame(s, txbuffer, txsize, 0);
+
+    DEBUG_PRINT(("RTL8139: +++ transmitted %d bytes from descriptor %d\n", 
txsize, descriptor));
 
     /* update interrupt */
     s->IntrStatus |= TxOK;
@@ -1639,21 +1801,104 @@ static int rtl8139_transmit_one(RTL8139S
     return 1;
 }
 
+/* structures and macros for task offloading */
+typedef struct ip_header
+{
+    uint8_t  ip_ver_len;    /* version and header length */
+    uint8_t  ip_tos;        /* type of service */
+    uint16_t ip_len;        /* total length */
+    uint16_t ip_id;         /* identification */
+    uint16_t ip_off;        /* fragment offset field */
+    uint8_t  ip_ttl;        /* time to live */
+    uint8_t  ip_p;          /* protocol */
+    uint16_t ip_sum;        /* checksum */
+    uint32_t ip_src,ip_dst; /* source and dest address */
+} ip_header;
+
+#define IP_HEADER_VERSION_4 4
+#define IP_HEADER_VERSION(ip) ((ip->ip_ver_len >> 4)&0xf)
+#define IP_HEADER_LENGTH(ip) (((ip->ip_ver_len)&0xf) << 2)
+
+typedef struct tcp_header
+{
+    uint16_t th_sport;         /* source port */
+    uint16_t th_dport;         /* destination port */
+    uint32_t th_seq;                   /* sequence number */
+    uint32_t th_ack;                   /* acknowledgement number */
+    uint16_t th_offset_flags; /* data offset, reserved 6 bits, TCP protocol 
flags */
+    uint16_t th_win;                   /* window */
+    uint16_t th_sum;                   /* checksum */
+    uint16_t th_urp;                   /* urgent pointer */
+} tcp_header;
+
+typedef struct udp_header
+{
+    uint16_t uh_sport; /* source port */
+    uint16_t uh_dport; /* destination port */
+    uint16_t uh_ulen;  /* udp length */
+    uint16_t uh_sum;   /* udp checksum */
+} udp_header;
+
+typedef struct ip_pseudo_header
+{
+    uint32_t ip_src;
+    uint32_t ip_dst;
+    uint8_t  zeros;
+    uint8_t  ip_proto;
+    uint16_t ip_payload;
+} ip_pseudo_header;
+
+#define IP_PROTO_TCP 6
+#define IP_PROTO_UDP 17
+
+#define TCP_HEADER_DATA_OFFSET(tcp) (((be16_to_cpu(tcp->th_offset_flags) >> 
12)&0xf) << 2)
+#define TCP_FLAGS_ONLY(flags) ((flags)&0x3f)
+#define TCP_HEADER_FLAGS(tcp) TCP_FLAGS_ONLY(be16_to_cpu(tcp->th_offset_flags))
+
+#define TCP_HEADER_CLEAR_FLAGS(tcp, off) ((tcp)->th_offset_flags &= 
cpu_to_be16(~TCP_FLAGS_ONLY(off)))
+
+#define TCP_FLAG_FIN  0x01
+#define TCP_FLAG_PUSH 0x08
+
+/* produces ones' complement sum of data */
+static uint16_t ones_complement_sum(uint8_t *data, size_t len)
+{
+    uint32_t result = 0;
+
+    for (; len > 1; data+=2, len-=2)
+    {
+        result += *(uint16_t*)data;
+    }
+
+    /* add the remainder byte */
+    if (len)
+    {
+        uint8_t odd[2] = {*data, 0};
+        result += *(uint16_t*)odd;
+    }
+
+    while (result>>16)
+        result = (result & 0xffff) + (result >> 16);
+
+    return result;
+}
+
+static uint16_t ip_checksum(void *data, size_t len)
+{
+    return ~ones_complement_sum((uint8_t*)data, len);
+}
+
 static int rtl8139_cplus_transmit_one(RTL8139State *s)
 {
     if (!rtl8139_transmitter_enabled(s))
     {
-#ifdef DEBUG_RTL8139
-        printf("RTL8139: +++ C+ mode: transmitter disabled\n");
-#endif
+        DEBUG_PRINT(("RTL8139: +++ C+ mode: transmitter disabled\n"));
         return 0;
     }
 
     if (!rtl8139_cp_transmitter_enabled(s))
     {
-#ifdef DEBUG_RTL8139
-        printf("RTL8139: +++ C+ mode: C+ transmitter disabled\n");
-#endif
+        DEBUG_PRINT(("RTL8139: +++ C+ mode: C+ transmitter disabled\n"));
         return 0 ;
     }
 
@@ -1665,10 +1910,8 @@ static int rtl8139_cplus_transmit_one(RT
     /* Normal priority ring */
     cplus_tx_ring_desc += 16 * descriptor;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: +++ C+ mode reading TX descriptor %d from host memory at 
%08x0x%08x = 0x%8lx\n",
-           descriptor, s->TxAddr[1], s->TxAddr[0], cplus_tx_ring_desc);
-#endif
+    DEBUG_PRINT(("RTL8139: +++ C+ mode reading TX descriptor %d from host 
memory at %08x0x%08x = 0x%8lx\n",
+           descriptor, s->TxAddr[1], s->TxAddr[0], cplus_tx_ring_desc));
 
     uint32_t val, txdw0,txdw1,txbufLO,txbufHI;
 
@@ -1681,11 +1924,9 @@ static int rtl8139_cplus_transmit_one(RT
     cpu_physical_memory_read(cplus_tx_ring_desc+12, (uint8_t *)&val, 4);
     txbufHI = le32_to_cpu(val);
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: +++ C+ mode TX descriptor %d %08x %08x %08x %08x\n",
+    DEBUG_PRINT(("RTL8139: +++ C+ mode TX descriptor %d %08x %08x %08x %08x\n",
            descriptor,
-           txdw0, txdw1, txbufLO, txbufHI);
-#endif
+           txdw0, txdw1, txbufLO, txbufHI));
 
 /* w0 ownership flag */
 #define CP_TX_OWN (1<<31)
@@ -1697,6 +1938,9 @@ static int rtl8139_cplus_transmit_one(RT
 #define CP_TX_LS (1<<28)
 /* large send packet flag */
 #define CP_TX_LGSEN (1<<27)
+/* large send MSS mask, bits 16...25 */
+#define CP_TC_LGSEN_MSS_MASK ((1 << 12) - 1)
+
 /* IP checksum offload flag */
 #define CP_TX_IPCS (1<<18)
 /* UDP checksum offload flag */
@@ -1728,28 +1972,73 @@ static int rtl8139_cplus_transmit_one(RT
 
     if (!(txdw0 & CP_TX_OWN))
     {
-#if defined(DEBUG_RTL8139)
-        printf("RTL8139: C+ Tx mode : descriptor %d is owned by host\n", 
descriptor);
-#endif
+        DEBUG_PRINT(("RTL8139: C+ Tx mode : descriptor %d is owned by host\n", 
descriptor));
         return 0 ;
     }
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: +++ C+ Tx mode : transmitting from descriptor %d\n", 
descriptor);
-#endif
+    DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : transmitting from descriptor 
%d\n", descriptor));
+
+    if (txdw0 & CP_TX_FS)
+    {
+        DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : descriptor %d is first segment 
descriptor\n", descriptor));
+
+        /* reset internal buffer offset */
+        s->cplus_txbuffer_offset = 0;
+    }
 
     int txsize = txdw0 & CP_TX_BUFFER_SIZE_MASK;
     target_phys_addr_t tx_addr = rtl8139_addr64(txbufLO, txbufHI);
 
-    uint8_t txbuffer[CP_TX_BUFFER_SIZE];
-
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: +++ C+ mode transmit reading %d bytes from host memory at 
0x%08x\n", txsize, tx_addr);
-#endif
-    cpu_physical_memory_read(tx_addr, txbuffer, txsize);
-
-    /* transmit the packet */
-    qemu_send_packet(s->vc, txbuffer, txsize);
+    /* make sure we have enough space to assemble the packet */
+    if (!s->cplus_txbuffer)
+    {
+        s->cplus_txbuffer_len = CP_TX_BUFFER_SIZE;
+        s->cplus_txbuffer = malloc(s->cplus_txbuffer_len);
+        s->cplus_txbuffer_offset = 0;
+
+        DEBUG_PRINT(("RTL8139: +++ C+ mode transmission buffer allocated space 
%d\n", s->cplus_txbuffer_len));
+    }
+
+    while (s->cplus_txbuffer && s->cplus_txbuffer_offset + txsize >= 
s->cplus_txbuffer_len)
+    {
+        s->cplus_txbuffer_len += CP_TX_BUFFER_SIZE;
+        s->cplus_txbuffer = realloc(s->cplus_txbuffer, s->cplus_txbuffer_len);
+
+        DEBUG_PRINT(("RTL8139: +++ C+ mode transmission buffer space changed 
to %d\n", s->cplus_txbuffer_len));
+    }
+
+    if (!s->cplus_txbuffer)
+    {
+        /* out of memory */
+
+        DEBUG_PRINT(("RTL8139: +++ C+ mode transmiter failed to reallocate %d 
bytes\n", s->cplus_txbuffer_len));
+
+        /* update tally counter */
+        ++s->tally_counters.TxERR;
+        ++s->tally_counters.TxAbt;
+
+        return 0;
+    }
+
+    /* append more data to the packet */
+
+    DEBUG_PRINT(("RTL8139: +++ C+ mode transmit reading %d bytes from host 
memory at %016" PRIx64 " to offset %d\n",
+                 txsize, (uint64_t)tx_addr, s->cplus_txbuffer_offset));
+
+    cpu_physical_memory_read(tx_addr, s->cplus_txbuffer + 
s->cplus_txbuffer_offset, txsize);
+    s->cplus_txbuffer_offset += txsize;
+
+    /* seek to next Rx descriptor */
+    if (txdw0 & CP_TX_EOR)
+    {
+        s->currCPlusTxDesc = 0;
+    }
+    else
+    {
+        ++s->currCPlusTxDesc;
+        if (s->currCPlusTxDesc >= 64)
+            s->currCPlusTxDesc = 0;
+    }
 
     /* transfer ownership to target */
     txdw0 &= ~CP_RX_OWN;
@@ -1767,19 +2056,266 @@ static int rtl8139_cplus_transmit_one(RT
 //    val = cpu_to_le32(txdw1);
 //    cpu_physical_memory_write(cplus_tx_ring_desc+4,  &val, 4);
 
-    /* seek to next Rx descriptor */
-    if (txdw0 & CP_TX_EOR)
-    {
-        s->currCPlusTxDesc = 0;
+    /* Now decide if descriptor being processed is holding the last segment of 
packet */
+    if (txdw0 & CP_TX_LS)
+    {
+        DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : descriptor %d is last segment 
descriptor\n", descriptor));
+
+        /* can transfer fully assembled packet */
+
+        uint8_t *saved_buffer  = s->cplus_txbuffer;
+        int      saved_size    = s->cplus_txbuffer_offset;
+        int      saved_buffer_len = s->cplus_txbuffer_len;
+
+        /* reset the card space to protect from recursive call */
+        s->cplus_txbuffer = NULL;
+        s->cplus_txbuffer_offset = 0;
+        s->cplus_txbuffer_len = 0;
+
+        if (txdw0 & (CP_TX_IPCS | CP_TX_UDPCS | CP_TX_TCPCS | CP_TX_LGSEN))
+        {
+            DEBUG_PRINT(("RTL8139: +++ C+ mode offloaded task checksum\n"));
+
+            #define ETH_P_IP   0x0800          /* Internet Protocol packet     
*/
+            #define ETH_HLEN    14
+            #define ETH_MTU     1500
+
+            /* ip packet header */
+            ip_header *ip = 0;
+            int hlen = 0;
+            uint8_t  ip_protocol = 0;
+            uint16_t ip_data_len = 0;
+
+            uint8_t *eth_payload_data = 0;
+            size_t   eth_payload_len  = 0;
+
+            int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
+            if (proto == ETH_P_IP)
+            {
+                DEBUG_PRINT(("RTL8139: +++ C+ mode has IP packet\n"));
+
+                /* not aligned */
+                eth_payload_data = saved_buffer + ETH_HLEN;
+                eth_payload_len  = saved_size   - ETH_HLEN;
+
+                ip = (ip_header*)eth_payload_data;
+
+                if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
+                    DEBUG_PRINT(("RTL8139: +++ C+ mode packet has bad IP 
version %d expected %d\n", IP_HEADER_VERSION(ip), IP_HEADER_VERSION_4));
+                    ip = NULL;
+                } else {
+                    hlen = IP_HEADER_LENGTH(ip);
+                    ip_protocol = ip->ip_p;
+                    ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
+                }
+            }
+
+            if (ip)
+            {
+                if (txdw0 & CP_TX_IPCS)
+                {
+                    DEBUG_PRINT(("RTL8139: +++ C+ mode need IP checksum\n"));
+
+                    if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* 
min header length */
+                        /* bad packet header len */
+                        /* or packet too short */
+                    }
+                    else
+                    {
+                        ip->ip_sum = 0;
+                        ip->ip_sum = ip_checksum(ip, hlen);
+                        DEBUG_PRINT(("RTL8139: +++ C+ mode IP header len=%d 
checksum=%04x\n", hlen, ip->ip_sum));
+                    }
+                }
+
+                if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
+                {
+#if defined (DEBUG_RTL8139)
+                    int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
+#endif
+                    DEBUG_PRINT(("RTL8139: +++ C+ mode offloaded task TSO 
MTU=%d IP data %d frame data %d specified MSS=%d\n",
+                                 ETH_MTU, ip_data_len, saved_size - ETH_HLEN, 
large_send_mss));
+
+                    int tcp_send_offset = 0;
+                    int send_count = 0;
+
+                    /* maximum IP header length is 60 bytes */
+                    uint8_t saved_ip_header[60];
+
+                    /* save IP header template; data area is used in tcp 
checksum calculation */
+                    memcpy(saved_ip_header, eth_payload_data, hlen);
+
+                    /* a placeholder for checksum calculation routine in tcp 
case */
+                    uint8_t *data_to_checksum     = eth_payload_data + hlen - 
12;
+                    //                    size_t   data_to_checksum_len = 
eth_payload_len  - hlen + 12;
+
+                    /* pointer to TCP header */
+                    tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + 
hlen);
+
+                    int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
+
+                    /* ETH_MTU = ip header len + tcp header len + payload */
+                    int tcp_data_len = ip_data_len - tcp_hlen;
+                    int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
+
+                    DEBUG_PRINT(("RTL8139: +++ C+ mode TSO IP data len %d TCP 
hlen %d TCP data len %d TCP chunk size %d\n",
+                                 ip_data_len, tcp_hlen, tcp_data_len, 
tcp_chunk_size));
+
+                    /* note the cycle below overwrites IP header data,
+                       but restores it from saved_ip_header before sending 
packet */
+
+                    int is_last_frame = 0;
+
+                    for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; 
tcp_send_offset += tcp_chunk_size)
+                    {
+                        uint16_t chunk_size = tcp_chunk_size;
+
+                        /* check if this is the last frame */
+                        if (tcp_send_offset + tcp_chunk_size >= tcp_data_len)
+                        {
+                            is_last_frame = 1;
+                            chunk_size = tcp_data_len - tcp_send_offset;
+                        }
+
+                        DEBUG_PRINT(("RTL8139: +++ C+ mode TSO TCP seqno 
%08x\n", be32_to_cpu(p_tcp_hdr->th_seq)));
+
+                        /* add 4 TCP pseudoheader fields */
+                        /* copy IP source and destination fields */
+                        memcpy(data_to_checksum, saved_ip_header + 12, 8);
+
+                        DEBUG_PRINT(("RTL8139: +++ C+ mode TSO calculating TCP 
checksum for packet with %d bytes data\n", tcp_hlen + chunk_size));
+
+                        if (tcp_send_offset)
+                        {
+                            memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, 
(uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size);
+                        }
+
+                        /* keep PUSH and FIN flags only for the last frame */
+                        if (!is_last_frame)
+                        {
+                            TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, 
TCP_FLAG_PUSH|TCP_FLAG_FIN);
+                        }
+
+                        /* recalculate TCP checksum */
+                        ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header 
*)data_to_checksum;
+                        p_tcpip_hdr->zeros      = 0;
+                        p_tcpip_hdr->ip_proto   = IP_PROTO_TCP;
+                        p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + 
chunk_size);
+
+                        p_tcp_hdr->th_sum = 0;
+
+                        int tcp_checksum = ip_checksum(data_to_checksum, 
tcp_hlen + chunk_size + 12);
+                        DEBUG_PRINT(("RTL8139: +++ C+ mode TSO TCP checksum 
%04x\n", tcp_checksum));
+
+                        p_tcp_hdr->th_sum = tcp_checksum;
+
+                        /* restore IP header */
+                        memcpy(eth_payload_data, saved_ip_header, hlen);
+
+                        /* set IP data length and recalculate IP checksum */
+                        ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size);
+
+                        /* increment IP id for subsequent frames */
+                        ip->ip_id = cpu_to_be16(tcp_send_offset/tcp_chunk_size 
+ be16_to_cpu(ip->ip_id));
+
+                        ip->ip_sum = 0;
+                        ip->ip_sum = ip_checksum(eth_payload_data, hlen);
+                        DEBUG_PRINT(("RTL8139: +++ C+ mode TSO IP header 
len=%d checksum=%04x\n", hlen, ip->ip_sum));
+
+                        int tso_send_size = ETH_HLEN + hlen + tcp_hlen + 
chunk_size;
+                        DEBUG_PRINT(("RTL8139: +++ C+ mode TSO transferring 
packet size %d\n", tso_send_size));
+                        rtl8139_transfer_frame(s, saved_buffer, tso_send_size, 
0);
+
+                        /* add transferred count to TCP sequence number */
+                        p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + 
be32_to_cpu(p_tcp_hdr->th_seq));
+                        ++send_count;
+                    }
+
+                    /* Stop sending this frame */
+                    saved_size = 0;
+                }
+                else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))
+                {
+                    DEBUG_PRINT(("RTL8139: +++ C+ mode need TCP or UDP 
checksum\n"));
+
+                    /* maximum IP header length is 60 bytes */
+                    uint8_t saved_ip_header[60];
+                    memcpy(saved_ip_header, eth_payload_data, hlen);
+
+                    uint8_t *data_to_checksum     = eth_payload_data + hlen - 
12;
+                    //                    size_t   data_to_checksum_len = 
eth_payload_len  - hlen + 12;
+
+                    /* add 4 TCP pseudoheader fields */
+                    /* copy IP source and destination fields */
+                    memcpy(data_to_checksum, saved_ip_header + 12, 8);
+
+                    if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP)
+                    {
+                        DEBUG_PRINT(("RTL8139: +++ C+ mode calculating TCP 
checksum for packet with %d bytes data\n", ip_data_len));
+
+                        ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header 
*)data_to_checksum;
+                        p_tcpip_hdr->zeros      = 0;
+                        p_tcpip_hdr->ip_proto   = IP_PROTO_TCP;
+                        p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
+
+                        tcp_header* p_tcp_hdr = (tcp_header *) 
(data_to_checksum+12);
+
+                        p_tcp_hdr->th_sum = 0;
+
+                        int tcp_checksum = ip_checksum(data_to_checksum, 
ip_data_len + 12);
+                        DEBUG_PRINT(("RTL8139: +++ C+ mode TCP checksum 
%04x\n", tcp_checksum));
+
+                        p_tcp_hdr->th_sum = tcp_checksum;
+                    }
+                    else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == 
IP_PROTO_UDP)
+                    {
+                        DEBUG_PRINT(("RTL8139: +++ C+ mode calculating UDP 
checksum for packet with %d bytes data\n", ip_data_len));
+
+                        ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header 
*)data_to_checksum;
+                        p_udpip_hdr->zeros      = 0;
+                        p_udpip_hdr->ip_proto   = IP_PROTO_UDP;
+                        p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
+
+                        udp_header *p_udp_hdr = (udp_header *) 
(data_to_checksum+12);
+
+                        p_udp_hdr->uh_sum = 0;
+
+                        int udp_checksum = ip_checksum(data_to_checksum, 
ip_data_len + 12);
+                        DEBUG_PRINT(("RTL8139: +++ C+ mode UDP checksum 
%04x\n", udp_checksum));
+
+                        p_udp_hdr->uh_sum = udp_checksum;
+                    }
+
+                    /* restore IP header */
+                    memcpy(eth_payload_data, saved_ip_header, hlen);
+                }
+            }
+        }
+
+        /* update tally counter */
+        ++s->tally_counters.TxOk;
+
+        DEBUG_PRINT(("RTL8139: +++ C+ mode transmitting %d bytes packet\n", 
saved_size));
+
+        rtl8139_transfer_frame(s, saved_buffer, saved_size, 1);
+
+        /* restore card space if there was no recursion and reset offset */
+        if (!s->cplus_txbuffer)
+        {
+            s->cplus_txbuffer        = saved_buffer;
+            s->cplus_txbuffer_len    = saved_buffer_len;
+            s->cplus_txbuffer_offset = 0;
+        }
+        else
+        {
+            free(saved_buffer);
+        }
     }
     else
     {
-        ++s->currCPlusTxDesc;
-    }
-
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: +++ C+ mode transmitted %d bytes from descriptor %d\n", 
txsize, descriptor);
-#endif
+        DEBUG_PRINT(("RTL8139: +++ C+ mode transmission continue to next 
descriptor\n"));
+    }
+
     return 1;
 }
 
@@ -1795,9 +2331,8 @@ static void rtl8139_cplus_transmit(RTL81
     /* Mark transfer completed */
     if (!txcount)
     {
-#ifdef DEBUG_RTL8139
-        printf("RTL8139: C+ mode : transmitter queue stalled, current TxDesc = 
%d\n", s->currCPlusTxDesc);
-#endif
+        DEBUG_PRINT(("RTL8139: C+ mode : transmitter queue stalled, current 
TxDesc = %d\n",
+                     s->currCPlusTxDesc));
     }
     else
     {
@@ -1822,9 +2357,7 @@ static void rtl8139_transmit(RTL8139Stat
     /* Mark transfer completed */
     if (!txcount)
     {
-#ifdef DEBUG_RTL8139
-        printf("RTL8139: transmitter queue stalled, current TxDesc = %d\n", 
s->currTxDesc);
-#endif
+        DEBUG_PRINT(("RTL8139: transmitter queue stalled, current TxDesc = 
%d\n", s->currTxDesc));
     }
 }
 
@@ -1832,9 +2365,31 @@ static void rtl8139_TxStatus_write(RTL81
 {
 
     int descriptor = txRegOffset/4;
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: TxStatus write offset=0x%x val=0x%08x descriptor=%d\n", 
txRegOffset, val, descriptor);
-#endif
+
+    /* handle C+ transmit mode register configuration */
+
+    if (rtl8139_cp_transmitter_enabled(s))
+    {
+        DEBUG_PRINT(("RTL8139C+ DTCCR write offset=0x%x val=0x%08x 
descriptor=%d\n", txRegOffset, val, descriptor));
+
+        /* handle Dump Tally Counters command */
+        s->TxStatus[descriptor] = val;
+
+        if (descriptor == 0 && (val & 0x8))
+        {
+            target_phys_addr_t tc_addr = rtl8139_addr64(s->TxStatus[0] & 
~0x3f, s->TxStatus[1]);
+
+            /* dump tally counters to specified memory location */
+            RTL8139TallyCounters_physical_memory_write( tc_addr, 
&s->tally_counters);
+
+            /* mark dump completed */
+            s->TxStatus[0] &= ~0x8;
+        }
+
+        return;
+    }
+
+    DEBUG_PRINT(("RTL8139: TxStatus write offset=0x%x val=0x%08x 
descriptor=%d\n", txRegOffset, val, descriptor));
 
     /* mask only reserved bits */
     val &= ~0xff00c000; /* these bits are reset on write */
@@ -1850,9 +2405,7 @@ static uint32_t rtl8139_TxStatus_read(RT
 {
     uint32_t ret = s->TxStatus[txRegOffset/4];
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: TxStatus read offset=0x%x val=0x%08x\n", txRegOffset, 
ret);
-#endif
+    DEBUG_PRINT(("RTL8139: TxStatus read offset=0x%x val=0x%08x\n", 
txRegOffset, ret));
 
     return ret;
 }
@@ -1884,9 +2437,7 @@ static uint16_t rtl8139_TSAD_read(RTL813
          |((s->TxStatus[0] & TxHostOwns )?TSAD_OWN0:0) ;
        
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: TSAD read val=0x%04x\n", ret);
-#endif
+    DEBUG_PRINT(("RTL8139: TSAD read val=0x%04x\n", ret));
 
     return ret;
 }
@@ -1895,18 +2446,14 @@ static uint16_t rtl8139_CSCR_read(RTL813
 {
     uint16_t ret = s->CSCR;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: CSCR read val=0x%04x\n", ret);
-#endif
+    DEBUG_PRINT(("RTL8139: CSCR read val=0x%04x\n", ret));
 
     return ret;
 }
 
 static void rtl8139_TxAddr_write(RTL8139State *s, uint32_t txAddrOffset, 
uint32_t val)
 {
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: TxAddr write offset=0x%x val=0x%08x\n", txAddrOffset, 
val);
-#endif
+    DEBUG_PRINT(("RTL8139: TxAddr write offset=0x%x val=0x%08x\n", 
txAddrOffset, val));
 
     s->TxAddr[txAddrOffset/4] = le32_to_cpu(val);
 }
@@ -1915,26 +2462,20 @@ static uint32_t rtl8139_TxAddr_read(RTL8
 {
     uint32_t ret = cpu_to_le32(s->TxAddr[txAddrOffset/4]);
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: TxAddr read offset=0x%x val=0x%08x\n", txAddrOffset, ret);
-#endif
+    DEBUG_PRINT(("RTL8139: TxAddr read offset=0x%x val=0x%08x\n", 
txAddrOffset, ret));
 
     return ret;
 }
 
 static void rtl8139_RxBufPtr_write(RTL8139State *s, uint32_t val)
 {
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: RxBufPtr write val=0x%04x\n", val);
-#endif
+    DEBUG_PRINT(("RTL8139: RxBufPtr write val=0x%04x\n", val));
 
     /* this value is off by 16 */
     s->RxBufPtr = MOD2(val + 0x10, s->RxBufferSize);
 
-#if defined(DEBUG_RTL8139)
-    printf(" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n",
-           s->RxBufferSize, s->RxBufAddr, s->RxBufPtr);
-#endif
+    DEBUG_PRINT((" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n",
+           s->RxBufferSize, s->RxBufAddr, s->RxBufPtr));
 }
 
 static uint32_t rtl8139_RxBufPtr_read(RTL8139State *s)
@@ -1942,18 +2483,24 @@ static uint32_t rtl8139_RxBufPtr_read(RT
     /* this value is off by 16 */
     uint32_t ret = s->RxBufPtr - 0x10;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: RxBufPtr read val=0x%04x\n", ret);
-#endif
+    DEBUG_PRINT(("RTL8139: RxBufPtr read val=0x%04x\n", ret));
 
     return ret;
 }
 
+static uint32_t rtl8139_RxBufAddr_read(RTL8139State *s)
+{
+    /* this value is NOT off by 16 */
+    uint32_t ret = s->RxBufAddr;
+
+    DEBUG_PRINT(("RTL8139: RxBufAddr read val=0x%04x\n", ret));
+
+    return ret;
+}
+
 static void rtl8139_RxBuf_write(RTL8139State *s, uint32_t val)
 {
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: RxBuf write val=0x%08x\n", val);
-#endif
+    DEBUG_PRINT(("RTL8139: RxBuf write val=0x%08x\n", val));
 
     s->RxBuf = val;
 
@@ -1964,18 +2511,14 @@ static uint32_t rtl8139_RxBuf_read(RTL81
 {
     uint32_t ret = s->RxBuf;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: RxBuf read val=0x%08x\n", ret);
-#endif
+    DEBUG_PRINT(("RTL8139: RxBuf read val=0x%08x\n", ret));
 
     return ret;
 }
 
 static void rtl8139_IntrMask_write(RTL8139State *s, uint32_t val)
 {
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: IntrMask write(w) val=0x%04x\n", val);
-#endif
+    DEBUG_PRINT(("RTL8139: IntrMask write(w) val=0x%04x\n", val));
 
     /* mask unwriteable bits */
     val = SET_MASKED(val, 0x1e00, s->IntrMask);
@@ -1989,18 +2532,14 @@ static uint32_t rtl8139_IntrMask_read(RT
 {
     uint32_t ret = s->IntrMask;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: IntrMask read(w) val=0x%04x\n", ret);
-#endif
+    DEBUG_PRINT(("RTL8139: IntrMask read(w) val=0x%04x\n", ret));
 
     return ret;
 }
 
 static void rtl8139_IntrStatus_write(RTL8139State *s, uint32_t val)
 {
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: IntrStatus write(w) val=0x%04x\n", val);
-#endif
+    DEBUG_PRINT(("RTL8139: IntrStatus write(w) val=0x%04x\n", val));
 
 #if 0
 
@@ -2027,9 +2566,7 @@ static uint32_t rtl8139_IntrStatus_read(
 {
     uint32_t ret = s->IntrStatus;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: IntrStatus read(w) val=0x%04x\n", ret);
-#endif
+    DEBUG_PRINT(("RTL8139: IntrStatus read(w) val=0x%04x\n", ret));
 
 #if 0
 
@@ -2045,9 +2582,7 @@ static uint32_t rtl8139_IntrStatus_read(
 
 static void rtl8139_MultiIntr_write(RTL8139State *s, uint32_t val)
 {
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: MultiIntr write(w) val=0x%04x\n", val);
-#endif
+    DEBUG_PRINT(("RTL8139: MultiIntr write(w) val=0x%04x\n", val));
 
     /* mask unwriteable bits */
     val = SET_MASKED(val, 0xf000, s->MultiIntr);
@@ -2059,9 +2594,7 @@ static uint32_t rtl8139_MultiIntr_read(R
 {
     uint32_t ret = s->MultiIntr;
 
-#ifdef DEBUG_RTL8139
-    printf("RTL8139: MultiIntr read(w) val=0x%04x\n", ret);
-#endif
+    DEBUG_PRINT(("RTL8139: MultiIntr read(w) val=0x%04x\n", ret));
 
     return ret;
 }
@@ -2109,15 +2642,11 @@ static void rtl8139_io_writeb(void *opaq
             break;
         case MediaStatus:
             /* ignore */
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: not implemented write(b) to MediaStatus 
val=0x%02x\n", val);
-#endif
+            DEBUG_PRINT(("RTL8139: not implemented write(b) to MediaStatus 
val=0x%02x\n", val));
             break;
 
         case HltClk:
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: HltClk write val=0x%08x\n", val);
-#endif
+            DEBUG_PRINT(("RTL8139: HltClk write val=0x%08x\n", val));
             if (val == 'R')
             {
                 s->clock_enabled = 1;
@@ -2129,37 +2658,27 @@ static void rtl8139_io_writeb(void *opaq
             break;
 
         case TxThresh:
-#ifdef DEBUG_RTL8139
-            printf("RTL8139C+ TxThresh write(b) val=0x%02x\n", val);
-#endif
+            DEBUG_PRINT(("RTL8139C+ TxThresh write(b) val=0x%02x\n", val));
             s->TxThresh = val;
             break;
 
         case TxPoll:
-#ifdef DEBUG_RTL8139
-                printf("RTL8139C+ TxPoll write(b) val=0x%02x\n", val);
-#endif
+            DEBUG_PRINT(("RTL8139C+ TxPoll write(b) val=0x%02x\n", val));
             if (val & (1 << 7))
             {
-#ifdef DEBUG_RTL8139
-                printf("RTL8139C+ TxPoll high priority transmission (not 
implemented)\n");
-#endif
+                DEBUG_PRINT(("RTL8139C+ TxPoll high priority transmission (not 
implemented)\n"));
                 //rtl8139_cplus_transmit(s);
             }
             if (val & (1 << 6))
             {
-#ifdef DEBUG_RTL8139
-                printf("RTL8139C+ TxPoll normal priority transmission\n");
-#endif
+                DEBUG_PRINT(("RTL8139C+ TxPoll normal priority 
transmission\n"));
                 rtl8139_cplus_transmit(s);
             }
 
             break;
 
         default:
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: not implemented write(b) addr=0x%x val=0x%02x\n", 
addr, val);
-#endif
+            DEBUG_PRINT(("RTL8139: not implemented write(b) addr=0x%x 
val=0x%02x\n", addr, val));
             break;
     }
 }
@@ -2195,20 +2714,14 @@ static void rtl8139_io_writew(void *opaq
             rtl8139_BasicModeStatus_write(s, val);
             break;
         case NWayAdvert:
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: NWayAdvert write(w) val=0x%04x\n", val);
-#endif
+            DEBUG_PRINT(("RTL8139: NWayAdvert write(w) val=0x%04x\n", val));
             s->NWayAdvert = val;
             break;
         case NWayLPAR:
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: forbidden NWayLPAR write(w) val=0x%04x\n", val);
-#endif
+            DEBUG_PRINT(("RTL8139: forbidden NWayLPAR write(w) val=0x%04x\n", 
val));
             break;
         case NWayExpansion:
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: NWayExpansion write(w) val=0x%04x\n", val);
-#endif
+            DEBUG_PRINT(("RTL8139: NWayExpansion write(w) val=0x%04x\n", val));
             s->NWayExpansion = val;
             break;
 
@@ -2216,10 +2729,12 @@ static void rtl8139_io_writew(void *opaq
             rtl8139_CpCmd_write(s, val);
             break;
 
+        case IntrMitigate:
+            rtl8139_IntrMitigate_write(s, val);
+            break;
+
         default:
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: ioport write(w) addr=0x%x val=0x%04x via 
write(b)\n", addr, val);
-#endif
+            DEBUG_PRINT(("RTL8139: ioport write(w) addr=0x%x val=0x%04x via 
write(b)\n", addr, val));
 
 #ifdef TARGET_WORDS_BIGENDIAN
             rtl8139_io_writeb(opaque, addr, (val >> 8) & 0xff);
@@ -2241,9 +2756,7 @@ static void rtl8139_io_writel(void *opaq
     switch (addr)
     {
         case RxMissed:
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: RxMissed clearing on write\n");
-#endif
+            DEBUG_PRINT(("RTL8139: RxMissed clearing on write\n"));
             s->RxMissed = 0;
             break;
 
@@ -2268,23 +2781,28 @@ static void rtl8139_io_writel(void *opaq
             break;
 
         case RxRingAddrLO:
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: C+ RxRing low bits write val=0x%08x\n", val);
-#endif
+            DEBUG_PRINT(("RTL8139: C+ RxRing low bits write val=0x%08x\n", 
val));
             s->RxRingAddrLO = val;
             break;
 
         case RxRingAddrHI:
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: C+ RxRing high bits write val=0x%08x\n", val);
-#endif
+            DEBUG_PRINT(("RTL8139: C+ RxRing high bits write val=0x%08x\n", 
val));
             s->RxRingAddrHI = val;
             break;
 
+        case Timer:
+            DEBUG_PRINT(("RTL8139: TCTR Timer reset on write\n"));
+            s->TCTR = 0;
+            s->TCTR_base = qemu_get_clock(vm_clock);
+            break;
+
+        case FlashReg:
+            DEBUG_PRINT(("RTL8139: FlashReg TimerInt write val=0x%08x\n", 
val));
+            s->TimerInt = val;
+            break;
+
         default:
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: ioport write(l) addr=0x%x val=0x%08x via 
write(b)\n", addr, val);
-#endif
+            DEBUG_PRINT(("RTL8139: ioport write(l) addr=0x%x val=0x%08x via 
write(b)\n", addr, val));
 #ifdef TARGET_WORDS_BIGENDIAN
             rtl8139_io_writeb(opaque, addr, (val >> 24) & 0xff);
             rtl8139_io_writeb(opaque, addr + 1, (val >> 16) & 0xff);
@@ -2342,43 +2860,31 @@ static uint32_t rtl8139_io_readb(void *o
 
         case MediaStatus:
             ret = 0xd0;
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: MediaStatus read 0x%x\n", ret);
-#endif
+            DEBUG_PRINT(("RTL8139: MediaStatus read 0x%x\n", ret));
             break;
 
         case HltClk:
             ret = s->clock_enabled;
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: HltClk read 0x%x\n", ret);
-#endif
+            DEBUG_PRINT(("RTL8139: HltClk read 0x%x\n", ret));
             break;
 
         case PCIRevisionID:
-            ret = 0x10;
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: PCI Revision ID read 0x%x\n", ret);
-#endif
+            ret = RTL8139_PCI_REVID;
+            DEBUG_PRINT(("RTL8139: PCI Revision ID read 0x%x\n", ret));
             break;
 
         case TxThresh:
             ret = s->TxThresh;
-#ifdef DEBUG_RTL8139
-            printf("RTL8139C+ TxThresh read(b) val=0x%02x\n", ret);
-#endif
+            DEBUG_PRINT(("RTL8139C+ TxThresh read(b) val=0x%02x\n", ret));
             break;
 
         case 0x43: /* Part of TxConfig register. Windows driver tries to read 
it */
             ret = s->TxConfig >> 24;
-#ifdef DEBUG_RTL8139
-            printf("RTL8139C TxConfig at 0x43 read(b) val=0x%02x\n", ret);
-#endif
+            DEBUG_PRINT(("RTL8139C TxConfig at 0x43 read(b) val=0x%02x\n", 
ret));
             break;
 
         default:
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: not implemented read(b) addr=0x%x\n", addr);
-#endif
+            DEBUG_PRINT(("RTL8139: not implemented read(b) addr=0x%x\n", 
addr));
             ret = 0;
             break;
     }
@@ -2411,6 +2917,10 @@ static uint32_t rtl8139_io_readw(void *o
             ret = rtl8139_RxBufPtr_read(s);
             break;
 
+        case RxBufAddr:
+            ret = rtl8139_RxBufAddr_read(s);
+            break;
+
         case BasicModeCtrl:
             ret = rtl8139_BasicModeCtrl_read(s);
             break;
@@ -2419,27 +2929,25 @@ static uint32_t rtl8139_io_readw(void *o
             break;
         case NWayAdvert:
             ret = s->NWayAdvert;
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: NWayAdvert read(w) val=0x%04x\n", ret);
-#endif
+            DEBUG_PRINT(("RTL8139: NWayAdvert read(w) val=0x%04x\n", ret));
             break;
         case NWayLPAR:
             ret = s->NWayLPAR;
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: NWayLPAR read(w) val=0x%04x\n", ret);
-#endif
+            DEBUG_PRINT(("RTL8139: NWayLPAR read(w) val=0x%04x\n", ret));
             break;
         case NWayExpansion:
             ret = s->NWayExpansion;
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: NWayExpansion read(w) val=0x%04x\n", ret);
-#endif
+            DEBUG_PRINT(("RTL8139: NWayExpansion read(w) val=0x%04x\n", ret));
             break;
 
         case CpCmd:
             ret = rtl8139_CpCmd_read(s);
             break;
 
+        case IntrMitigate:
+            ret = rtl8139_IntrMitigate_read(s);
+            break;
+
         case TxSummary:
             ret = rtl8139_TSAD_read(s);
             break;
@@ -2449,9 +2957,7 @@ static uint32_t rtl8139_io_readw(void *o
             break;
 
         default:
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: ioport read(w) addr=0x%x via read(b)\n", addr);
-#endif
+            DEBUG_PRINT(("RTL8139: ioport read(w) addr=0x%x via read(b)\n", 
addr));
 
 #ifdef TARGET_WORDS_BIGENDIAN
             ret  = rtl8139_io_readb(opaque, addr) << 8;
@@ -2461,9 +2967,7 @@ static uint32_t rtl8139_io_readw(void *o
             ret |= rtl8139_io_readb(opaque, addr + 1) << 8;
 #endif
 
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: ioport read(w) addr=0x%x val=0x%04x\n", addr, 
ret);
-#endif
+            DEBUG_PRINT(("RTL8139: ioport read(w) addr=0x%x val=0x%04x\n", 
addr, ret));
             break;
     }
 
@@ -2482,9 +2986,7 @@ static uint32_t rtl8139_io_readl(void *o
         case RxMissed:
             ret = s->RxMissed;
 
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: RxMissed read val=0x%08x\n", ret);
-#endif
+            DEBUG_PRINT(("RTL8139: RxMissed read val=0x%08x\n", ret));
             break;
 
         case TxConfig:
@@ -2509,22 +3011,26 @@ static uint32_t rtl8139_io_readl(void *o
 
         case RxRingAddrLO:
             ret = s->RxRingAddrLO;
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: C+ RxRing low bits read val=0x%08x\n", ret);
-#endif
+            DEBUG_PRINT(("RTL8139: C+ RxRing low bits read val=0x%08x\n", 
ret));
             break;
 
         case RxRingAddrHI:
             ret = s->RxRingAddrHI;
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: C+ RxRing high bits read val=0x%08x\n", ret);
-#endif
+            DEBUG_PRINT(("RTL8139: C+ RxRing high bits read val=0x%08x\n", 
ret));
+            break;
+
+        case Timer:
+            ret = s->TCTR;
+            DEBUG_PRINT(("RTL8139: TCTR Timer read val=0x%08x\n", ret));
+            break;
+
+        case FlashReg:
+            ret = s->TimerInt;
+            DEBUG_PRINT(("RTL8139: FlashReg TimerInt read val=0x%08x\n", ret));
             break;
 
         default:
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: ioport read(l) addr=0x%x via read(b)\n", addr);
-#endif
+            DEBUG_PRINT(("RTL8139: ioport read(l) addr=0x%x via read(b)\n", 
addr));
 
 #ifdef TARGET_WORDS_BIGENDIAN
             ret  = rtl8139_io_readb(opaque, addr) << 24;
@@ -2538,9 +3044,7 @@ static uint32_t rtl8139_io_readl(void *o
             ret |= rtl8139_io_readb(opaque, addr + 3) << 24;
 #endif
 
-#ifdef DEBUG_RTL8139
-            printf("RTL8139: read(l) addr=0x%x val=%08x\n", addr, ret);
-#endif
+            DEBUG_PRINT(("RTL8139: read(l) addr=0x%x val=%08x\n", addr, ret));
             break;
     }
 
@@ -2688,6 +3192,12 @@ static void rtl8139_save(QEMUFile* f,voi
     qemu_put_8s(f, &s->eeprom.eesk);
     qemu_put_8s(f, &s->eeprom.eedi);
     qemu_put_8s(f, &s->eeprom.eedo);
+
+    qemu_put_be32s(f, &s->TCTR);
+    qemu_put_be32s(f, &s->TimerInt);
+    qemu_put_be64s(f, &s->TCTR_base);
+
+    RTL8139TallyCounters_save(f, &s->tally_counters);
 }
 
 static int rtl8139_load(QEMUFile* f,void* opaque,int version_id)
@@ -2695,9 +3205,11 @@ static int rtl8139_load(QEMUFile* f,void
     RTL8139State* s=(RTL8139State*)opaque;
     int i;
 
-    if (version_id != 1)
+    /* just 2 versions for now */
+    if (version_id > 2)
             return -EINVAL;
 
+    /* saved since version 1 */
     qemu_get_buffer(f, s->phys, 6);
     qemu_get_buffer(f, s->mult, 8);
 
@@ -2769,6 +3281,25 @@ static int rtl8139_load(QEMUFile* f,void
     qemu_get_8s(f, &s->eeprom.eedi);
     qemu_get_8s(f, &s->eeprom.eedo);
 
+    /* saved since version 2 */
+    if (version_id >= 2)
+    {
+        qemu_get_be32s(f, &s->TCTR);
+        qemu_get_be32s(f, &s->TimerInt);
+        qemu_get_be64s(f, &s->TCTR_base);
+
+        RTL8139TallyCounters_load(f, &s->tally_counters);
+    }
+    else
+    {
+        /* not saved, use default */
+        s->TCTR = 0;
+        s->TimerInt = 0;
+        s->TCTR_base = 0;
+
+        RTL8139TallyCounters_clear(&s->tally_counters);
+    }
+
     return 0;
 }
 
@@ -2816,6 +3347,59 @@ static CPUWriteMemoryFunc *rtl8139_mmio_
     rtl8139_mmio_writew,
     rtl8139_mmio_writel,
 };
+
+static inline int64_t rtl8139_get_next_tctr_time(RTL8139State *s, int64_t 
current_time)
+{
+    int64_t next_time = current_time + 
+        muldiv64(1, ticks_per_sec, PCI_FREQUENCY);
+    if (next_time <= current_time)
+        next_time = current_time + 1;
+    return next_time;
+}
+
+#if RTL8139_ONBOARD_TIMER
+static void rtl8139_timer(void *opaque)
+{
+    RTL8139State *s = opaque;
+
+    int is_timeout = 0;
+
+    int64_t  curr_time;
+    uint32_t curr_tick;
+
+    if (!s->clock_enabled)
+    {
+        DEBUG_PRINT(("RTL8139: >>> timer: clock is not running\n"));
+        return;
+    }
+
+    curr_time = qemu_get_clock(vm_clock);
+
+    curr_tick = muldiv64(curr_time - s->TCTR_base, PCI_FREQUENCY, 
ticks_per_sec);
+
+    if (s->TimerInt && curr_tick >= s->TimerInt)
+    {
+        if (s->TCTR < s->TimerInt || curr_tick < s->TCTR)
+        {
+            is_timeout = 1;
+        }
+    }
+
+    s->TCTR = curr_tick;
+
+//  DEBUG_PRINT(("RTL8139: >>> timer: tick=%08u\n", s->TCTR));
+
+    if (is_timeout)
+    {
+        DEBUG_PRINT(("RTL8139: >>> timer: timeout tick=%08u\n", s->TCTR));
+        s->IntrStatus |= PCSTimeout;
+        rtl8139_update_irq(s);
+    }
+
+    qemu_mod_timer(s->timer, 
+        rtl8139_get_next_tctr_time(s,curr_time));
+}
+#endif /* RTL8139_ONBOARD_TIMER */
 
 void pci_rtl8139_init(PCIBus *bus, NICInfo *nd)
 {
@@ -2833,7 +3417,7 @@ void pci_rtl8139_init(PCIBus *bus, NICIn
     pci_conf[0x02] = 0x39;
     pci_conf[0x03] = 0x81;
     pci_conf[0x04] = 0x05; /* command = I/O space, Bus Master */
-    pci_conf[0x08] = 0x20; /* 0x10 */ /* PCI revision ID; >=0x20 is for 8139C+ 
*/
+    pci_conf[0x08] = RTL8139_PCI_REVID; /* PCI revision ID; >=0x20 is for 
8139C+ */
     pci_conf[0x0a] = 0x00; /* ethernet network controller */
     pci_conf[0x0b] = 0x02;
     pci_conf[0x0e] = 0x00; /* header_type */
@@ -2867,9 +3451,21 @@ void pci_rtl8139_init(PCIBus *bus, NICIn
              s->macaddr[3],
              s->macaddr[4],
              s->macaddr[5]);
+
+    s->cplus_txbuffer = NULL;
+    s->cplus_txbuffer_len = 0;
+    s->cplus_txbuffer_offset = 0;
              
     /* XXX: instance number ? */
-    register_savevm("rtl8139", 0, 1, rtl8139_save, rtl8139_load, s);
+    register_savevm("rtl8139", 0, 2, rtl8139_save, rtl8139_load, s);
     register_savevm("rtl8139_pci", 0, 1, generic_pci_save, generic_pci_load, 
                     &d->dev);
-}
+
+#if RTL8139_ONBOARD_TIMER
+    s->timer = qemu_new_timer(vm_clock, rtl8139_timer, s);
+
+    qemu_mod_timer(s->timer, 
+        rtl8139_get_next_tctr_time(s,qemu_get_clock(vm_clock)));
+#endif /* RTL8139_ONBOARD_TIMER */
+}
+
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/sb16.c
--- a/tools/ioemu/hw/sb16.c     Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/sb16.c     Mon Aug 07 18:25:30 2006 +0100
@@ -193,6 +193,31 @@ static void aux_timer (void *opaque)
 #define DMA8_AUTO 1
 #define DMA8_HIGH 2
 
+static void continue_dma8 (SB16State *s)
+{
+    if (s->freq > 0) {
+        audsettings_t as;
+
+        s->audio_free = 0;
+
+        as.freq = s->freq;
+        as.nchannels = 1 << s->fmt_stereo;
+        as.fmt = s->fmt;
+        as.endianness = 0;
+
+        s->voice = AUD_open_out (
+            &s->card,
+            s->voice,
+            "sb16",
+            s,
+            SB_audio_callback,
+            &as
+            );
+    }
+
+    control (s, 1);
+}
+
 static void dma_cmd8 (SB16State *s, int mask, int dma_len)
 {
     s->fmt = AUD_FMT_U8;
@@ -201,7 +226,8 @@ static void dma_cmd8 (SB16State *s, int 
     s->fmt_signed = 0;
     s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
     if (-1 == s->time_const) {
-        s->freq = 11025;
+        if (s->freq <= 0)
+            s->freq = 11025;
     }
     else {
         int tmp = (256 - s->time_const);
@@ -239,27 +265,7 @@ static void dma_cmd8 (SB16State *s, int 
             s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
             s->block_size, s->dma_auto, s->fifo, s->highspeed);
 
-    if (s->freq) {
-        audsettings_t as;
-
-        s->audio_free = 0;
-
-        as.freq = s->freq;
-        as.nchannels = 1 << s->fmt_stereo;
-        as.fmt = s->fmt;
-
-        s->voice = AUD_open_out (
-            &s->card,
-            s->voice,
-            "sb16",
-            s,
-            SB_audio_callback,
-            &as,
-            0                   /* little endian */
-            );
-    }
-
-    control (s, 1);
+    continue_dma8 (s);
     speaker (s, 1);
 }
 
@@ -342,6 +348,7 @@ static void dma_cmd (SB16State *s, uint8
         as.freq = s->freq;
         as.nchannels = 1 << s->fmt_stereo;
         as.fmt = s->fmt;
+        as.endianness = 0;
 
         s->voice = AUD_open_out (
             &s->card,
@@ -349,8 +356,7 @@ static void dma_cmd (SB16State *s, uint8
             "sb16",
             s,
             SB_audio_callback,
-            &as,
-            0                   /* little endian */
+            &as
             );
     }
 
@@ -437,7 +443,7 @@ static void command (SB16State *s, uint8
             break;
 
         case 0x1c:              /* Auto-Initialize DMA DAC, 8-bit */
-            control (s, 1);
+            dma_cmd8 (s, DMA8_AUTO, -1);
             break;
 
         case 0x20:              /* Direct ADC, Juice/PL */
@@ -531,7 +537,9 @@ static void command (SB16State *s, uint8
             break;
 
         case 0xd4:              /* continue DMA operation. 8bit */
-            control (s, 1);
+            /* KQ6 (or maybe Sierras audblst.drv in general) resets
+               the frequency between halt/continue */
+            continue_dma8 (s);
             break;
 
         case 0xd5:              /* halt DMA operation. 16bit */
@@ -765,7 +773,7 @@ static void complete (SB16State *s)
                             );
                     }
                 }
-                ldebug ("mix silence %d %d %lld\n", samples, bytes, ticks);
+                ldebug ("mix silence %d %d %" PRId64 "\n", samples, bytes, 
ticks);
             }
             break;
 
@@ -816,6 +824,33 @@ static void complete (SB16State *s)
     ldebug ("\n");
     s->cmd = -1;
     return;
+}
+
+static void legacy_reset (SB16State *s)
+{
+    audsettings_t as;
+
+    s->freq = 11025;
+    s->fmt_signed = 0;
+    s->fmt_bits = 8;
+    s->fmt_stereo = 0;
+
+    as.freq = s->freq;
+    as.nchannels = 1;
+    as.fmt = AUD_FMT_U8;
+    as.endianness = 0;
+
+    s->voice = AUD_open_out (
+        &s->card,
+        s->voice,
+        "sb16",
+        s,
+        SB_audio_callback,
+        &as
+        );
+
+    /* Not sure about that... */
+    /* AUD_set_active_out (s->voice, 1); */
 }
 
 static void reset (SB16State *s)
@@ -841,6 +876,7 @@ static void reset (SB16State *s)
     dsp_out_data(s, 0xaa);
     speaker (s, 0);
     control (s, 0);
+    legacy_reset (s);
 }
 
 static IO_WRITE_PROTO (dsp_write)
@@ -1335,6 +1371,7 @@ static int SB_load (QEMUFile *f, void *o
             as.freq = s->freq;
             as.nchannels = 1 << s->fmt_stereo;
             as.fmt = s->fmt;
+            as.endianness = 0;
 
             s->voice = AUD_open_out (
                 &s->card,
@@ -1342,8 +1379,7 @@ static int SB_load (QEMUFile *f, void *o
                 "sb16",
                 s,
                 SB_audio_callback,
-                &as,
-                0               /* little endian */
+                &as
                 );
         }
 
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/sh7750.c
--- a/tools/ioemu/hw/sh7750.c   Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/sh7750.c   Mon Aug 07 18:25:30 2006 +0100
@@ -124,7 +124,7 @@ static void start_timer0(SH7750State * s
                       s->periph_freq);
     if (next == now)
        next = now + 1;
-    fprintf(stderr, "now=%016llx, next=%016llx\n", now, next);
+    fprintf(stderr, "now=%016" PRIx64 ", next=%016" PRIx64 "\n", now, next);
     fprintf(stderr, "timer will underflow in %f seconds\n",
            (float) (next - now) / (float) ticks_per_sec);
 
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/slavio_intctl.c
--- a/tools/ioemu/hw/slavio_intctl.c    Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/slavio_intctl.c    Mon Aug 07 18:25:30 2006 +0100
@@ -203,7 +203,7 @@ void slavio_irq_info(void *opaque)
     for (i = 0; i < 32; i++) {
         count = s->irq_count[i];
         if (count > 0)
-            term_printf("%2d: %lld\n", i, count);
+            term_printf("%2d: %" PRId64 "\n", i, count);
     }
 #endif
 }
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/slavio_timer.c
--- a/tools/ioemu/hw/slavio_timer.c     Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/slavio_timer.c     Mon Aug 07 18:25:30 2006 +0100
@@ -100,7 +100,7 @@ static void slavio_timer_get_out(SLAVIO_
     // Convert remaining counter ticks to CPU ticks
     s->expire_time = ticks + muldiv64(limit - count, ticks_per_sec, CNT_FREQ);
 
-    DPRINTF("irq %d limit %d reached %d d %lld count %d s->c %x diff %lld 
stopped %d mode %d\n", s->irq, limit, s->reached?1:0, 
(ticks-s->count_load_time), count, s->count, s->expire_time - ticks, 
s->stopped, s->mode);
+    DPRINTF("irq %d limit %d reached %d d %" PRId64 " count %d s->c %x diff %" 
PRId64 " stopped %d mode %d\n", s->irq, limit, s->reached?1:0, 
(ticks-s->count_load_time), count, s->count, s->expire_time - ticks, 
s->stopped, s->mode);
 
     if (s->mode != 1)
        pic_set_irq_cpu(s->irq, out, s->cpu);
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/sun4m.c
--- a/tools/ioemu/hw/sun4m.c    Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/sun4m.c    Mon Aug 07 18:25:30 2006 +0100
@@ -28,8 +28,7 @@
 #define INITRD_LOAD_ADDR     0x00800000
 #define PROM_SIZE_MAX        (256 * 1024)
 #define PROM_ADDR           0xffd00000
-#define PROM_FILENAMEB      "proll.bin"
-#define PROM_FILENAMEE      "proll.elf"
+#define PROM_FILENAME       "openbios-sparc32"
 #define PHYS_JJ_EEPROM 0x71200000      /* m48t08 */
 #define PHYS_JJ_IDPROM_OFF     0x1FD8
 #define PHYS_JJ_EEPROM_SIZE    0x2000
@@ -183,6 +182,11 @@ void pic_set_irq(int irq, int level)
     slavio_pic_set_irq(slavio_intctl, irq, level);
 }
 
+void pic_set_irq_new(void *opaque, int irq, int level)
+{
+    pic_set_irq(irq, level);
+}
+
 void pic_set_irq_cpu(int irq, int level, unsigned int cpu)
 {
     slavio_pic_set_irq_cpu(slavio_intctl, irq, level, cpu);
@@ -268,12 +272,8 @@ static void sun4m_init(int ram_size, int
                                  (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) & 
TARGET_PAGE_MASK, 
                                  prom_offset | IO_MEM_ROM);
 
-    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEE);
+    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
     ret = load_elf(buf, 0, NULL);
-    if (ret < 0) {
-       snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEB);
-       ret = load_image(buf, phys_ram_base + prom_offset);
-    }
     if (ret < 0) {
        fprintf(stderr, "qemu: could not load prom '%s'\n", 
                buf);
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/sun4u.c
--- a/tools/ioemu/hw/sun4u.c    Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/sun4u.c    Mon Aug 07 18:25:30 2006 +0100
@@ -27,13 +27,12 @@
 #define KERNEL_LOAD_ADDR     0x00404000
 #define CMDLINE_ADDR         0x003ff000
 #define INITRD_LOAD_ADDR     0x00300000
-#define PROM_SIZE_MAX        (256 * 1024)
+#define PROM_SIZE_MAX        (512 * 1024)
 #define PROM_ADDR           0x1fff0000000ULL
 #define APB_SPECIAL_BASE     0x1fe00000000ULL
 #define APB_MEM_BASE        0x1ff00000000ULL
 #define VGA_BASE            (APB_MEM_BASE + 0x400000ULL)
-#define PROM_FILENAMEB      "proll-sparc64.bin"
-#define PROM_FILENAMEE      "proll-sparc64.elf"
+#define PROM_FILENAME       "openbios-sparc64"
 #define NVRAM_SIZE           0x2000
 
 /* TSC handling */
@@ -282,12 +281,8 @@ static void sun4u_init(int ram_size, int
                                  (PROM_SIZE_MAX + TARGET_PAGE_SIZE) & 
TARGET_PAGE_MASK, 
                                  prom_offset | IO_MEM_ROM);
 
-    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEE);
+    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
     ret = load_elf(buf, 0, NULL);
-    if (ret < 0) {
-       snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEB);
-       ret = load_image(buf, phys_ram_base + prom_offset);
-    }
     if (ret < 0) {
        fprintf(stderr, "qemu: could not load prom '%s'\n", 
                buf);
@@ -329,12 +324,9 @@ static void sun4u_init(int ram_size, int
            }
         }
     }
-    pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE);
+    pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, NULL);
     isa_mem_base = VGA_BASE;
-    vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size, 
-                   vga_ram_size, 0, 0);
-    cpu_register_physical_memory(VGA_BASE, vga_ram_size, ram_size);
-    //pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size, ram_size, 
vga_ram_size);
+    pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size, ram_size, 
vga_ram_size);
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/usb-hid.c
--- a/tools/ioemu/hw/usb-hid.c  Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/usb-hid.c  Mon Aug 07 18:25:30 2006 +0100
@@ -500,6 +500,14 @@ static int usb_mouse_handle_data(USBDevi
     return ret;
 }
 
+static void usb_mouse_handle_destroy(USBDevice *dev)
+{
+    USBMouseState *s = (USBMouseState *)dev;
+
+    qemu_add_mouse_event_handler(NULL, NULL, 0);
+    qemu_free(s);
+}
+
 USBDevice *usb_tablet_init(void)
 {
     USBMouseState *s;
@@ -513,7 +521,10 @@ USBDevice *usb_tablet_init(void)
     s->dev.handle_reset = usb_mouse_handle_reset;
     s->dev.handle_control = usb_mouse_handle_control;
     s->dev.handle_data = usb_mouse_handle_data;
+    s->dev.handle_destroy = usb_mouse_handle_destroy;
     s->kind = USB_TABLET;
+
+    pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
 
     return (USBDevice *)s;
 }
@@ -531,7 +542,10 @@ USBDevice *usb_mouse_init(void)
     s->dev.handle_reset = usb_mouse_handle_reset;
     s->dev.handle_control = usb_mouse_handle_control;
     s->dev.handle_data = usb_mouse_handle_data;
+    s->dev.handle_destroy = usb_mouse_handle_destroy;
     s->kind = USB_MOUSE;
 
+    pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");
+
     return (USBDevice *)s;
 }
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/usb-hub.c
--- a/tools/ioemu/hw/usb-hub.c  Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/usb-hub.c  Mon Aug 07 18:25:30 2006 +0100
@@ -152,7 +152,7 @@ static const uint8_t qemu_hub_config_des
 
 static const uint8_t qemu_hub_hub_descriptor[] =
 {
-       0x09,                   /*  u8  bLength; */
+       0x00,                   /*  u8  bLength; patched in later */
        0x29,                   /*  u8  bDescriptorType; Hub-descriptor */
        0x00,                   /*  u8  bNbrPorts; (patched later) */
        0x0a,                   /* u16  wHubCharacteristics; */
@@ -179,6 +179,9 @@ static void usb_hub_attach(USBPort *port
         else
             port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
         port->port.dev = dev;
+        /* send the attach message */
+        dev->handle_packet(dev, 
+                           USB_MSG_ATTACH, 0, 0, NULL, 0);
     } else {
         dev = port->port.dev;
         if (dev) {
@@ -188,6 +191,9 @@ static void usb_hub_attach(USBPort *port
                 port->wPortStatus &= ~PORT_STAT_ENABLE;
                 port->wPortChange |= PORT_STAT_C_ENABLE;
             }
+            /* send the detach message */
+            dev->handle_packet(dev, 
+                               USB_MSG_DETACH, 0, 0, NULL, 0);
             port->port.dev = NULL;
         }
     }
@@ -417,6 +423,7 @@ static int usb_hub_handle_control(USBDev
             }
 
             ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size;
+            data[0] = ret;
             break;
         }
     default:
@@ -516,7 +523,14 @@ static int usb_hub_handle_packet(USBDevi
     return usb_generic_handle_packet(dev, pid, devaddr, devep, data, len);
 }
 
-USBDevice *usb_hub_init(USBPort **usb_ports, int nb_ports)
+static void usb_hub_handle_destroy(USBDevice *dev)
+{
+    USBHubState *s = (USBHubState *)dev;
+
+    qemu_free(s);
+}
+
+USBDevice *usb_hub_init(int nb_ports)
 {
     USBHubState *s;
     USBHubPort *port;
@@ -534,16 +548,16 @@ USBDevice *usb_hub_init(USBPort **usb_po
     s->dev.handle_reset = usb_hub_handle_reset;
     s->dev.handle_control = usb_hub_handle_control;
     s->dev.handle_data = usb_hub_handle_data;
+    s->dev.handle_destroy = usb_hub_handle_destroy;
+
+    pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Hub");
 
     s->nb_ports = nb_ports;
     for(i = 0; i < s->nb_ports; i++) {
         port = &s->ports[i];
+        qemu_register_usb_port(&port->port, s, i, usb_hub_attach);
         port->wPortStatus = PORT_STAT_POWER;
         port->wPortChange = 0;
-        port->port.attach = usb_hub_attach;
-        port->port.opaque = s;
-        port->port.index = i;
-        usb_ports[i] = &port->port;
     }
     return (USBDevice *)s;
 }
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/usb-uhci.c
--- a/tools/ioemu/hw/usb-uhci.c Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/usb-uhci.c Mon Aug 07 18:25:30 2006 +0100
@@ -327,9 +327,8 @@ static void uhci_attach(USBPort *port1, 
             usb_attach(port1, NULL);
         }
         /* set connect status */
-        if (!(port->ctrl & UHCI_PORT_CCS)) {
-            port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
-        }
+        port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
+
         /* update speed */
         if (dev->speed == USB_SPEED_LOW)
             port->ctrl |= UHCI_PORT_LSDA;
@@ -341,8 +340,9 @@ static void uhci_attach(USBPort *port1, 
                            USB_MSG_ATTACH, 0, 0, NULL, 0);
     } else {
         /* set connect status */
-        if (!(port->ctrl & UHCI_PORT_CCS)) {
-            port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
+        if (port->ctrl & UHCI_PORT_CCS) {
+            port->ctrl &= ~UHCI_PORT_CCS;
+            port->ctrl |= UHCI_PORT_CSC;
         }
         /* disable port */
         if (port->ctrl & UHCI_PORT_EN) {
@@ -638,17 +638,15 @@ static void uhci_map(PCIDevice *pci_dev,
     register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
 }
 
-void usb_uhci_init(PCIBus *bus, USBPort **usb_ports)
+void usb_uhci_init(PCIBus *bus, int devfn)
 {
     UHCIState *s;
     uint8_t *pci_conf;
-    UHCIPort *port;
     int i;
 
     s = (UHCIState *)pci_register_device(bus,
                                         "USB-UHCI", sizeof(UHCIState),
-                                        ((PCIDevice *)piix3_state)->devfn + 2, 
-                                        NULL, NULL);
+                                        devfn, NULL, NULL);
     pci_conf = s->dev.config;
     pci_conf[0x00] = 0x86;
     pci_conf[0x01] = 0x80;
@@ -663,11 +661,7 @@ void usb_uhci_init(PCIBus *bus, USBPort 
     pci_conf[0x60] = 0x10; // release number
     
     for(i = 0; i < NB_PORTS; i++) {
-        port = &s->ports[i];
-        port->port.opaque = s;
-        port->port.index = i;
-        port->port.attach = uhci_attach;
-        usb_ports[i] = &port->port;
+        qemu_register_usb_port(&s->ports[i].port, s, i, uhci_attach);
     }
     s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
 
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/usb.h
--- a/tools/ioemu/hw/usb.h      Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/usb.h      Mon Aug 07 18:25:30 2006 +0100
@@ -116,6 +116,8 @@ struct USBDevice {
     int (*handle_packet)(USBDevice *dev, int pid, 
                          uint8_t devaddr, uint8_t devep,
                          uint8_t *data, int len);
+    void (*handle_destroy)(USBDevice *dev);
+
     int speed;
     
     /* The following fields are used by the generic USB device
@@ -127,6 +129,7 @@ struct USBDevice {
     int (*handle_data)(USBDevice *dev, int pid, uint8_t devep,
                        uint8_t *data, int len);
     uint8_t addr;
+    char devname[32];
     
     int state;
     uint8_t setup_buf[8];
@@ -137,12 +140,15 @@ struct USBDevice {
     int setup_index;
 };
 
+typedef void (*usb_attachfn)(USBPort *port, USBDevice *dev);
+
 /* USB port on which a device can be connected */
 struct USBPort {
     USBDevice *dev;
-    void (*attach)(USBPort *port, USBDevice *dev);
+    usb_attachfn attach;
     void *opaque;
     int index; /* internal port index, may be used with the opaque */
+    struct USBPort *next; /* Used internally by qemu.  */
 };
 
 void usb_attach(USBPort *port, USBDevice *dev);
@@ -152,10 +158,13 @@ int set_usb_string(uint8_t *buf, const c
 int set_usb_string(uint8_t *buf, const char *str);
 
 /* usb hub */
-USBDevice *usb_hub_init(USBPort **usb_ports, int nb_ports);
+USBDevice *usb_hub_init(int nb_ports);
 
 /* usb-uhci.c */
-void usb_uhci_init(PCIBus *bus, USBPort **usb_ports);
+void usb_uhci_init(PCIBus *bus, int devfn);
+
+/* usb-ohci.c */
+void usb_ohci_init(struct PCIBus *bus, int num_ports, int devfn);
 
 /* usb-linux.c */
 USBDevice *usb_host_device_open(const char *devname);
@@ -164,3 +173,6 @@ void usb_host_info(void);
 /* usb-hid.c */
 USBDevice *usb_mouse_init(void);
 USBDevice *usb_tablet_init(void);
+
+/* usb-msd.c */
+USBDevice *usb_msd_init(const char *filename);
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/versatilepb.c
--- a/tools/ioemu/hw/versatilepb.c      Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/versatilepb.c      Mon Aug 07 18:25:30 2006 +0100
@@ -9,6 +9,8 @@
 
 #include "vl.h"
 #include "arm_pic.h"
+
+#define LOCK_VALUE 0xa05f
 
 /* Primary interrupt controller.  */
 
@@ -145,6 +147,188 @@ static vpb_sic_state *vpb_sic_init(uint3
     return s;
 }
 
+/* System controller.  */
+
+typedef struct {
+    uint32_t base;
+    uint32_t leds;
+    uint16_t lockval;
+    uint32_t cfgdata1;
+    uint32_t cfgdata2;
+    uint32_t flags;
+    uint32_t nvflags;
+    uint32_t resetlevel;
+} vpb_sys_state;
+
+static uint32_t vpb_sys_read(void *opaque, target_phys_addr_t offset)
+{
+    vpb_sys_state *s = (vpb_sys_state *)opaque;
+
+    offset -= s->base;
+    switch (offset) {
+    case 0x00: /* ID */
+        return 0x41007004;
+    case 0x04: /* SW */
+        /* General purpose hardware switches.
+           We don't have a useful way of exposing these to the user.  */
+        return 0;
+    case 0x08: /* LED */
+        return s->leds;
+    case 0x20: /* LOCK */
+        return s->lockval;
+    case 0x0c: /* OSC0 */
+    case 0x10: /* OSC1 */
+    case 0x14: /* OSC2 */
+    case 0x18: /* OSC3 */
+    case 0x1c: /* OSC4 */
+    case 0x24: /* 100HZ */
+        /* ??? Implement these.  */
+        return 0;
+    case 0x28: /* CFGDATA1 */
+        return s->cfgdata1;
+    case 0x2c: /* CFGDATA2 */
+        return s->cfgdata2;
+    case 0x30: /* FLAGS */
+        return s->flags;
+    case 0x38: /* NVFLAGS */
+        return s->nvflags;
+    case 0x40: /* RESETCTL */
+        return s->resetlevel;
+    case 0x44: /* PCICTL */
+        return 1;
+    case 0x48: /* MCI */
+        return 0;
+    case 0x4c: /* FLASH */
+        return 0;
+    case 0x50: /* CLCD */
+        return 0x1000;
+    case 0x54: /* CLCDSER */
+        return 0;
+    case 0x58: /* BOOTCS */
+        return 0;
+    case 0x5c: /* 24MHz */
+        /* ??? not implemented.  */
+        return 0;
+    case 0x60: /* MISC */
+        return 0;
+    case 0x64: /* DMAPSR0 */
+    case 0x68: /* DMAPSR1 */
+    case 0x6c: /* DMAPSR2 */
+    case 0x8c: /* OSCRESET0 */
+    case 0x90: /* OSCRESET1 */
+    case 0x94: /* OSCRESET2 */
+    case 0x98: /* OSCRESET3 */
+    case 0x9c: /* OSCRESET4 */
+    case 0xc0: /* SYS_TEST_OSC0 */
+    case 0xc4: /* SYS_TEST_OSC1 */
+    case 0xc8: /* SYS_TEST_OSC2 */
+    case 0xcc: /* SYS_TEST_OSC3 */
+    case 0xd0: /* SYS_TEST_OSC4 */
+        return 0;
+    default:
+        printf ("vpb_sys_read: Bad register offset 0x%x\n", offset);
+        return 0;
+    }
+}
+
+static void vpb_sys_write(void *opaque, target_phys_addr_t offset,
+                          uint32_t val)
+{
+    vpb_sys_state *s = (vpb_sys_state *)opaque;
+    offset -= s->base;
+
+    switch (offset) {
+    case 0x08: /* LED */
+        s->leds = val;
+    case 0x0c: /* OSC0 */
+    case 0x10: /* OSC1 */
+    case 0x14: /* OSC2 */
+    case 0x18: /* OSC3 */
+    case 0x1c: /* OSC4 */
+        /* ??? */
+        break;
+    case 0x20: /* LOCK */
+        if (val == LOCK_VALUE)
+            s->lockval = val;
+        else
+            s->lockval = val & 0x7fff;
+        break;
+    case 0x28: /* CFGDATA1 */
+        /* ??? Need to implement this.  */
+        s->cfgdata1 = val;
+        break;
+    case 0x2c: /* CFGDATA2 */
+        /* ??? Need to implement this.  */
+        s->cfgdata2 = val;
+        break;
+    case 0x30: /* FLAGSSET */
+        s->flags |= val;
+        break;
+    case 0x34: /* FLAGSCLR */
+        s->flags &= ~val;
+        break;
+    case 0x38: /* NVFLAGSSET */
+        s->nvflags |= val;
+        break;
+    case 0x3c: /* NVFLAGSCLR */
+        s->nvflags &= ~val;
+        break;
+    case 0x40: /* RESETCTL */
+        if (s->lockval == LOCK_VALUE) {
+            s->resetlevel = val;
+            if (val & 0x100)
+                cpu_abort(cpu_single_env, "Board reset\n");
+        }
+        break;
+    case 0x44: /* PCICTL */
+        /* nothing to do.  */
+        break;
+    case 0x4c: /* FLASH */
+    case 0x50: /* CLCD */
+    case 0x54: /* CLCDSER */
+    case 0x64: /* DMAPSR0 */
+    case 0x68: /* DMAPSR1 */
+    case 0x6c: /* DMAPSR2 */
+    case 0x8c: /* OSCRESET0 */
+    case 0x90: /* OSCRESET1 */
+    case 0x94: /* OSCRESET2 */
+    case 0x98: /* OSCRESET3 */
+    case 0x9c: /* OSCRESET4 */
+        break;
+    default:
+        printf ("vpb_sys_write: Bad register offset 0x%x\n", offset);
+        return;
+    }
+}
+
+static CPUReadMemoryFunc *vpb_sys_readfn[] = {
+   vpb_sys_read,
+   vpb_sys_read,
+   vpb_sys_read
+};
+
+static CPUWriteMemoryFunc *vpb_sys_writefn[] = {
+   vpb_sys_write,
+   vpb_sys_write,
+   vpb_sys_write
+};
+
+static vpb_sys_state *vpb_sys_init(uint32_t base)
+{
+    vpb_sys_state *s;
+    int iomemtype;
+
+    s = (vpb_sys_state *)qemu_mallocz(sizeof(vpb_sys_state));
+    if (!s)
+        return NULL;
+    s->base = base;
+    iomemtype = cpu_register_io_memory(0, vpb_sys_readfn,
+                                       vpb_sys_writefn, s);
+    cpu_register_physical_memory(base, 0x00000fff, iomemtype);
+    /* ??? Save/restore.  */
+    return s;
+}
+
 /* Board init.  */
 
 /* The AB and PB boards both use the same core, just with different
@@ -159,6 +343,11 @@ static void versatile_init(int ram_size,
     CPUState *env;
     void *pic;
     void *sic;
+    void *scsi_hba;
+    PCIBus *pci_bus;
+    NICInfo *nd;
+    int n;
+    int done_smc = 0;
 
     env = cpu_init();
     cpu_arm_set_model(env, ARM_CPUID_ARM926);
@@ -166,20 +355,33 @@ static void versatile_init(int ram_size,
     /* SDRAM at address zero.  */
     cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
 
+    vpb_sys_init(0x10000000);
     pic = arm_pic_init_cpu(env);
     pic = pl190_init(0x10140000, pic, ARM_PIC_CPU_IRQ, ARM_PIC_CPU_FIQ);
     sic = vpb_sic_init(0x10003000, pic, 31);
     pl050_init(0x10006000, sic, 3, 0);
     pl050_init(0x10007000, sic, 4, 1);
 
-    /* TODO: Init PCI NICs.  */
-    if (nd_table[0].vlan) {
-        if (nd_table[0].model == NULL
-            || strcmp(nd_table[0].model, "smc91c111") == 0) {
-            smc91c111_init(&nd_table[0], 0x10010000, sic, 25);
+    pci_bus = pci_vpb_init(sic);
+    /* The Versatile PCI bridge does not provide access to PCI IO space,
+       so many of the qemu PCI devices are not useable.  */
+    for(n = 0; n < nb_nics; n++) {
+        nd = &nd_table[n];
+        if (!nd->model)
+            nd->model = done_smc ? "rtl8139" : "smc91c111";
+        if (strcmp(nd->model, "smc91c111") == 0) {
+            smc91c111_init(nd, 0x10010000, sic, 25);
         } else {
-            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
-            exit (1);
+            pci_nic_init(pci_bus, nd);
+        }
+    }
+    if (usb_enabled) {
+        usb_ohci_init(pci_bus, 3, -1);
+    }
+    scsi_hba = lsi_scsi_init(pci_bus, -1);
+    for (n = 0; n < MAX_DISKS; n++) {
+        if (bs_table[n]) {
+            lsi_scsi_attach(scsi_hba, bs_table[n], n);
         }
     }
 
diff -r fd59667e5365 -r 08a11694b109 tools/ioemu/hw/vga.c
--- a/tools/ioemu/hw/vga.c      Mon Aug 07 18:11:59 2006 +0100
+++ b/tools/ioemu/hw/vga.c      Mon Aug 07 18:25:30 2006 +0100
@@ -378,10 +378,29 @@ static uint32_t vbe_ioport_read_data(voi
     VGAState *s = opaque;
     uint32_t val;
 
-    if (s->vbe_index <= VBE_DISPI_INDEX_NB)
-        val = s->vbe_regs[s->vbe_index];
-    else
+    if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
+        if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
+            switch(s->vbe_index) {
+                /* XXX: do not hardcode ? */
+            case VBE_DISPI_INDEX_XRES:
+                val = VBE_DISPI_MAX_XRES;
+                break;
+            case VBE_DISPI_INDEX_YRES:
+                val = VBE_DISPI_MAX_YRES;
+                break;
+            case VBE_DISPI_INDEX_BPP:
+                val = VBE_DISPI_MAX_BPP;
+                break;
+            default:
+                val = s->vbe_regs[s->vbe_index]; 
+                break;
+            }
+        } else {
+            val = s->vbe_regs[s->vbe_index]; 
+        }
+    } else {
         val = 0;
+    }
 #ifdef DEBUG_BOCHS_VBE
     printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
 #endif
@@ -434,7 +453,8 @@ static void vbe_ioport_write_data(void *
             s->bank_offset = (val << 16);
             break;
         case VBE_DISPI_INDEX_ENABLE:
-            if (val & VBE_DISPI_ENABLED) {
+            if ((val & VBE_DISPI_ENABLED) &&
+                !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
                 int h, shift_control;
 
                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = 
@@ -450,7 +470,7 @@ static void vbe_ioport_write_data(void *
                     s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] * 
                         ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
                 s->vbe_start_addr = 0;
-                
+
                 /* clear the screen (should be done in BIOS) */
                 if (!(val & VBE_DISPI_NOCLEARMEM)) {
                     memset(s->vram_ptr, 0, 
@@ -464,7 +484,7 @@ static void vbe_ioport_write_data(void *
                 s->cr[0x13] = s->vbe_line_offset >> 3;
                 /* width */
                 s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
-                /* height */
+                /* height (only meaningful if < 1024) */
                 h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
                 s->cr[0x12] = h;
                 s->cr[0x07] = (s->cr[0x07] & ~0x42) | 
@@ -808,6 +828,11 @@ static inline unsigned int rgb_to_pixel3
     return (r << 16) | (g << 8) | b;
 }
 
+static inline unsigned int rgb_to_pixel32bgr(unsigned int r, unsigned int g, 
unsigned b)
+{
+    return (b << 16) | (g << 8) | r;
+}
+
 #define DEPTH 8
 #include "vga_template.h"
 
@@ -817,6 +842,10 @@ static inline unsigned int rgb_to_pixel3
 #define DEPTH 16
 #include "vga_template.h"
 
+#define DEPTH 32
+#include "vga_template.h"
+
+#define BGR_FORMAT
 #define DEPTH 32
 #include "vga_template.h"
 
@@ -849,6 +878,13 @@ static unsigned int rgb_to_pixel32_dup(u
 {
     unsigned int col;
     col = rgb_to_pixel32(r, g, b);
+    return col;
+}
+
+static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, 
unsigned b)
+{
+    unsigned int col;
+    col = rgb_to_pixel32bgr(r, g, b);
     return col;
 }
 
@@ -948,9 +984,11 @@ static int update_basic_params(VGAState 
     return full_update;
 }
 
-static inline int get_depth_index(int depth)
-{
-    switch(depth) {
+#define NB_DEPTHS 5
+
+static inline int get_depth_index(DisplayState *s)
+{
+    switch(s->depth) {
     default:
     case 8:
         return 0;
@@ -959,28 +997,34 @@ static inline int get_depth_index(int de
     case 16:
         return 2;
     case 32:
-        return 3;
-    }
-}
-
-static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
+        if (s->bgr)
+            return 4;
+        else
+            return 3;
+    }
+}
+
+static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
     vga_draw_glyph8_8,
     vga_draw_glyph8_16,
     vga_draw_glyph8_16,
     vga_draw_glyph8_32,
+    vga_draw_glyph8_32,
 };
 
-static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = {
+static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
     vga_draw_glyph16_8,
     vga_draw_glyph16_16,
     vga_draw_glyph16_16,
     vga_draw_glyph16_32,
+    vga_draw_glyph16_32,
 };
 
-static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
+static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
     vga_draw_glyph9_8,
     vga_draw_glyph9_16,
     vga_draw_glyph9_16,
+    vga_draw_glyph9_32,
     vga_draw_glyph9_32,
 };
     
@@ -1103,7 +1147,7 @@ static void vga_draw_text(VGAState *s, i
     }
     cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
     
-    depth_index = get_depth_index(s->ds->depth);
+    depth_index = get_depth_index(s->ds);
     if (cw == 16)
         vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
     else
@@ -1196,56 +1240,76 @@ enum {
     VGA_DRAW_LINE_NB,
 };
 
-static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
+static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = 
{
     vga_draw_line2_8,
     vga_draw_line2_16,
     vga_draw_line2_16,
     vga_draw_line2_32,
+    vga_draw_line2_32,
 
     vga_draw_line2d2_8,
     vga_draw_line2d2_16,
     vga_draw_line2d2_16,
     vga_draw_line2d2_32,
+    vga_draw_line2d2_32,
 
     vga_draw_line4_8,
     vga_draw_line4_16,
     vga_draw_line4_16,
     vga_draw_line4_32,
+    vga_draw_line4_32,
 
     vga_draw_line4d2_8,

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


 


Rackspace

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