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

[Xen-ia64-devel] [RFC 3/3] hvm-stub for ia64: stubfw



diff -r 092232fa1fbd extras/stubfw/.gdb_history
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/.gdb_history        Fri Nov 09 04:05:17 2007 +0100
@@ -0,0 +1,9 @@
+print 128*1024
+print 128*1024
+print 128*1024
+print 128*1024 - 131056
+print 128*1024 - 131056
+print 128*1024 - 131072
+print /x 2095872
+print /x 2095872
+print /x 2097152
diff -r 092232fa1fbd extras/stubfw/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/Makefile    Thu Nov 22 04:14:03 2007 +0100
@@ -0,0 +1,88 @@
+# Common Makefile for hvmstub fw
+#
+
+XEN_ROOT = ../..
+include $(XEN_ROOT)/Config.mk
+
+XEN_INTERFACE_VERSION := 0x00030207
+export XEN_INTERFACE_VERSION
+
+# Set mini-os root path, used in mini-os.mk.
+STUBFW_ROOT=$(PWD)
+export STUBFW_ROOT
+
+# This is used for architecture specific links.
+# This can be overwritten from arch specific rules.
+ARCH_LINKS =
+
+ARCH_CFLAGS=
+ARCH_ASFLAGS=#-Wa,-xauto
+
+# Include common mini-os makerules.
+include stubfw.mk
+
+# Define some default flags for linking.
+LDLIBS := 
+LDFLAGS := -T stubfw.lds
+
+# The common mini-os objects to build.
+OBJS := main.o startup.o  hobs.o events.o \
+ ioemu/serial.o ioemu/mc146818rtc.o ioemu/pci.o ioemu/irq.o \
+ ioemu/piix_pci.o ioemu/ide.o ioemu/cdrom.o ioemu/block.o ioemu/vl.o \
+ ioemu.o console.o xenbus.o xenbus_test.o gnttab.o vbd.o block-vbd.o \
+ event-asm.o \
+ printf.o string.o __umoddi3.o __divdi3.o __udivdi3.o __udivsi3.o __umodsi3.o
+
+.PHONY: default
+default: stubfw
+
+.PHONY: links
+links: $(ARCH_LINKS)
+       [ -e include/xen ] || ln -sf ../../../xen/include/public include/xen
+
+
+stubfw.elf: links $(OBJS)
+       $(LD) $(LDFLAGS) $(OBJS) -Map stubfw.map -o $@
+
+stubfw.bin: stubfw.elf
+       $(OBJCOPY) -v -O binary $< $@
+
+stubfw: stubfw.bin
+       dd if=/dev/zero of=4M.pad bs=1024 count=4096
+       cat stubfw.bin 4M.pad /usr/lib/xen/boot/efi-vms.bin > $@
+
+.PHONY: clean
+
+
+clean:
+       rm -f *.o *~ ioemu/*.o ioemu/*~ 
+       rm -f core stubfw stubfw.bin stubfw.elf 4M.pad
+       rm -f asm-offset.h as-offset.s
+       find . -type l | xargs rm -f
+       rm -f tags TAGS
+
+
+define all_sources
+     ( find . -follow -name SCCS -prune -o -name '*.[chS]' -print )
+endef
+
+.PHONY: cscope
+cscope:
+       $(all_sources) > cscope.files
+       cscope -k -b -q
+
+.PHONY: tags
+tags:
+       $(all_sources) | xargs ctags
+
+.PHONY: TAGS
+TAGS:
+       $(all_sources) | xargs etags
+
+$(OBJS): $(HDRS) Makefile $(EXTRA_DEPS) asm-offset.h
+
+asm-offset.s: asm-offset.c include/callback.h
+       $(CC) -S -o $@ $(CFLAGS) $(CPPFLAGS) $<
+
+asm-offset.h: asm-offset.s
+       sed -ne "/^->/ {s/->/#define /; p}" < $< > $@
diff -r 092232fa1fbd extras/stubfw/__divdi3.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/__divdi3.S  Wed Nov 07 00:40:13 2007 +0100
@@ -0,0 +1,141 @@
+.file "__divdi3.s"
+
+// $FreeBSD: src/sys/libkern/ia64/__divdi3.S,v 1.1 2000/10/04 17:53:03 dfr Exp 
$
+//  
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, 
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, 
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS 
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+.section .text
+.proc __divdi3#
+.align 32
+.global __divdi3#
+.align 32
+
+// 64-bit signed integer divide
+
+__divdi3:
+
+{ .mii
+  alloc r31=ar.pfs,2,0,0,0
+  nop.i 0
+  nop.i 0;;
+} { .mmi
+
+  // 64-BIT SIGNED INTEGER DIVIDE BEGINS HERE
+
+  setf.sig f8=r32
+  setf.sig f9=r33
+  nop.i 0;;
+} { .mfb
+  nop.m 0
+  fcvt.xf f6=f8
+  nop.b 0
+} { .mfb
+  nop.m 0
+  fcvt.xf f7=f9
+  nop.b 0;;
+} { .mfi
+  nop.m 0
+  // Step (1)
+  // y0 = 1 / b in f8
+  frcpa.s1 f8,p6=f6,f7
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (2)
+  // e0 = 1 - b * y0 in f9
+  (p6) fnma.s1 f9=f7,f8,f1
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // Step (3)
+  // q0 = a * y0 in f10
+  (p6) fma.s1 f10=f6,f8,f0
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (4)
+  // e1 = e0 * e0 in f11
+  (p6) fma.s1 f11=f9,f9,f0
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // Step (5)
+  // q1 = q0 + e0 * q0 in f10
+  (p6) fma.s1 f10=f9,f10,f10
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (6)
+  // y1 = y0 + e0 * y0 in f8
+  (p6) fma.s1 f8=f9,f8,f8
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (7)
+  // q2 = q1 + e1 * q1 in f9
+  (p6) fma.s1 f9=f11,f10,f10
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (8)
+  // y2 = y1 + e1 * y1 in f8
+  (p6) fma.s1 f8=f11,f8,f8
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (9)
+  // r2 = a - b * q2 in f10
+  (p6) fnma.s1 f10=f7,f9,f6
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (10)
+  // q3 = q2 + r2 * y2 in f8
+  (p6) fma.s1 f8=f10,f8,f9
+  nop.i 0;;
+} { .mfb
+  nop.m 0
+  // Step (11)
+  // q = trunc (q3)
+  fcvt.fx.trunc.s1 f8=f8
+  nop.b 0;;
+} { .mmi
+  // quotient will be in r8 (if b != 0)
+  getf.sig r8=f8
+  nop.m 0
+  nop.i 0;;
+}
+
+  // 64-BIT SIGNED INTEGER DIVIDE ENDS HERE
+
+{ .mmb
+  nop.m 0
+  nop.m 0
+  br.ret.sptk b0;;
+}
+
+.endp __divdi3
diff -r 092232fa1fbd extras/stubfw/__udivdi3.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/__udivdi3.S Wed Nov 07 00:40:13 2007 +0100
@@ -0,0 +1,142 @@
+.file "__udivdi3.s"
+
+// $FreeBSD: src/sys/libkern/ia64/__udivdi3.S,v 1.1 2000/10/04 17:53:03 dfr 
Exp $
+//  
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, 
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, 
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS 
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+.section .text
+.proc __udivdi3#
+.align 32
+.global __udivdi3#
+.align 32
+
+// 64-bit unsigned integer divide
+
+__udivdi3:
+
+{ .mii
+  alloc r31=ar.pfs,2,0,0,0
+  nop.i 0
+  nop.i 0;;
+}
+
+{ .mmi
+
+  // 64-BIT UNSIGNED INTEGER DIVIDE BEGINS HERE
+
+  setf.sig f8=r32
+  setf.sig f9=r33
+  nop.i 0;;
+} { .mfb
+  nop.m 0
+  fma.s1 f6=f8,f1,f0
+  nop.b 0
+} { .mfb
+  nop.m 0
+  fma.s1 f7=f9,f1,f0
+  nop.b 0;;
+} { .mfi
+  nop.m 0
+  // Step (1)
+  // y0 = 1 / b in f8
+  frcpa.s1 f8,p6=f6,f7
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (2)
+  // e0 = 1 - b * y0 in f9
+  (p6) fnma.s1 f9=f7,f8,f1
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // Step (3)
+  // q0 = a * y0 in f10
+  (p6) fma.s1 f10=f6,f8,f0
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (4)
+  // e1 = e0 * e0 in f11
+  (p6) fma.s1 f11=f9,f9,f0
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // Step (5)
+  // q1 = q0 + e0 * q0 in f10
+  (p6) fma.s1 f10=f9,f10,f10
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (6)
+  // y1 = y0 + e0 * y0 in f8
+  (p6) fma.s1 f8=f9,f8,f8
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (7)
+  // q2 = q1 + e1 * q1 in f9
+  (p6) fma.s1 f9=f11,f10,f10
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (8)
+  // y2 = y1 + e1 * y1 in f8
+  (p6) fma.s1 f8=f11,f8,f8
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (9)
+  // r2 = a - b * q2 in f10
+  (p6) fnma.s1 f10=f7,f9,f6
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (10)
+  // q3 = q2 + r2 * y2 in f8
+  (p6) fma.s1 f8=f10,f8,f9
+  nop.i 0;;
+} { .mfb
+  nop.m 0
+  // (11) q = trunc(q3)
+  fcvt.fxu.trunc.s1 f8=f8
+  nop.b 0;;
+} { .mmi
+  // quotient will be in r8 (if b != 0)
+  getf.sig r8=f8
+  nop.m 0
+  nop.i 0;;
+}
+
+  // 64-BIT UNSIGNED INTEGER DIVIDE ENDS HERE
+
+{ .mmb
+  nop.m 0
+  nop.m 0
+  br.ret.sptk b0;;
+}
+
+.endp __udivdi3
diff -r 092232fa1fbd extras/stubfw/__udivsi3.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/__udivsi3.S Thu Nov 15 02:04:22 2007 +0100
@@ -0,0 +1,124 @@
+.file "__udivsi3.s"
+
+// $FreeBSD: src/sys/libkern/ia64/__udivsi3.S,v 1.1.8.1 2005/01/31 23:26:21 
imp Exp $
+
+//-
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, 
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, 
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS 
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+.section .text
+
+// 32-bit unsigned integer divide
+
+.proc __udivsi3#
+.align 32
+.global __udivsi3#
+.align 32
+
+__udivsi3:
+
+{ .mii
+  alloc r31=ar.pfs,2,0,0,0
+  nop.i 0
+  nop.i 0;;
+} { .mii
+  nop.m 0
+
+  // 32-BIT UNSIGNED INTEGER DIVIDE BEGINS HERE
+
+  // general register used:
+  //    r32 - 32-bit unsigned integer dividend
+  //    r33 - 32-bit unsigned integer divisor
+  //    r8 - 32-bit unsigned integer result
+  //    r2 - scratch register
+  // floating-point registers used: f6, f7, f8, f9
+  // predicate registers used: p6
+
+  zxt4 r32=r32
+  zxt4 r33=r33;;
+} { .mmb
+  setf.sig f6=r32
+  setf.sig f7=r33
+  nop.b 0;;
+} { .mfi
+  nop.m 0
+  fcvt.xf f6=f6
+  nop.i 0
+} { .mfi
+  nop.m 0
+  fcvt.xf f7=f7
+  mov r2 = 0x0ffdd;;
+} { .mfi
+  setf.exp f9 = r2
+  // (1) y0
+  frcpa.s1 f8,p6=f6,f7
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (2) q0 = a * y0
+  (p6) fma.s1 f6=f6,f8,f0
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // (3) e0 = 1 - b * y0
+  (p6) fnma.s1 f7=f7,f8,f1
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (4) q1 = q0 + e0 * q0
+  (p6) fma.s1 f6=f7,f6,f6
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // (5) e1 = e0 * e0 + 2^-34
+  (p6) fma.s1 f7=f7,f7,f9
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (6) q2 = q1 + e1 * q1
+  (p6) fma.s1 f8=f7,f6,f6
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (7) q = trunc(q2)
+  fcvt.fxu.trunc.s1 f8=f8
+  nop.i 0;;
+} { .mmi
+  // quotient will be in the least significant 32 bits of r8 (if b != 0)
+  getf.sig r8=f8
+  nop.m 0
+  nop.i 0;;
+}
+
+  // 32-BIT UNSIGNED INTEGER DIVIDE ENDS HERE
+
+{ .mmb
+  nop.m 0
+  nop.m 0
+  br.ret.sptk b0;;
+}
+
+.endp __udivsi3
diff -r 092232fa1fbd extras/stubfw/__umoddi3.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/__umoddi3.S Wed Nov 07 00:40:13 2007 +0100
@@ -0,0 +1,154 @@
+.file "__umoddi3.s"
+
+// $FreeBSD: src/sys/libkern/ia64/__umoddi3.S,v 1.3 2003/02/11 20:15:11 
schweikh Exp $
+//  
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, 
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, 
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS 
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+.section .text
+
+  // 64-bit unsigned integer remainder
+
+.proc __umoddi3#
+.align 32
+.global __umoddi3#
+.align 32
+
+__umoddi3:
+
+{ .mii
+  alloc r31=ar.pfs,3,0,0,0
+  nop.i 0
+  nop.i 0
+} { .mmb
+
+  // 64-BIT UNSIGNED INTEGER REMAINDER BEGINS HERE
+
+  // general register used:
+  //    r32 - 64-bit unsigned integer dividend, called a below
+  //    r33 - 64-bit unsigned integer divisor, called b below
+  //    r8 - 64-bit unsigned integer result
+  // floating-point registers used: f6, f7, f8, f9, f10, f11, f12
+  // predicate registers used: p6
+
+  setf.sig f12=r32  // holds a in integer form
+  setf.sig f7=r33
+  nop.b 0;;
+} { .mfi
+  // get 2s complement of b
+  sub r33=r0,r33
+  fcvt.xuf.s1 f6=f12
+  nop.i 0
+} { .mfi
+  nop.m 0
+  fcvt.xuf.s1 f7=f7
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (1)
+  // y0 = 1 / b in f8
+  frcpa.s1 f8,p6=f6,f7
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (2)
+  // q0 = a * y0 in f10
+  (p6) fma.s1 f10=f6,f8,f0
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // Step (3)
+  // e0 = 1 - b * y0 in f9
+  (p6) fnma.s1 f9=f7,f8,f1
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (4)
+  // q1 = q0 + e0 * q0 in f10
+  (p6) fma.s1 f10=f9,f10,f10
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // Step (5)
+  // e1 = e0 * e0 in f11
+  (p6) fma.s1 f11=f9,f9,f0
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (6)
+  // y1 = y0 + e0 * y0 in f8
+  (p6) fma.s1 f8=f9,f8,f8
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (7)
+  // q2 = q1 + e1 * q1 in f9
+  (p6) fma.s1 f9=f11,f10,f10
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (8)
+  // y2 = y1 + e1 * y1 in f8
+  (p6) fma.s1 f8=f11,f8,f8
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (9)
+  // r2 = a - b * q2 in f10
+  (p6) fnma.s1 f10=f7,f9,f6
+  nop.i 0;;
+} { .mfi
+  // f7=-b
+  setf.sig f7=r33
+  // Step (10)
+  // q3 = q2 + r2 * y2 in f8
+  (p6) fma.s1 f8=f10,f8,f9
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (11) q = trunc(q3)
+  fcvt.fxu.trunc.s1 f8=f8
+  nop.i 0;;
+}  { .mfi
+  nop.m 0
+  // (12) r = a + (-b) * q
+  xma.l f8=f8,f7,f12
+  nop.i 0;;
+}  { .mib
+  getf.sig r8=f8
+  nop.i 0
+  nop.b 0
+}
+
+  // 64-BIT UNSIGNED INTEGER REMAINDER ENDS HERE
+
+{ .mib
+  nop.m 0
+  nop.i 0
+  br.ret.sptk b0;;
+}
+
+.endp __umoddi3
diff -r 092232fa1fbd extras/stubfw/__umodsi3.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/__umodsi3.S Thu Nov 15 02:05:23 2007 +0100
@@ -0,0 +1,131 @@
+.file "__umodsi3.s"
+
+// $FreeBSD: src/sys/libkern/ia64/__umodsi3.S,v 1.1.8.1 2005/01/31 23:26:21 
imp Exp $
+
+//-
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, 
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, 
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS 
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+.section .text
+
+// 32-bit unsigned integer remainder
+
+.proc __umodsi3#
+.align 32
+.global __umodsi3#
+.align 32
+
+__umodsi3:
+
+{ .mii
+  alloc r31=ar.pfs,2,0,0,0
+  nop.i 0
+  nop.i 0;;
+} { .mii
+  nop.m 0
+
+  // 32-BIT UNSIGNED INTEGER REMAINDER BEGINS HERE
+
+  // general register used:
+  //    r32 - 32-bit unsigned integer dividend
+  //    r33 - 32-bit unsigned integer divisor
+  //    r8 - 32-bit unsigned integer result
+  //    r2 - scratch register
+  // floating-point registers used: f6, f7, f8, f9, f10, f11
+  // predicate registers used: p6
+
+  zxt4 r32=r32
+  zxt4 r33=r33;;
+} { .mmb
+  setf.sig f11=r32
+  setf.sig f7=r33
+  nop.b 0;;
+} { .mfi
+  nop.m 0
+  fcvt.xf f6=f11
+  nop.i 0
+} { .mfi
+  // get 2's complement of b
+  sub r33=r0,r33
+  fcvt.xf f7=f7
+  mov r2 = 0x0ffdd;;
+} { .mfi
+  setf.exp f9 = r2
+  // (1) y0
+  frcpa.s1 f8,p6=f6,f7
+  nop.i 0;;
+}  { .mfi
+  nop.m 0
+  // (2) q0 = a * y0
+  (p6) fma.s1 f10=f6,f8,f0
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // (3) e0 = 1 - b * y0
+  (p6) fnma.s1 f8=f7,f8,f1
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (4) q1 = q0 + e0 * q0
+  (p6) fma.s1 f10=f8,f10,f10
+  nop.i 0
+} { .mfi
+  // get 2's complement of b
+  setf.sig f7=r33
+  // (5) e1 = e0 * e0 + 2^-34
+  (p6) fma.s1 f8=f8,f8,f9
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (6) q2 = q1 + e1 * q1
+  (p6) fma.s1 f8=f8,f10,f10
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (7) q = trunc(q2)
+  fcvt.fxu.trunc.s1 f8=f8
+  nop.i 0;;
+}  { .mfi
+  nop.m 0
+  // (8) r = a + (-b) * q
+  xma.l f8=f8,f7,f11
+  nop.i 0;;
+}  { .mmi
+  // remainder will be in the least significant 32 bits of r8 (if b != 0)
+  getf.sig r8=f8
+  nop.m 0
+  nop.i 0;;
+}
+
+  // 32-BIT UNSIGNED INTEGER REMAINDER ENDS HERE
+
+{ .mmb
+  nop.m 0
+  nop.m 0
+  br.ret.sptk b0;;
+}
+
+.endp __umodsi3
diff -r 092232fa1fbd extras/stubfw/asm-offset.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/asm-offset.c        Thu Nov 22 04:07:56 2007 +0100
@@ -0,0 +1,54 @@
+#include "callback.h"
+
+#define DEFINE(sym, val)                                       \
+  asm volatile("\n->" sym " %0 /* " #val " */": : "i" (val))
+
+#define CB_OFF(F,N) DEFINE("IA64_CB_"#N, offsetof(struct ia64_cb_regs, F))
+
+int
+main(int argc, char ** argv)
+{
+  CB_OFF (unat, UNAT);
+  CB_OFF (r1, R1);
+  CB_OFF (r2, R2);
+  CB_OFF (r3, R3);
+  CB_OFF (r4, R4);
+  CB_OFF (r5, R5);
+  CB_OFF (r8, R8);
+  CB_OFF (r9, R9);
+  CB_OFF (r10, R10);
+  CB_OFF (r11, R11);
+  CB_OFF (r12, R12);
+  CB_OFF (r13, R13);
+  CB_OFF (r14, R14);
+  CB_OFF (r15, R15);
+  CB_OFF (pr, PR);
+  CB_OFF (b0, B0);
+  CB_OFF (b6, B6);
+  CB_OFF (b7, B7);
+  CB_OFF (fpsr, FPSR);
+  CB_OFF (f6, F6);
+  CB_OFF (f7, F7);
+  CB_OFF (f8, F8);
+  CB_OFF (f9, F9);
+  CB_OFF (f10, F10);
+  CB_OFF (f11, F11);
+  CB_OFF (rsc, RSC);
+  CB_OFF (pfs, PFS);
+  CB_OFF (ccv, CCV);
+  CB_OFF (csd, CSD);
+  CB_OFF (ssd, SSD);
+  CB_OFF (nats, NATS);
+  CB_OFF (ip, IP);
+  CB_OFF (psr, PSR);
+  CB_OFF (cfm, CFM);
+  CB_OFF (rsv, RSV);
+  CB_OFF (bspstore, BSPSTORE);
+  CB_OFF (rnat, RNAT);
+  CB_OFF (ndirty, NDIRTY);
+  CB_OFF (rbs, RBS);
+
+  return 0;
+}
+
+  
diff -r 092232fa1fbd extras/stubfw/asm-offset.i
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/asm-offset.i        Thu Nov 22 04:06:59 2007 +0100
@@ -0,0 +1,995 @@
+#define atomic_subtract_32 atomic_subtract_acq_32
+#define __HYPERVISOR_dom0_op __HYPERVISOR_platform_op
+#define _PTRDIFF_T_ 
+#define GNTCOPY_source_gref (1<<_GNTCOPY_source_gref)
+#define XENMEM_memory_map 9
+#define ASSIGN_readonly (1UL << _ASSIGN_readonly)
+#define ENOANO 55
+#define GTF_writing (1U<<_GTF_writing)
+#define __DBL_MIN_EXP__ (-1021)
+#define local_irq_restore(x) __restore_flags(x)
+#define EMULTIHOP 72
+#define BUG() { printk("mini-os BUG at %s:%d!\n", __FILE__, __LINE__); exit(); 
}
+#define __HYPERVISOR_callback_op 30
+#define GNTST_no_device_space (-7)
+#define FDESC_FUNC(fn) (((struct ia64_fdesc *) fn)->func)
+#define xen_vga_console_info_t dom0_vga_console_info_t
+#define IA64_FPSR_TRAP_UD UL_CONST(0x0000000000000010)
+#define __INT_WCHAR_T_H 
+#define INVALID_MFN (~0UL)
+#define atomic_add_int atomic_add_32
+#define XENFEAT_NR_SUBMAPS 1
+#define MMUEXT_INVLPG_LOCAL 7
+#define atomic_subtract_64 atomic_subtract_acq_64
+#define _ERRNO_BASE_H 
+#define __ia64__ 1
+#define ENOTSOCK 88
+#define __FLT_MIN__ 1.17549435e-38F
+#define __XEN_PUBLIC_GRANT_TABLE_H__ 
+#define XEN_IA64_DEBUG_ON_EXCEPT (1 << 4)
+#define VIRQ_TIMER 0
+#define _T_PTRDIFF_ 
+#define ENOMEM 12
+#define atomic_set_short atomic_set_16
+#define EUSERS 87
+#define HYPERPRIVOP_SSM_I (HYPERPRIVOP_START + 0x6)
+#define _T_WCHAR_ 
+#define EUNATCH 49
+#define XENVER_get_features 6
+#define atomic_cmpset_32 atomic_cmpset_acq_32
+#define IA64_PSR_CPL 0x0000000300000000
+#define XENMEM_decrease_reservation 1
+#define ESTALE 116
+#define __HYPERVISOR_set_timer_op 15
+#define IA64_VEC_DEBUG 29
+#define atomic_clear_64 atomic_clear_acq_64
+#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name)
+#define XENVER_extraversion 1
+#define HYPERPRIVOP_SET_TPR (HYPERPRIVOP_START + 0x9)
+#define EBADFD 77
+#define IA64_PSR_AC 0x0000000000000008
+#define atomic_add_acq_int atomic_add_acq_32
+#define IA64_FPSR_TRAP_ZD UL_CONST(0x0000000000000004)
+#define HYPERPRIVOP_SET_ITM (HYPERPRIVOP_START + 0xb)
+#define __XEN_LATEST_INTERFACE_VERSION__ 0x00030207
+#define MMUEXT_PIN_L4_TABLE 3
+#define XEN_IA64_OPTF_IDENT_MAP_REG7 (1UL << XEN_IA64_OPTF_IDENT_MAP_REG7_BIT)
+#define XENMEM_machine_memory_map 10
+#define uint64_aligned_t uint64_t
+#define atomic_set_acq_char atomic_set_acq_8
+#define __cli() do { vcpu_info_t *_vcpu; _vcpu = 
&HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; 
_vcpu->evtchn_upcall_mask = SWAP(1); barrier(); } while (0)
+#define __CHAR_BIT__ 8
+#define IA64_PSR_BE 0x0000000000000002
+#define IA64_PSR_BN 0x0000100000000000
+#define IA64_VEC_INST_ACCESS 9
+#define EAFNOSUPPORT 97
+#define HYPERPRIVOP_START 0x1
+#define _hypercall0(type,name) ({ long __res; __res = __hypercall(0, 0, 0, 0, 
0, __HYPERVISOR_ ##name); (type)__res; })
+#define _hypercall1(type,name,a1) ({ long __res; __res = __hypercall((unsigned 
long)a1, 0, 0, 0, 0, __HYPERVISOR_ ##name); (type)__res; })
+#define _hypercall2(type,name,a1,a2) ({ long __res; __res = 
__hypercall((unsigned long)a1, (unsigned long)a2, 0, 0, 0, __HYPERVISOR_ 
##name); (type)__res; })
+#define _hypercall3(type,name,a1,a2,a3) ({ long __res; __res = 
__hypercall((unsigned long)a1, (unsigned long)a2, (unsigned long)a3, 0, 0, 
__HYPERVISOR_ ##name); (type)__res; })
+#define _hypercall4(type,name,a1,a2,a3,a4) ({ long __res; __res = 
__hypercall((unsigned long)a1, (unsigned long)a2, (unsigned long)a3, (unsigned 
long)a4, 0, __HYPERVISOR_ ##name); (type)__res; })
+#define __SIZE_T__ 
+#define __HYPERVISOR_domctl 36
+#define EACCES 13
+#define GNTST_bad_handle (-4)
+#define EVTCHNSTAT_pirq 3
+#define HYPERPRIVOP_GET_PMD (HYPERPRIVOP_START + 0x14)
+#define IA64_PSR_DB 0x0000000001000000
+#define IA64_PSR_DD 0x0000008000000000
+#define EDESTADDRREQ 89
+#define IA64_PSR_DI 0x0000000000400000
+#define IA64_DCR_BE 1
+#define IA64_PSR_DT 0x0000000000020000
+#define CONSOLEIO_write 0
+#define HYPERPRIVOP_FC (HYPERPRIVOP_START + 0x12)
+#define IA64_PSR_CPL_USER 0x0000000300000000
+#define _SYS_SIZE_T_H 
+#define IA64_PSR_ED 0x0000080000000000
+#define IA64_DCR_MBZ0 4
+#define IA64_DCR_MBZ1 2
+#define XMAPPEDREGS_OFS XSI_SIZE
+#define GNTTABOP_unmap_grant_ref 1
+#define EVTCHNOP_bind_interdomain 0
+#define HVMSTUB_HYPERCALL_SET_CALLBACK 0x801
+#define VMASST_CMD_disable 1
+#define __XEN_PUBLIC_HVM_HVM_OP_H__ 
+#define IA64_ISR_EI_0 0x0000000000000000
+#define IA64_ISR_EI_1 0x0000020000000000
+#define IA64_ISR_EI_2 0x0000040000000000
+#define IA64_DCR_DA 13
+#define IA64_DCR_DD 14
+#define ELOOP 40
+#define IA64_DCR_DK 10
+#define IA64_DCR_DM 8
+#define EILSEQ 84
+#define va_start(v,l) __builtin_va_start(v,l)
+#define IA64_DCR_DP 9
+#define IA64_DCR_DR 12
+#define MMUEXT_PIN_L2_TABLE 1
+#define _HYPERVISOR_H_ 
+#define IA64_DCR_DX 11
+#define _IA64_FPU_H_ 
+#define ESPIPE 29
+#define XSI_SIZE (1 << XSI_SHIFT)
+#define PIB_START 0xfee00000UL
+#define IA64_VEC_BREAK 11
+#define EMLINK 31
+#define set_xen_guest_handle(hnd,val) do { (hnd).p = val; } while (0)
+#define DOMID_XEN (0x7FF2U)
+#define XENVER_platform_parameters 5
+#define atomic_subtract_acq_char atomic_subtract_acq_8
+#define __WCHAR_MAX__ 2147483647
+#define PRINT_BV(_fmt,_params...) if (bootverbose) printk(_fmt , ## _params)
+#define atomic_set_char atomic_set_8
+#define XEN_IA64_DEBUG_ON_TC (1 << 16)
+#define __XEN_PUBLIC_FEATURES_H__ 
+#define XEN_IA64_DEBUG_ON_TR (1 << 15)
+#define IA64_SF_DEFAULT (IA64_SF_PC_3 | IA64_SF_RC_NEAREST)
+#define EL2HLT 51
+#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
+#define atomic_set_int atomic_set_32
+#define IA64_PSR_IA 0x0000200000000000
+#define IA64_PSR_IC (1<<IA64_PSR_IC_BIT)
+#define IA64_PSR_ID 0x0000002000000000
+#define __save_flags(x) do { vcpu_info_t *_vcpu; _vcpu = 
&HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; (x) = 
SWAP(_vcpu->evtchn_upcall_mask); } while (0)
+#define GNTTABOP_copy 5
+#define __va_copy(d,s) __builtin_va_copy(d,s)
+#define IA64_PSR_IS 0x0000000400000000
+#define IA64_PSR_IT 0x0000001000000000
+#define MMU_NORMAL_PT_UPDATE 0
+#define safe_halt() ((void)0)
+#define ENOKEY 126
+#define LEGACY_IO_SIZE (64*MEM_M)
+#define __HYPERVISOR_xsm_op 27
+#define HYPERPRIVOP_GET_PSR (HYPERPRIVOP_START + 0x18)
+#define __FLT_EVAL_METHOD__ 0
+#define HVMOP_get_param 1
+#define XENFEAT_writable_descriptor_tables 1
+#define __unix__ 1
+#define EINVAL 22
+#define _ANSI_STDARG_H_ 
+#define __HYPERVISOR_mmuext_op 26
+#define UVMF_INVLPG (2UL<<0)
+#define UVMF_TLB_FLUSH (1UL<<0)
+#define IA64_RR_IDX_POS 61
+#define unix 1
+#define IA64_PSR_LP 0x0000000002000000
+#define __HYPERVISOR_vcpu_op 24
+#define VGA_IO_SIZE 0x20000
+#define GTF_transfer_committed (1U<<_GTF_transfer_committed)
+#define __XEN_PUBLIC_SCHED_H__ 
+#define ESHUTDOWN 108
+#define PTE_PL_KERN 0
+#define IA64_PSR_MC 0x0000000800000000
+#define EKEYREJECTED 129
+#define _BSD_SIZE_T_ 
+#define IA64_PSR_DFH 0x0000000000080000
+#define __SIZE_TYPE__ long unsigned int
+#define _SIZE_T_DECLARED 
+#define irqs_disabled() 
SWAP(HYPERVISOR_shared_info->vcpu_info[smp_processor_id()].evtchn_upcall_mask)
+#define IA64_VEC_DATA_ACCESS_RIGHTS 23
+#define IA64_DOM0VP_unexpose_foreign_p2m 13
+#define XENVER_pagesize 7
+#define EVTCHNOP_send 4
+#define IA64_DCR_LC 2
+#define XEN_IA64_DEBUG_OP_SET_FLAGS 1
+#define IA64_PSR_DFL 0x0000000000040000
+#define atomic_set_16 atomic_set_acq_16
+#define EOWNERDEAD 130
+#define SCHEDOP_block 1
+#define XENMEM_machphys_mapping 12
+#define SHUTDOWN_crash 3
+#define _GNTCOPY_dest_gref (1)
+#define __ia64 1
+#define EVTCHNSTAT_closed 0
+#define IA64_RR_MBZ1 32
+#define UL_TYPE(x) ((uint64_t)x)
+#define __ELF__ 1
+#define ENOMEDIUM 123
+#define __DBL_MIN_10_EXP__ (-307)
+#define IA64_PSR_PK 0x0000000000008000
+#define IA64_PSR_PP 0x0000000000200000
+#define PTE_OFF_AR 9
+#define ENOTTY 25
+#define __FINITE_MATH_ONLY__ 0
+#define atomic_set_32 atomic_set_acq_32
+#define XEN_IA64_DEBUG_ON_SAL (1 << 8)
+#define atomic_clear_rel_short atomic_clear_rel_16
+#define wmb() mb()
+#define __HYPERVISOR_set_callbacks 4
+#define MAX_VIRT_CPUS 64
+#define atomic_add_rel_short atomic_add_rel_16
+#define EBADE 52
+#define EBADF 9
+#define ELIBSCN 81
+#define CONSOLEIO_read 1
+#define XEN_IA64_DEBUG_OP_TRANSLATE 4
+#define EBADR 53
+#define GTF_PAT (1U<<_GTF_PAT)
+#define IA64_PSR_RI 0x0000060000000000
+#define __STDDEF_H__ 
+#define MMUEXT_NEW_USER_BASEPTR 15
+#define IA64_VEC_VHPT 0
+#define IA64_PSR_RT 0x0000000008000000
+#define IA64_DCR_PP 0
+#define SCHEDOP_remote_shutdown 4
+#define atomic_set_rel_short atomic_set_rel_16
+#define EADV 68
+#define ERANGE 34
+#define __GNUC_PATCHLEVEL__ 5
+#define ECANCELED 125
+#define __FLT_RADIX__ 2
+#define IA64_PSR_SI 0x0000000000800000
+#define IA64_PSR_SP 0x0000000000100000
+#define IA64_PSR_SS 0x0000010000000000
+#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
+#define IA64_RSC_LOADRS_LEN 14
+#define __HYPERVISOR_get_debugreg 9
+#define MMUEXT_TLB_FLUSH_LOCAL 6
+#define atomic_add_char atomic_add_8
+#define GTF_PCD (1U<<_GTF_PCD)
+#define atomic_set_64 atomic_set_acq_64
+#define MMUEXT_PIN_L1_TABLE 0
+#define __HYPERVISOR_nmi_op 28
+#define __size_t 
+#define XEN_IA64_DEBUG_ON_KERN_DEBUG (1 << 1)
+#define _WCHAR_T_DEFINED 
+#define ETXTBSY 26
+#define IA64_PSR_UP 0x0000000000000004
+#define ENAVAIL 119
+#define atomic_add_8 atomic_add_acq_8
+#define _GNTMAP_device_map (0)
+#define _ERRNO_H 
+#define CB_OFF(F,N) DEFINE("IA64_CB_"#N, offsetof(struct ia64_cb_regs, F))
+#define IA64_RR_PS 2
+#define EVTCHNSTAT_ipi 5
+#define EVTCHNOP_bind_virq 1
+#define __HYPERVISOR_ia64_dom0vp_op __HYPERVISOR_arch_0
+#define IA64_VEC_IA32_INTERCEPT 46
+#define HYPERPRIVOP_RSM_DT (HYPERPRIVOP_START + 0x1)
+#define __SHRT_MAX__ 32767
+#define SIF_INITDOMAIN (1<<1)
+#define PTE_AR_RX_RWX 5
+#define HYPERPRIVOP_COVER (HYPERPRIVOP_START + 0x3)
+#define __LDBL_MAX__ 1.18973149535723176502e+4932L
+#define _GTF_transfer_completed (3)
+#define GNTST_permission_denied (-8)
+#define MMUEXT_INVLPG_MULTI 9
+#define EVTCHNOP_status 5
+#define atomic_subtract_long atomic_subtract_64
+#define IA64_SF_D UL_CONST(0x0100)
+#define IA64_PSR_CPL_1 0x0000000100000000
+#define IA64_PSR_CPL_2 0x0000000200000000
+#define atomic_subtract_rel_long atomic_subtract_rel_64
+#define XEN_CHANGESET_INFO_LEN (sizeof(xen_changeset_info_t))
+#define SCHEDOP_yield 0
+#define HVMOP_set_param 0
+#define __HYPERVISOR_event_channel_op_compat 16
+#define MMU_MACHPHYS_UPDATE 1
+#define IA64_ISR_R 0x0000000400000000
+#define XENMEM_translate_gpfn_list 8
+#define XENVER_version 0
+#define HYPERPRIVOP_GET_RR (HYPERPRIVOP_START + 0xf)
+#define IA64_DOM0VP_add_io_space 11
+#define barrier() __asm__ __volatile__("": : :"memory")
+#define EBUSY 16
+#define EINPROGRESS 115
+#define __HYPERVISOR_platform_op 7
+#define _LIB_H_ 
+#define IA64_RR_VE 0
+#define __OS_H__ 
+#define GNTST_general_error (-1)
+#define _SIZE_T_ 
+#define IA64_SF_FTZ UL_CONST(0x0001)
+#define mk_unsigned_long(x) __mk_unsigned_long(x)
+#define __linux 1
+#define MOS_IA64_PSR_BE 0
+#define _WCHAR_T_H 
+#define EPROTO 71
+#define ENODEV 19
+#define __HYPERVISOR_xen_version 17
+#define __HYPERVISOR_set_segment_base 25
+#define __unix 1
+#define ASSERT(x) do { if (!(x)) { printk("ASSERTION FAILED: %s at %s:%d.\n", 
#x , __FILE__, __LINE__); BUG(); } } while(0)
+#define PTE_OFF_PL 7
+#define atomic_cmpset_rel_long atomic_cmpset_rel_64
+#define HYPERPRIVOP_GET_TPR (HYPERPRIVOP_START + 0x8)
+#define GFW_SIZE (16*MEM_M)
+#define INT_MAX ((int)(~0U>>1))
+#define __HYPERVISOR_console_io 18
+#define likely(x) __builtin_expect(!!(x), 1)
+#define EMSGSIZE 90
+#define IA64_SF_RC_POSINF UL_CONST(0x0020)
+#define MOS_IA64_DCR_BE (0 << IA64_DCR_BE)
+#define PAGE_SHIFT 14
+#define __SIZE_T 
+#define EREMCHG 78
+#define XEN_IA64_DEBUG_OP_GET_FLAGS 2
+#define EKEYEXPIRED 127
+#define __HYPERCALL_H__ 
+#define __LDBL_MAX_EXP__ 16384
+#define EROFS 30
+#define ENOTEMPTY 39
+#define GNTTABOP_transfer 4
+#define ENOTBLK 15
+#define IA64_VEC_NAT_CONSUMPTION 26
+#define IA64_RSC_LOADRS 16
+#define UVMF_NONE (0UL<<0)
+#define HYPERPRIVOP_GET_IVR (HYPERPRIVOP_START + 0x7)
+#define __HYPERVISOR_opt_feature 0x700UL
+#define EPROTOTYPE 91
+#define ERESTART 85
+#define IA64_AR(name) static __inline uint64_t ia64_get_ ##name(void) { 
uint64_t result; __asm __volatile(";;mov %0=ar." #name ";;" : "=r" (result)); 
return result; } static __inline void ia64_set_ ##name(uint64_t v) { __asm 
__volatile("mov ar." #name "=%0" :: "r" (v)); }
+#define EVTCHNOP_bind_ipi 7
+#define _hypercall5(type,name,a1,a2,a3,a4,a5) ({ long __res; __res = 
__hypercall((unsigned long)a1, (unsigned long)a2, (unsigned long)a3, (unsigned 
long)a4, (unsigned long)a5, __HYPERVISOR_ ##name); (type)__res; })
+#define EISNAM 120
+#define local_irq_enable() __sti()
+#define __LONG_MAX__ 9223372036854775807L
+#define __linux__ 1
+#define __HYPERVISOR_update_va_mapping_otherdomain 22
+#define ELIBACC 79
+#define va_copy(d,s) __builtin_va_copy(d,s)
+#define _GNTMAP_readonly (2)
+#define GTF_reading (1U<<_GTF_reading)
+#define atomic_set_rel_int atomic_set_rel_32
+#define ENOMSG 42
+#define IA64_RSC_BE 4
+#define _SIZE_T_DEFINED_ 
+#define IA64_CR(name) static __inline uint64_t ia64_get_ ##name(void) { 
uint64_t result; __asm __volatile("mov %0=cr." #name : "=r" (result)); return 
result; } static __inline void ia64_set_ ##name(uint64_t v) { __asm 
__volatile("mov cr." #name "=%0" :: "r" (v)); }
+#define _BSD_PTRDIFF_T_ 
+#define __HYPERVISOR_physdev_op __HYPERVISOR_physdev_op_compat
+#define __SCHAR_MAX__ 127
+#define EALREADY 114
+#define IA64_DOM0VP_perfmon 8
+#define _GTF_writing (4)
+#define MMIO_START (3 * MEM_G)
+#define XEN_IA64_DEBUG_ON_EXTINT (1 << 3)
+#define NULL ((void *)0)
+#define IA64_PSR_UMASK (IA64_PSR_BE | IA64_PSR_UP | IA64_PSR_AC | IA64_PSR_MFL 
| IA64_PSR_MFH)
+#define PTE_AR_R 0
+#define VIRQ_ITC VIRQ_ARCH_0
+#define __HYPERVISOR_IF_IA64_H__ 
+#define GNTST_bad_page (-9)
+#define E2BIG 7
+#define __DBL_DIG__ 15
+#define HYPERVISOR_console_io xencomm_arch_console_io
+#define PTE_PL_SHIFT 7
+#define atomic_clear_rel_char atomic_clear_rel_8
+#define _VA_LIST_DEFINED 
+#define XEN_IA64_DEBUG_ON_BAD_MPA (1 << 12)
+#define HYPERPRIVOP_THASH (HYPERPRIVOP_START + 0xc)
+#define IA64_DOM0VP_add_physmap_with_gmfn 9
+#define EVTCHNOP_alloc_unbound 6
+#define STARTUP_PSR (IA64_PSR_IT | IA64_PSR_PK | IA64_PSR_DT | IA64_PSR_RT | 
MOS_IA64_PSR_BE | IA64_PSR_BN | IA64_PSR_CPL_KERN | IA64_PSR_AC)
+#define EVTCHNSTAT_virq 4
+#define IA64_PKR_RD 2
+#define _GTF_readonly (2)
+#define PTE_A 1
+#define EDEADLK 35
+#define IA64_ITIR_MBZ0 0
+#define IA64_ITIR_MBZ1 32
+#define IA64_ITIR_MBZ2 63
+#define HYPERVISOR_sched_op xencomm_arch_sched_op
+#define EL3RST 47
+#define IA64_GR(name) static __inline uint64_t ia64_get_ ##name(void) { 
uint64_t result; __asm __volatile("mov %0=" #name : "=r" (result)); return 
result; } static __inline void ia64_set_ ##name(uint64_t v) { __asm 
__volatile("mov " #name "=%0" :: "r" (v)); }
+#define local_save_flags(x) __save_flags(x)
+#define HVMOP_set_pci_intx_level 2
+#define GTF_PWT (1U<<_GTF_PWT)
+#define atomic_clear_16 atomic_clear_acq_16
+#define GFW_START (4*MEM_G -16*MEM_M)
+#define IA64_PSR_CPL_KERN 0x0000000000000000
+#define __XEN_PUBLIC_XEN_COMPAT_H__ 
+#define IA64_DOM0VP_machtophys 3
+#define SCHEDOP_shutdown 2
+#define ASSIGN_tlb_track (1UL << _ASSIGN_tlb_track)
+#define VGA_IO_START 0xA0000UL
+#define ENOTDIR 20
+#define EDOM 33
+#define HYPERVISOR_event_channel_op xencomm_arch_event_channel_op
+#define __HYPERVISOR_set_trap_table 0
+#define __HYPERVISOR_fpu_taskswitch 5
+#define local_irq_save(x) __save_and_cli(x)
+#define ETIMEDOUT 110
+#define IA64_VEC_PAGE_NOT_PRESENT 20
+#define __XEN_PUBLIC_XEN_H__ 
+#define ECONNRESET 104
+#define HVMOP_set_pci_link_route 4
+#define __USER_LABEL_PREFIX__ 
+#define atomic_add_16 atomic_add_acq_16
+#define IA64_VEC_EXT_INTR 12
+#define HYPERPRIVOP_EOI (HYPERPRIVOP_START + 0xa)
+#define HYPERPRIVOP_GET_CPUID (HYPERPRIVOP_START + 0x13)
+#define _ASSIGN_pgc_allocated 3
+#define IA64_PSR_MFH (1 << IA64_PSR_MFH_BIT)
+#define ENODATA 61
+#define _ASSIGN_readonly 0
+#define linux 1
+#define IA64_PKR_WD 1
+#define __DEFINE_XEN_GUEST_HANDLE(name,type) typedef type * __guest_handle_ ## 
name
+#define IA64_DOM0VP_expose_foreign_p2m 12
+#define ENXIO 6
+#define atomic_cmpset_long atomic_cmpset_64
+#define IA64_RSC_PL 2
+#define IA64_VEC_KEY_PERMISSION 21
+#define IA64_PKR_XD 3
+#define atomic_add_32 atomic_add_acq_32
+#define EOVERFLOW 75
+#define EVTCHNSTAT_interdomain 2
+#define IA64_RSC_MBZ0_V 0x3ff
+#define __STDC_HOSTED__ 1
+#define EBADRQC 56
+#define IO_PAGE_START (LEGACY_IO_START + LEGACY_IO_SIZE)
+#define IA64_PSR_RI_SHIFT 41
+#define XENMEM_current_reservation 3
+#define __HYPERVISOR_multicall 13
+#define IA64_PSR_I_BIT 14
+#define XEN_IA64_OPTF_ON 0x1
+#define MMUEXT_TLB_FLUSH_MULTI 8
+#define HYPERPRIVOP_SSM_DT (HYPERPRIVOP_START + 0x2)
+#define ENOSTR 60
+#define IA64_DOM0VP_fpswa_revision 10
+#define __aligned(x) __attribute__((__aligned__(x)))
+#define XENMEM_maximum_reservation 4
+#define IA64_PKR_KEY_LEN 24
+#define IA64_PSR_MFL 0x0000000000000010
+#define atomic_add_64 atomic_add_acq_64
+#define __LDBL_MANT_DIG__ 64
+#define NR_VIRQS 24
+#define GTF_type_mask (3U<<0)
+#define _BSD_SIZE_T_DEFINED_ 
+#define __itanium__ 1
+#define IA64_PSR_MFH_BIT 5
+#define __HYPERVISOR_mmu_update 1
+#define ENAMETOOLONG 36
+#define FDESC_GP(fn) (((struct ia64_fdesc *) fn)->gp)
+#define EINTR 4
+#define PTE_OFF_A 5
+#define PTE_OFF_D 6
+#define __HYPERVISOR_update_va_mapping 14
+#define HYPERPRIVOP_RFI (HYPERPRIVOP_START + 0x0)
+#define PTE_OFF_P 0
+#define IA64_VEC_ITLB 1
+#define __FLT_EPSILON__ 1.19209290e-7F
+#define IA64_DOM0VP_zap_physmap 5
+#define _LONGLONG 1
+#define ENOLINK 67
+#define VIRQ_CONSOLE 2
+#define XEN_IA64_DEBUG_ON_EVENT (1 << 5)
+#define GNTMAP_host_map (1<<_GNTMAP_host_map)
+#define XENMAPSPACE_grant_table 1
+#define __GNUC_VA_LIST 
+#define atomic_subtract_8 atomic_subtract_acq_8
+#define XEN_GUEST_HANDLE_00030205(type) type *
+#define IA64_ITIR_PPN_LEN 15
+#define HVMOP_flush_tlbs 5
+#define IA64_PSR_I (1<<IA64_PSR_I_BIT)
+#define PTE_PS_16K 14
+#define PTE_AR_RWX_RW 6
+#define __HYPERVISOR_arch_0 48
+#define __HYPERVISOR_arch_1 49
+#define __HYPERVISOR_arch_2 50
+#define __HYPERVISOR_arch_3 51
+#define __HYPERVISOR_arch_4 52
+#define __HYPERVISOR_arch_5 53
+#define __HYPERVISOR_arch_6 54
+#define __HYPERVISOR_arch_7 55
+#define PTE_PS_16M 24
+#define VMASST_TYPE_4gb_segments_notify 1
+#define IA64_VEC_DISABLED_FP 25
+#define atomic_set_8 atomic_set_acq_8
+#define ESOCKTNOSUPPORT 94
+#define atomic_add_acq_long atomic_add_acq_64
+#define __LDBL_MIN__ 3.36210314311209350626e-4932L
+#define MMUEXT_PIN_L3_TABLE 2
+#define __WCHAR_TYPE__ int
+#define atomic_clear_32 atomic_clear_acq_32
+#define atomic_subtract_acq_long atomic_subtract_acq_64
+#define atomic_set_long atomic_set_64
+#define MMUEXT_TLB_FLUSH_ALL 10
+#define _GNTMAP_contains_pte (4)
+#define IA64_VEC_SPECULATION 27
+#define IA64_PSR_TB 0x0000000004000000
+#define IA64_FPSR_TRAP_VD UL_CONST(0x0000000000000001)
+#define ELIBEXEC 83
+#define PTE_PS_8K 13
+#define MAX_GUEST_CMDLINE 1024
+#define _ANSI_STDDEF_H 
+#define IA64_PSR_DA 0x0000004000000000
+#define atomic_add_rel_long atomic_add_rel_64
+#define ENOPKG 65
+#define _WCHAR_T_ 
+#define VIRQ_DEBUGGER 6
+#define EPERM 1
+#define EDOTDOT 73
+#define _STDDEF_H 
+#define atomic_subtract_rel_short atomic_subtract_rel_16
+#define XENFEAT_pae_pgdir_above_4gb 4
+#define IA64_PKR_VALID (1 << IA64_PKR_V)
+#define EADDRNOTAVAIL 99
+#define __XEN_PUBLIC_VERSION_H__ 
+#define ETIME 62
+#define IO_PORTS_SIZE 0x0000000004000000UL
+#define IA64_VEC_UNALIGNED_REFERENCE 30
+#define PRI_xen_pfn "lx"
+#define IA64_DCR_DEFAULT (MOS_IA64_DCR_BE)
+#define __FLT_DIG__ 6
+#define rmb() mb()
+#define __FLT_MAX_10_EXP__ 38
+#define IA64_SF_PC UL_CONST(0x000c)
+#define _WCHAR_T_DECLARED 
+#define atomic_cmpset_acq_long atomic_cmpset_acq_64
+#define atomic_set_acq_short atomic_set_acq_16
+#define atomic_add_acq_short atomic_add_acq_16
+#define _IA64_CPU_H_ 
+#define IA64_ITIR_PPN 48
+#define xen_vga_console_info dom0_vga_console_info
+#define HYPERVISOR_callback_op xencomm_arch_callback_op
+#define XEN_IA64_DEBUG_FORCE_DB (1 << 14)
+#define MOS_USR_PSR (IA64_PSR_IC | IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT | 
IA64_PSR_RT | MOS_IA64_PSR_BE | IA64_PSR_BN | IA64_PSR_CPL_USER | IA64_PSR_AC)
+#define IA64_PKR_V 0
+#define __HYPERVISOR_ia64_debug_op __HYPERVISOR_arch_2
+#define __INT_MAX__ 2147483647
+#define atomic_clear_char atomic_clear_8
+#define UL_CONST(x) x ##UL
+#define IA64_SF_RC UL_CONST(0x0030)
+#define IA64_PKR_MBZ0 4
+#define IA64_PKR_MBZ1 32
+#define __gnu_linux__ 1
+#define IA64_RSE_EAGER ((IA64_RSC_MODE_EA<<IA64_RSC_MODE) | (MOS_IA64_RSC_BE 
<< IA64_RSC_BE) )
+#define HYPERPRIVOP_SET_KR (HYPERPRIVOP_START + 0x11)
+#define GNTCOPY_dest_gref (1<<_GNTCOPY_dest_gref)
+#define XEN_IA64_DEBUG_ON_PAL (1 << 7)
+#define ENETDOWN 100
+#define EPROTONOSUPPORT 93
+#define UINT_MAX (~0U)
+#define _T_SIZE_ 
+#define VIRQ_CON_RING 8
+#define ENOTRECOVERABLE 131
+#define IA64_SF_TD UL_CONST(0x0040)
+#define atomic_set_rel_char atomic_set_rel_8
+#define XEN_IA64_DEBUG_ON_EFI (1 << 9)
+#define _ASSIGN_tlb_track 2
+#define EIO 5
+#define __FLT_MAX_EXP__ 128
+#define atomic_set_acq_int atomic_set_acq_32
+#define ENOSR 63
+#define ENETUNREACH 101
+#define EXDEV 18
+#define atomic_readandclear_long atomic_readandclear_64
+#define xchg xchg8
+#define __DECIMAL_DIG__ 21
+#define synch_cmpxchg(ptr,old,new) ((__typeof__(*(ptr)))__synch_cmpxchg((ptr), 
(unsigned long)(old), (unsigned long)(new), sizeof(*(ptr))))
+#define __DBL_MANT_DIG__ 53
+#define ___int_size_t_h 
+#define _GNTMAP_application_map (3)
+#define __restore_flags(x) do { vcpu_info_t *_vcpu; barrier(); _vcpu = 
&HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; if 
((_vcpu->evtchn_upcall_mask = (x)) == 0) { barrier(); if ( 
unlikely(SWAP(_vcpu->evtchn_upcall_pending)) ) force_evtchn_callback(); }} 
while (0)
+#define atomic_subtract_rel_int atomic_subtract_rel_32
+#define ECHILD 10
+#define IA64_RR_MBZ0 1
+#define GTF_transfer_completed (1U<<_GTF_transfer_completed)
+#define ___int_wchar_t_h 
+#define __WINT_TYPE__ unsigned int
+#define EDQUOT 122
+#define IA64_SF_WRE UL_CONST(0x0002)
+#define _T_PTRDIFF 
+#define __GNUC__ 3
+#define atomic_clear_rel_int atomic_clear_rel_32
+#define MOS_SYS_PSR (IA64_PSR_IC | IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT | 
IA64_PSR_RT | MOS_IA64_PSR_BE | IA64_PSR_BN | IA64_PSR_CPL_KERN | IA64_PSR_AC)
+#define IA64_RR_RID_LEN 24
+#define IA64_DOM0VP_iounmap 4
+#define IA64_RR_PS_LEN 6
+#define HYPERPRIVOP_PTC_GA (HYPERPRIVOP_START + 0xd)
+#define offsetof(TYPE,MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#define __LDBL_MIN_EXP__ (-16381)
+#define atomic_clear_acq_char atomic_clear_acq_8
+#define XENVER_capabilities 3
+#define IA64_VEC_INST_ACCESS_RIGHTS 22
+#define IA64_VEC_IA32_EXCEPTION 45
+#define __HYPERVISOR_hvm_op 34
+#define XEN_GUEST_HANDLE_64(name) XEN_GUEST_HANDLE(name)
+#define XEN_PAGE_SIZE PAGE_SIZE
+#define __HYPERVISOR_event_channel_op __HYPERVISOR_event_channel_op_compat
+#define __HYPERVISOR_set_gdt 2
+#define EREMOTEIO 121
+#define IA64_DOM0VP_ioremap 0
+#define HVMOP_set_isa_irq_level 3
+#define IA64_VEC_TAKEN_BRANCH_TRAP 35
+#define ENOSPC 28
+#define IA64_FPSR_SF(i,v) ((v) << ((i)*13+6))
+#define ENOEXEC 8
+#define UVMF_FLUSHTYPE_MASK (3UL<<0)
+#define atomic_cmpset_64 atomic_cmpset_acq_64
+#define GNTTABOP_error_msgs { "okay", "undefined error", "unrecognised domain 
id", "invalid grant reference", "invalid mapping handle", "invalid virtual 
address", "invalid device address", "no spare translation slot in the I/O MMU", 
"permission denied", "bad page", "copy arguments cross page boundary" }
+#define BUFFER_IO_PAGE_SIZE XEN_PAGE_SIZE
+#define atomic_clear_8 atomic_clear_acq_8
+#define atomic_clear_acq_short atomic_clear_acq_16
+#define ELNRNG 48
+#define IA64_VEC_FLOATING_POINT_TRAP 33
+#define __HYPERVISOR_memory_op 12
+#define VIRQ_DEBUG 1
+#define PTE_AR_RWX 3
+#define IA64_RSC_MODE_EA (0x3)
+#define XENMEM_populate_physmap 6
+#define SCHEDOP_poll 3
+#define __LDBL_MAX_10_EXP__ 4932
+#define XEN_CAPABILITIES_INFO_LEN (sizeof(xen_capabilities_info_t))
+#define XENMEM_maximum_ram_page 2
+#define __save_and_cli(x) do { vcpu_info_t *_vcpu; _vcpu = 
&HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; (x) = 
SWAP(_vcpu->evtchn_upcall_mask); _vcpu->evtchn_upcall_mask = SWAP(1); 
barrier(); } while (0)
+#define __DBL_EPSILON__ 2.2204460492503131e-16
+#define EVTCHNSTAT_unbound 1
+#define IA64_VEC_DIRTY_BIT 8
+#define get_xen_guest_handle(val,hnd) do { val = (hnd).p; } while (0)
+#define _SIZET_ 
+#define __HYPERVISOR_update_descriptor 10
+#define XEN_IA64_DEBUG_ON_PRIVOP (1 << 6)
+#define _LP64 1
+#define BUFFER_PIO_PAGE_START (BUFFER_IO_PAGE_START + BUFFER_IO_PAGE_SIZE)
+#define DOMID_IO (0x7FF1U)
+#define EFBIG 27
+#define __DBL_MAX__ 1.7976931348623157e+308
+#define SHUTDOWN_suspend 2
+#define GNTTABOP_unmap_and_replace 7
+#define ESRCH 3
+#define IA64_SF_RC_NEAREST UL_CONST(0x0000)
+#define ECHRNG 44
+#define GTF_invalid (0U<<0)
+#define EHOSTDOWN 112
+#define UVMF_ALL (1UL<<2)
+#define GNTTABOP_dump_table 3
+#define __wchar_t__ 
+#define XEN_IA64_DEBUG_FORCE_SS (1 << 13)
+#define ECOMM 70
+#define XMAPPEDREGS_SIZE (1 << XMAPPEDREGS_SHIFT)
+#define XEN_VGATYPE_VESA_LFB 0x23
+#define UVMF_LOCAL (0UL<<2)
+#define EVTCHNOP_unmask 9
+#define XENVER_changeset 4
+#define ENOLCK 37
+#define PTE_PS_256M 28
+#define ENFILE 23
+#define IA64_VEC_DKEY_MISS 7
+#define PTE_AR_RW 2
+#define PTE_AR_RX 1
+#define XENMAPSPACE_shared_info 0
+#define STORE_PAGE_SIZE XEN_PAGE_SIZE
+#define _STDDEF_H_ 
+#define IO_PORTS_PADDR 0x00000ffffc000000UL
+#define _GTF_reading (3)
+#define HYPERPRIVOP_MAX (0x1a)
+#define ENOSYS 38
+#define EPIPE 32
+#define XEN_IA64_DEBUG_ON_RFI (1 << 10)
+#define IA64_RSC_MODE_LI (0x2)
+#define PTE_MA_SHIFT 2
+#define IA64_RSC_MODE_LY (0x0)
+#define IA64_RSC_MODE 0
+#define atomic_subtract_short atomic_subtract_16
+#define ENOTCONN 107
+#define _SIZE_T_DEFINED 
+#define GNTST_bad_dev_addr (-6)
+#define va_arg(v,l) __builtin_va_arg(v,l)
+#define GTF_readonly (1U<<_GTF_readonly)
+#define IA64_ITIR_KEY 8
+#define _WCHAR_T_DEFINED_ 
+#define IA64_DOM0VP_phystomach 1
+#define MMUEXT_FLUSH_CACHE 12
+#define EBADMSG 74
+#define IA64_DOM0VP_add_physmap 6
+#define GNTMAP_contains_pte (1<<_GNTMAP_contains_pte)
+#define atomic_set_acq_long atomic_set_acq_64
+#define GNTTABOP_setup_table 2
+#define VGCF_EXTRA_REGS (1UL << 1)
+#define IA64_VEC_GENERAL_EXCEPTION 24
+#define EPFNOSUPPORT 96
+#define ENOTSUP 150
+#define ESRMNT 69
+#define IA64_VEC_UNSUPP_DATA_REFERENCE 31
+#define BUFFER_IO_PAGE_START (STORE_PAGE_START + STORE_PAGE_SIZE)
+#define __HYPERVISOR_sched_op __HYPERVISOR_sched_op_compat
+#define DOMID_FIRST_RESERVED (0x7FF0U)
+#define local_irq_disable() __cli()
+#define atomic_cmpset_ptr atomic_cmpset_acq_ptr
+#define HYPERPRIVOP_SET_RR0_TO_RR4 (HYPERPRIVOP_START + 0x19)
+#define EDEADLOCK EDEADLK
+#define ECONNABORTED 103
+#define _SIZE_T 
+#define IA64_VEC_IA32_INTERRUPT 47
+#define EBFONT 59
+#define PTE_AR_SHIFT 9
+#define XENFEAT_auto_translated_physmap 2
+#define _TYPES_H_ 
+#define atomic_clear_rel_long atomic_clear_rel_64
+#define __DBL_MAX_EXP__ 1024
+#define IA64_ISR_ED 0x0000080000000000
+#define IA64_ISR_EI 0x0000060000000000
+#define HYPERPRIVOP_ITC_D (HYPERPRIVOP_START + 0x4)
+#define HYPERPRIVOP_ITC_I (HYPERPRIVOP_START + 0x5)
+#define IA64_RSC_MODE_SI (0x1)
+#define IA64_RSC_MBZ0 5
+#define IA64_RSC_MBZ1 30
+#define IA64_ISR_CODE 0x000000000000ffff
+#define PTE_OFF_ED 52
+#define MMUEXT_INVLPG_ALL 11
+#define __HYPERVISOR_vm_assist 21
+#define EREMOTE 66
+#define _VA_LIST_ 
+#define GTF_accept_transfer (2U<<0)
+#define PTE_PS_64K 16
+#define ETOOMANYREFS 109
+#define PTE_PS_64M 26
+#define atomic_clear_int atomic_clear_32
+#define _GCC_SIZE_T 
+#define EVTCHNOP_bind_vcpu 8
+#define VMASST_CMD_enable 0
+#define XEN_IA64_DEBUG_ON_KERN_SSTEP (1 << 0)
+#define IA64_ITIR_PS 2
+#define __HYPERVISOR_xenoprof_op 31
+#define IA64_VEC_IKEY_MISS 6
+#define atomic_clear_short atomic_clear_16
+#define XENVER_compile_info 2
+#define IA64_VEC_ALT_DTLB 4
+#define EISCONN 106
+#define __size_t__ 
+#define XENMEM_add_to_physmap 7
+#define __FLT_DENORM_MIN__ 1.40129846e-45F
+#define IA64_ISR_IR 0x0000004000000000
+#define IO_SAPIC_SIZE 0x100000
+#define ENONET 64
+#define EXFULL 54
+#define VIRQ_DOM_EXC 3
+#define _STDARG_H 
+#define atomic_cmpset_acq_int atomic_cmpset_acq_32
+#define NVRAM_START (GFW_START + 10 * MEM_M)
+#define __HYPERVISOR_iret 23
+#define _T_WCHAR 
+#define __LONG_LONG_MAX__ 9223372036854775807LL
+#define HYPERPRIVOP_SET_RR (HYPERPRIVOP_START + 0x10)
+#define _VA_LIST_T_H 
+#define _MACHINE_ATOMIC_H_ 
+#define _GTF_PAT (7)
+#define _WCHAR_T 
+#define _GNTCOPY_source_gref (0)
+#define atomic_readandclear_int atomic_readandclear_32
+#define IA64_DCR_MBZ1_V 0xffffffffffffULL
+#define IA64_PKR_KEY 8
+#define XENMEM_exchange 11
+#define PTE_D_SHIFT 6
+#define ENOPROTOOPT 92
+#define ASSIGN_nocache (1UL << _ASSIGN_nocache)
+#define XEN_VGATYPE_TEXT_MODE_3 0x03
+#define XEN_GUEST_HANDLE(name) __guest_handle_ ## name
+#define _GTF_PCD (6)
+#define __FLT_MAX__ 3.40282347e+38F
+#define XMAPPEDREGS_SHIFT 12
+#define DEFINE(sym,val) asm volatile("\n->" sym " %0 /* " #val " */": : "i" 
(val))
+#define VMASST_TYPE_pae_extended_cr3 3
+#define __HYPERVISOR_sysctl 35
+#define atomic_clear_acq_long atomic_clear_acq_64
+#define ENOTNAM 118
+#define atomic_subtract_acq_int atomic_subtract_acq_32
+#define EMFILE 24
+#define PTE_MA_WB 0
+#define IA64_ISR_NA 0x0000000800000000
+#define __HYPERVISOR_sched_op_compat 6
+#define __va_list__ 
+#define IA64_ISR_NI 0x0000008000000000
+#define XEN_IA64_DEBUG_ON_KERN_TBRANCH (1 << 2)
+#define IA64_SF_RC_NEGINF UL_CONST(0x0010)
+#define VGC_PRIVREGS_HVM (~(-2UL))
+#define atomic_clear_acq_int atomic_clear_acq_32
+#define _GCC_WCHAR_T 
+#define VIRQ_TBUF 4
+#define MMUEXT_NEW_BASEPTR 5
+#define PTE_P_SHIFT 0
+#define _GTF_transfer_committed (2)
+#define IA64_RR_RID 8
+#define IA64_PSR_IC_BIT 13
+#define _PTRDIFF_T 
+#define IA64_PSR_RI_0 0x0000000000000000
+#define IA64_PSR_RI_1 0x0000020000000000
+#define IA64_PSR_RI_2 0x0000040000000000
+#define ENOBUFS 105
+#define __mk_unsigned_long(x) x ## UL
+#define IA64_ITIR_KEY_LEN 24
+#define __GXX_ABI_VERSION 102
+#define IA64_ISR_W 0x0000000200000000
+#define __FLT_MIN_10_EXP__ (-37)
+#define VIRQ_ARCH_0 16
+#define VIRQ_ARCH_1 17
+#define VIRQ_ARCH_2 18
+#define VIRQ_ARCH_3 19
+#define VIRQ_ARCH_4 20
+#define VIRQ_ARCH_5 21
+#define VIRQ_ARCH_6 22
+#define VIRQ_ARCH_7 23
+#define IA64_ISR_X 0x0000000100000000
+#define IA64_FPSR_DEFAULT (IA64_FPSR_TRAP_VD | IA64_FPSR_TRAP_DD | 
IA64_FPSR_TRAP_ZD | IA64_FPSR_TRAP_OD | IA64_FPSR_TRAP_UD | IA64_FPSR_TRAP_ID | 
IA64_FPSR_SF(0, IA64_SF_DEFAULT) | IA64_FPSR_SF(1, (IA64_SF_DEFAULT | 
IA64_SF_TD | IA64_SF_WRE)) | IA64_FPSR_SF(2, (IA64_SF_DEFAULT | IA64_SF_TD)) | 
IA64_FPSR_SF(3, (IA64_SF_DEFAULT | IA64_SF_TD)))
+#define atomic_add_rel_int atomic_add_rel_32
+#define atomic_subtract_acq_short atomic_subtract_acq_16
+#define atomic_cmpset_int atomic_cmpset_32
+#define HYPERPRIVOP_SET_EFLAG (HYPERPRIVOP_START + 0x16)
+#define __FLT_MIN_EXP__ (-125)
+#define EL3HLT 46
+#define VIRQ_MCA_CMC VIRQ_ARCH_1
+#define EFAULT 14
+#define HYPERPRIVOP_RSM_BE (HYPERPRIVOP_START + 0x17)
+#define IA64_ITIR_PS_LEN 6
+#define __XEN_PUBLIC_EVENT_CHANNEL_H__ 
+#define IA64_ISR_RS 0x0000002000000000
+#define BUFFER_PIO_PAGE_SIZE XEN_PAGE_SIZE
+#define _T_SIZE 
+#define XEN_EXTRAVERSION_LEN (sizeof(xen_extraversion_t))
+#define NR_EVENT_CHANNELS (sizeof(unsigned long) * sizeof(unsigned long) * 64)
+#define EWOULDBLOCK EAGAIN
+#define ASSIGN_pgc_allocated (1UL << _ASSIGN_pgc_allocated)
+#define PTE_A_SHIFT 5
+#define IA64_ISR_SO 0x0000010000000000
+#define IA64_ISR_SP 0x0000001000000000
+#define GNTTABOP_query_size 6
+#define _p(_x) ((void *)(unsigned long)(_x))
+#define IO_SAPIC_START 0xfec00000UL
+#define va_end(v) __builtin_va_end(v)
+#define console_mfn console.domU.mfn
+#define PTE_D 1
+#define PTE_P 1
+#define GNTST_bad_virt_addr (-5)
+#define XENCOMM_INLINE_FLAG 0x8000000000000000UL
+#define __PTRDIFF_T 
+#define __GNUC_MINOR__ 3
+#define IA64_ITIR_MBZ1_LEN 16
+#define ENOCSI 50
+#define ASSIGN_writable (0UL << _ASSIGN_readonly)
+#define GNTMAP_device_map (1<<_GNTMAP_device_map)
+#define smp_processor_id() 0
+#define VIRQ_MCA_CPE VIRQ_ARCH_2
+#define ELIBBAD 80
+#define IA64_DOM0VP_expose_p2m 7
+#define ESTRPIPE 86
+#define _GNTMAP_host_map (1)
+#define ECONNREFUSED 111
+#define get_popcnt(x) ({ uint64_t num; asm ("popcnt %0=%1" : "=r" (num) : "r" 
(x)); num; })
+#define IA64_RSE_LAZY ((IA64_RSC_MODE_LY<<IA64_RSC_MODE) | (MOS_IA64_RSC_BE << 
IA64_RSC_BE) )
+#define IA64_VEC_SINGLE_STEP_TRAP 36
+#define EAGAIN 11
+#define XENMEM_set_memory_map 13
+#define PAGE_SIZE (1 << PAGE_SHIFT)
+#define __DBL_MAX_10_EXP__ 308
+#define PTE_AR_R_RW 4
+#define MMUEXT_UNPIN_TABLE 4
+#define PTE_PS_256K 18
+#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
+#define GNTST_bad_domain (-2)
+#define __DBL_MIN__ 2.2250738585072014e-308
+#define EADDRINUSE 98
+#define _VA_LIST 
+#define PIB_SIZE 0x200000
+#define IA64_FPSR_TRAP_DD UL_CONST(0x0000000000000002)
+#define EVTCHNOP_reset 10
+#define atomic_add_rel_char atomic_add_rel_8
+#define atomic_subtract_char atomic_subtract_8
+#define HVMSTUB_HYPERCALL_FW_START 0x802
+#define UVMF_MULTI (0UL<<2)
+#define IA64_VEC_DTLB 2
+#define XEN_IA64_OPTF_OFF 0x0
+#define GNTST_bad_gntref (-3)
+#define NVRAM_VALID_SIG 0x4650494e45584948
+#define XENMEM_machphys_mfn_list 5
+#define XEN_IA64_DEBUG_OP_GET_TC 3
+#define VMASST_TYPE_4gb_segments 0
+#define ELIBMAX 82
+#define __HYPERVISOR_ia64_fast_eoi __HYPERVISOR_arch_1
+#define EEXIST 17
+#define EUCLEAN 117
+#define __PTRDIFF_TYPE__ long int
+#define __HYPERVISOR_grant_table_op 20
+#define IA64_VEC_DATA_ACCESS 10
+#define IA64_ISR_VECTOR 0x0000000000ff0000
+#define __sti() do { vcpu_info_t *_vcpu; barrier(); _vcpu = 
&HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; 
_vcpu->evtchn_upcall_mask = 0; barrier(); if 
(unlikely(SWAP(_vcpu->evtchn_upcall_pending))) force_evtchn_callback(); } while 
(0)
+#define IA64_VEC_FLOATING_POINT_FAULT 32
+#define IO_PAGE_SIZE XEN_PAGE_SIZE
+#define __LP64__ 1
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#define EL2NSYNC 45
+#define atomic_clear_long atomic_clear_64
+#define MMUEXT_SET_LDT 13
+#define ENETRESET 102
+#define IA64_SF_I UL_CONST(0x1000)
+#define __HYPERVISOR_physdev_op_compat 19
+#define IA64_SF_O UL_CONST(0x0400)
+#define IA64_VEC_NESTED_DTLB 5
+#define IA64_SF_U UL_CONST(0x0800)
+#define IA64_SF_V UL_CONST(0x0080)
+#define IA64_SF_Z UL_CONST(0x0200)
+#define __HYPERVISOR_stack_switch 3
+#define VMASST_TYPE_writable_pagetables 2
+#define IA64_DOM0VP_EFP_ALLOC_PTE 0x1
+#define addr_to_mfn(ADDR) (((unsigned long)ADDR) >> PAGE_SHIFT)
+#define GNTMAP_application_map (1<<_GNTMAP_application_map)
+#define MMIO_SIZE (512 * MEM_M)
+#define __XEN_PUBLIC_MEMORY_H__ 
+#define PTE_OFF_MA 3
+#define EISDIR 21
+#define PTE_PS_1M 20
+#define ENOENT 2
+#define XENVER_guest_handle 8
+#define DOMID_SELF (0x7FF0U)
+#define IA64_FPSR_TRAP_ID UL_CONST(0x0000000000000020)
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#define atomic_set_rel_long atomic_set_rel_64
+#define VIRQ_XENOPROF 7
+#define XSI_SHIFT 14
+#define GNTMAP_readonly (1<<_GNTMAP_readonly)
+#define GNTST_bad_copy_arg (-10)
+#define XEN_IA64_OPTF_IDENT_MAP_REG7_BIT 0
+#define XENMEM_maximum_gpfn 14
+#define GNTST_okay (0)
+#define EBADSLT 57
+#define __WCHAR_T__ 
+#define __LDBL_MIN_10_EXP__ (-4931)
+#define EVTCHNOP_close 3
+#define EKEYREVOKED 128
+#define _ASSIGN_nocache 1
+#define atomic_subtract_int atomic_subtract_32
+#define __XEN_INTERFACE_VERSION__ 0x00000000
+#define atomic_add_short atomic_add_16
+#define atomic_cmpset_rel_int atomic_cmpset_rel_32
+#define IA64_SF_RC_TRUNC UL_CONST(0x0030)
+#define PTE_PS_4K 12
+#define PTE_PS_4M 22
+#define XENMEM_increase_reservation 0
+#define MAX_VMASST_TYPE 3
+#define EHOSTUNREACH 113
+#define IA64_RR_VAL(size,rid) (((size) << IA64_RR_PS) | ((rid) << IA64_RR_RID))
+#define NVRAM_SIZE (MEM_K * 64)
+#define GTF_permit_access (1U<<0)
+#define atomic_subtract_rel_char atomic_subtract_rel_8
+#define __REGISTER_PREFIX__ 
+#define _GCC_PTRDIFF_T 
+#define EVTCHNOP_bind_pirq 2
+#define EIDRM 43
+#define SHUTDOWN_reboot 1
+#define HYPERPRIVOP_ITR_D (HYPERPRIVOP_START + 0xe)
+#define __LDBL_DIG__ 18
+#define ENOTUNIQ 76
+#define _GTF_PWT (5)
+#define MOS_IA64_RSC_BE 0
+#define MEM_G (1UL << 30)
+#define MEM_K (1UL << 10)
+#define MEM_M (1UL << 20)
+#define IA64_VEC_ALT_ITLB 3
+#define mb() ia64_mf()
+#define IA64_SF_PC_0 UL_CONST(0x0000)
+#define IA64_SF_PC_1 UL_CONST(0x0004)
+#define IA64_SF_PC_2 UL_CONST(0x0008)
+#define IA64_SF_PC_3 UL_CONST(0x000c)
+#define XENFEAT_writable_page_tables 0
+#define IA64_RSC_MBZ1_V 0x3ffffffffULL
+#define ___int_ptrdiff_t_h 
+#define PTE_OFF_PPN 12
+#define IA64_FPSR_TRAP_OD UL_CONST(0x0000000000000008)
+#define SIF_PRIVILEGED (1<<0)
+#define GNTTABOP_map_grant_ref 0
+#define atomic_add_acq_char atomic_add_acq_8
+#define HYPERPRIVOP_GET_EFLAG (HYPERPRIVOP_START + 0x15)
+#define __NO_INLINE__ 1
+#define BIND_PIRQ__WILL_SHARE 1
+#define XENCOMM_INLINE_MASK 0xf800000000000000UL
+#define XENFEAT_supervisor_mode_kernel 3
+#define EOPNOTSUPP 95
+#define __HYPERVISOR_set_debugreg 8
+#define atomic_subtract_16 atomic_subtract_acq_16
+#define IA64_VEC_LOWER_PRIVILEGE_TRANSFER 34
+#define __HYPERVISOR_kexec_op 37
+#define SHUTDOWN_poweroff 0
+#define __FLT_MANT_DIG__ 24
+#define atomic_add_long atomic_add_64
+#define __WCHAR_T 
+#define IA64_DCR_DEFER_ALL 0x7f00
+#define __VERSION__ "3.3.5 (Debian 1:3.3.5-13)"
+#define IA64_DCR_MBZ0_V 0xf
+#define EMEDIUMTYPE 124
+#define LEGACY_IO_START (MMIO_START + MMIO_SIZE)
+#define XEN_IA64_DEBUG_ON_MMU (1 << 11)
+#define console_evtchn console.domU.evtchn
+#define STORE_PAGE_START (IO_PAGE_START + IO_PAGE_SIZE)
diff -r 092232fa1fbd extras/stubfw/asm-offset.s
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/asm-offset.s        Thu Nov 22 04:09:09 2007 +0100
@@ -0,0 +1,100 @@
+       .file   "asm-offset.c"
+       .pred.safe_across_calls p1-p5,p16-p63
+       .section        .rodata
+       .align 8
+       .type   __func__.0#, @object
+       .size   __func__.0#, 26
+__func__.0:
+       stringz "HYPERVISOR_grant_table_op"
+       .text
+       .align 16
+       .global main#
+       .proc main#
+main:
+       .prologue
+       .body
+#APP
+       
+->IA64_CB_UNAT 0 /* offsetof(struct ia64_cb_regs, unat) */
+       
+->IA64_CB_R1 16 /* offsetof(struct ia64_cb_regs, r1) */
+       
+->IA64_CB_R2 24 /* offsetof(struct ia64_cb_regs, r2) */
+       
+->IA64_CB_R3 32 /* offsetof(struct ia64_cb_regs, r3) */
+       
+->IA64_CB_R4 40 /* offsetof(struct ia64_cb_regs, r4) */
+       
+->IA64_CB_R5 48 /* offsetof(struct ia64_cb_regs, r5) */
+       
+->IA64_CB_R8 56 /* offsetof(struct ia64_cb_regs, r8) */
+       
+->IA64_CB_R9 64 /* offsetof(struct ia64_cb_regs, r9) */
+       
+->IA64_CB_R10 72 /* offsetof(struct ia64_cb_regs, r10) */
+       
+->IA64_CB_R11 80 /* offsetof(struct ia64_cb_regs, r11) */
+       
+->IA64_CB_R12 88 /* offsetof(struct ia64_cb_regs, r12) */
+       
+->IA64_CB_R13 96 /* offsetof(struct ia64_cb_regs, r13) */
+       
+->IA64_CB_R14 104 /* offsetof(struct ia64_cb_regs, r14) */
+       
+->IA64_CB_R15 112 /* offsetof(struct ia64_cb_regs, r15) */
+       
+->IA64_CB_PR 120 /* offsetof(struct ia64_cb_regs, pr) */
+       
+->IA64_CB_B0 128 /* offsetof(struct ia64_cb_regs, b0) */
+       
+->IA64_CB_B6 136 /* offsetof(struct ia64_cb_regs, b6) */
+       
+->IA64_CB_B7 144 /* offsetof(struct ia64_cb_regs, b7) */
+       
+->IA64_CB_FPSR 152 /* offsetof(struct ia64_cb_regs, fpsr) */
+       
+->IA64_CB_F6 160 /* offsetof(struct ia64_cb_regs, f6) */
+       
+->IA64_CB_F7 176 /* offsetof(struct ia64_cb_regs, f7) */
+       
+->IA64_CB_F8 192 /* offsetof(struct ia64_cb_regs, f8) */
+       
+->IA64_CB_F9 208 /* offsetof(struct ia64_cb_regs, f9) */
+       
+->IA64_CB_F10 224 /* offsetof(struct ia64_cb_regs, f10) */
+       
+->IA64_CB_F11 240 /* offsetof(struct ia64_cb_regs, f11) */
+       
+->IA64_CB_RSC 256 /* offsetof(struct ia64_cb_regs, rsc) */
+       
+->IA64_CB_PFS 264 /* offsetof(struct ia64_cb_regs, pfs) */
+       
+->IA64_CB_CCV 272 /* offsetof(struct ia64_cb_regs, ccv) */
+       
+->IA64_CB_CSD 288 /* offsetof(struct ia64_cb_regs, csd) */
+       
+->IA64_CB_SSD 280 /* offsetof(struct ia64_cb_regs, ssd) */
+       
+->IA64_CB_NATS 296 /* offsetof(struct ia64_cb_regs, nats) */
+       
+->IA64_CB_IP 304 /* offsetof(struct ia64_cb_regs, ip) */
+       
+->IA64_CB_PSR 312 /* offsetof(struct ia64_cb_regs, psr) */
+       
+->IA64_CB_CFM 320 /* offsetof(struct ia64_cb_regs, cfm) */
+       
+->IA64_CB_RSV 328 /* offsetof(struct ia64_cb_regs, rsv) */
+       
+->IA64_CB_BSPSTORE 336 /* offsetof(struct ia64_cb_regs, bspstore) */
+       
+->IA64_CB_RNAT 344 /* offsetof(struct ia64_cb_regs, rnat) */
+       
+->IA64_CB_NDIRTY 352 /* offsetof(struct ia64_cb_regs, ndirty) */
+       
+->IA64_CB_RBS 360 /* offsetof(struct ia64_cb_regs, rbs) */
+#NO_APP
+       mov r8 = r0
+       br.ret.sptk.many b0
+       ;;
+       .endp main#
+       .ident  "GCC: (GNU) 3.3.5 (Debian 1:3.3.5-13)"
diff -r 092232fa1fbd extras/stubfw/block-vbd.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/block-vbd.c Wed Nov 21 14:51:38 2007 +0100
@@ -0,0 +1,186 @@
+/*
+ * Block driver for RAW files
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "ioemu/vl.h"
+#include "ioemu/block_int.h"
+
+#if defined(DEBUG_BLOCK) && !defined(QEMU_TOOL)
+#define DEBUG_BLOCK_PRINT(formatCstr, args...) do { if (loglevel != 0) \
+    { fprintf(logfile, formatCstr, ##args); fflush(logfile); } } while (0)
+#else
+#define DEBUG_BLOCK_PRINT(formatCstr, args...)
+#endif
+
+
+static int vbd_pread(BlockDriverState *bs, int64_t offset,
+                     uint8_t *buf, int count)
+{
+  struct vbd_info *info = bs->opaque;
+  unsigned long sect;
+  //unsigned char *obuf;
+  //unsigned int ocount;
+
+  sect = offset >> SECTOR_BITS;
+
+  //printf ("vbd_pread: sect=%lu count=%lu\n", sect, count >> SECTOR_BITS);
+
+  /* Sanity checks.  */
+  if (((unsigned long)buf) & SECTOR_MASK) {
+    printf ("vbd_pread: bad buffer (%p)\n", buf);
+    exit ();
+  }
+  if (offset & SECTOR_MASK) {
+    printf ("vbd_pread: bad offset (%ld)\n", offset);
+    exit ();
+  }
+  if (count & SECTOR_MASK) {
+    printf ("vbd_pread: bad count (%ld)\n", count);
+    exit ();
+  }
+
+  //printf ("vbd_pread: off=%lx (sec=%lu) count=%x\n", offset, sect, count);
+
+  while (count > 0) {
+    if (vbd_request (info, 0, sect, buf) != 0) {
+      printf ("vbd_request failed (sect=%lu)\n", sect);
+      return -EIO;
+    }
+
+    buf += SECTOR_SIZE;
+    count -= SECTOR_SIZE;
+    sect++;
+  }
+
+
+
+  return 0;
+}
+
+static int vbd_pwrite(BlockDriverState *bs, int64_t offset,
+                      const uint8_t *buf, int count)
+{
+  struct vbd_info *info = bs->opaque;
+  unsigned long sect;
+
+  sect = offset >> SECTOR_BITS;
+
+  /* Sanity checks.  */
+  if (((unsigned long)buf) & SECTOR_MASK) {
+    printf ("vbd_pread: bad buffer (%p)\n", buf);
+    exit ();
+  }
+  if (offset & SECTOR_MASK) {
+    printf ("vbd_pread: bad offset (%ld)\n", offset);
+    exit ();
+  }
+  if (count & SECTOR_MASK) {
+    printf ("vbd_pread: bad count (%ld)\n", count);
+    exit ();
+  }
+
+  //printf ("vbd_pwrite: off=%lx (sec=%lu) count=%x\n", offset, sect, count);
+
+  while (count > 0) {
+    if (vbd_request (info, 1, sect, (uint8_t *)buf) != 0)
+      return -EIO;
+
+    buf += SECTOR_SIZE;
+    count -= SECTOR_SIZE;
+    sect++;
+  }
+  return 0;
+}
+
+static void vbd_close(BlockDriverState *bs)
+{
+    printk ("vbd_close: not implemented\n");
+}
+
+static int64_t vbd_getlength(BlockDriverState *bs)
+{
+  struct vbd_info *info = bs->opaque;
+
+  return info->sectors * info->sector_size;
+}
+
+
+
+BlockDriver bdrv_vbd = {
+    "vbd",
+    0,
+    NULL, /* no probe for protocols */
+    NULL,
+    NULL,
+    NULL,
+    vbd_close,
+    NULL,
+    NULL,
+
+#if 0
+    .bdrv_aio_read = raw_aio_read,
+    .bdrv_aio_write = raw_aio_write,
+    .bdrv_aio_cancel = raw_aio_cancel,
+    .aiocb_size = sizeof(RawAIOCB),
+#endif
+    .protocol_name = "file",
+    .bdrv_pread = vbd_pread,
+    .bdrv_pwrite = vbd_pwrite,
+    .bdrv_getlength = vbd_getlength,
+};
+
+int bdrv_open_vbd(BlockDriverState *bs, struct vbd_info *info, int flags)
+{
+    bs->read_only = 0;
+    bs->is_temporary = 0;
+    bs->encrypted = 0;
+
+    pstrcpy(bs->filename, sizeof(bs->filename), info->node_name);
+    bs->drv = &bdrv_vbd;
+    bs->opaque = info;
+#if 0
+    bs->opaque = qemu_mallocz(drv->instance_size);
+    if (bs->opaque == NULL && drv->instance_size > 0)
+        return -1;
+#endif
+    bs->read_only = info->is_ro;
+    if (bs->drv->bdrv_getlength) {
+        bs->total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
+    }
+
+    printf ("bdrv_vbd: %s nsec=%ld\n", bs->filename, bs->total_sectors);
+
+    /* call the change callback */
+    bs->media_changed = 1;
+    if (bs->change_cb)
+        bs->change_cb(bs->change_opaque);
+
+    return 0;
+}
+
+extern void bdrv_register(BlockDriver *bdrv);
+
+void
+bdrv_init (void)
+{
+  bdrv_register (&bdrv_vbd);
+}
diff -r 092232fa1fbd extras/stubfw/callback.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/callback.h  Sun Nov 11 03:47:58 2007 +0100
@@ -0,0 +1,48 @@
+#include "ia64_cpu.h"
+#include "ia64_fpu.h"
+
+struct ia64_cb_regs {
+  unsigned long unat;
+  unsigned long _pad1;
+  unsigned long r1;
+  unsigned long r2;
+  unsigned long r3;
+  unsigned long r4;
+  unsigned long r5;
+  unsigned long r8;
+  unsigned long r9;
+  unsigned long r10;
+  unsigned long r11;
+  unsigned long r12;
+  unsigned long r13;
+  unsigned long r14;
+  unsigned long r15;
+  unsigned long pr;
+  unsigned long b0;
+  unsigned long b6;
+  unsigned long b7;
+  unsigned long fpsr;
+  ia64_fpreg_t  f6;
+  ia64_fpreg_t  f7;
+  ia64_fpreg_t  f8;
+  ia64_fpreg_t  f9;
+  ia64_fpreg_t  f10;
+  ia64_fpreg_t  f11;
+  unsigned long rsc;
+  unsigned long pfs;
+  unsigned long ccv;
+  unsigned long ssd;
+  unsigned long csd;
+  unsigned long nats;
+  unsigned long ip;
+  unsigned long psr;
+  unsigned long cfm;
+  unsigned long rsv;
+  unsigned long bspstore;
+  unsigned long rnat;
+  unsigned long ndirty;
+
+  unsigned long rbs[0];
+};
+
+  
diff -r 092232fa1fbd extras/stubfw/console.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/console.c   Wed Nov 21 16:09:36 2007 +0100
@@ -0,0 +1,336 @@
+#include "console.h"
+#include "types.h"
+#include "lib.h"
+#include "os.h"
+#include "events.h"
+#include "ioemu/vl.h"
+
+
+#define BUG_ON(cond)
+
+static int term_got_escape;
+static void mon_proc_byte(char c);
+static int term_escape_char = 0x01; /* ctrl-a is used for escape */
+
+static CharDriverState xc_chr;
+
+static struct xencons_interface *xencons_interface;
+static unsigned int xencons_evtchn;
+
+
+int xencons_ring_send_no_notify(const char *data, unsigned len)
+{      
+  int sent = 0;
+  struct xencons_interface *intf = xencons_interface;
+  XENCONS_RING_IDX cons, prod;
+  cons = intf->out_cons;
+  prod = intf->out_prod;
+  mb();
+  BUG_ON((prod - cons) > sizeof(intf->out));
+
+  while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
+    intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
+
+  wmb();
+  intf->out_prod = prod;
+    
+  return sent;
+}
+
+int xencons_ring_send(const char *data, unsigned len)
+{
+    int sent;
+    sent = xencons_ring_send_no_notify(data, len);
+    notify_remote_via_evtchn(xencons_evtchn);
+
+    return sent;
+}      
+
+void xencons_wait_send (void)
+{
+  XENCONS_RING_IDX cons, prod;
+  struct xencons_interface *intf = xencons_interface;
+
+  while (1) {
+    cons = intf->out_cons;
+    prod = intf->out_prod;
+    mb();
+    if ((prod - cons) < sizeof(intf->out))
+      break;
+    poll_evtchn (xencons_evtchn);
+  }
+}
+
+void xencons_input(evtchn_port_t port, void *unused)
+{
+  struct xencons_interface *intf = xencons_interface;
+  XENCONS_RING_IDX cons, prod;
+  char c;
+  
+  cons = intf->in_cons;
+  prod = intf->in_prod;
+  mb();
+  BUG_ON((prod - cons) > sizeof(intf->in));
+
+  /* We are currently polling on output.
+     No need to send an event if no input.  */
+  if (cons == prod)
+    return;
+
+  while (cons != prod) {
+    c = intf->in[MASK_XENCONS_IDX(cons,intf->in)];
+    if (term_got_escape)
+       mon_proc_byte (c);
+    else if (c == term_escape_char)
+       term_got_escape = 1;
+    else if (qemu_chr_can_read (&xc_chr))
+       qemu_chr_read (&xc_chr, &c, 1);
+    else
+       break;
+    cons++;
+  }
+
+  mb();
+  intf->in_cons = cons;
+
+  notify_remote_via_evtchn(xencons_evtchn);
+}
+
+void
+init_console (void *interface, int evtchn)
+{
+  /* Setup console.  */
+  xencons_interface = (struct xencons_interface*)interface;
+  xencons_evtchn = evtchn;
+  bind_evtchn (evtchn, xencons_input, NULL);
+
+  unmask_evtchn (xencons_evtchn);
+}
+
+/* MUX driver for serial I/O splitting */
+#define MAX_MUX 4
+typedef struct {
+    IOCanRWHandler *chr_can_read[MAX_MUX];
+    IOReadHandler *chr_read[MAX_MUX];
+    IOEventHandler *chr_event[MAX_MUX];
+    void *ext_opaque[MAX_MUX];
+    int mux_cnt;
+    int max_size;
+} MuxDriver;
+static MuxDriver mux_drv;
+
+extern int ioemu_trace;
+
+static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+    int res;
+    int len_orig = len;
+
+#if 0
+    if (len == 1 && *buf == '\a') {
+      printk ("Got marker!");
+      //ioemu_trace = 1;
+    }
+#endif
+
+    while (1) {
+       res = xencons_ring_send (buf, len);
+       len -= res;
+       if (len == 0)
+           break;
+       buf += res;
+       xencons_wait_send ();
+    }
+    return len_orig;
+}
+
+static char *mux_help[] = {
+    "% h    print this help\n\r",
+    "% x    exit emulator\n\r",
+    "% s    save disk data back to file (if -snapshot)\n\r",
+    "% b    send break (magic sysrq)\n\r",
+    "% p    pci info\n\r",
+    "% c    switch between console and monitor\n\r",
+    "% %  sends %\n\r",
+    NULL
+};
+
+static void mux_print_help(CharDriverState *chr)
+{
+    int i, j;
+    char ebuf[15] = "Escape-Char";
+    char cbuf[50] = "\n\r";
+
+    if (term_escape_char > 0 && term_escape_char < 26) {
+        sprintf(cbuf,"\n\r");
+        sprintf(ebuf,"C-%c", term_escape_char - 1 + 'a');
+    } else {
+        sprintf(cbuf,"\n\rEscape-Char set to Ascii: 0x%02x\n\r\n\r", 
term_escape_char);
+    }
+    chr->chr_write(chr, cbuf, strlen(cbuf));
+    for (i = 0; mux_help[i] != NULL; i++) {
+        for (j=0; mux_help[i][j] != '\0'; j++) {
+            if (mux_help[i][j] == '%')
+                chr->chr_write(chr, ebuf, strlen(ebuf));
+            else
+                chr->chr_write(chr, &mux_help[i][j], 1);
+        }
+    }
+}
+
+static void mon_proc_byte(char c)
+{
+    CharDriverState *chr = &xc_chr;
+    switch(c) {
+    case '?':
+    case 'h':
+       mux_print_help(chr);
+       break;
+    case 'x':
+    {
+       char *term =  "QEMU: Terminated\n\r";
+       chr->chr_write(chr,term,strlen(term));
+       exit();
+       break;
+    }
+    case 's':
+#ifndef IOEMU
+    {
+       int i;
+       for (i = 0; i < MAX_DISKS; i++) {
+           if (bs_table[i])
+               bdrv_commit(bs_table[i]);
+       }
+       if (mtd_bdrv)
+           bdrv_commit(mtd_bdrv);
+    }
+#endif
+    break;
+    case 'b':
+       qemu_chr_event(chr, CHR_EVENT_BREAK);
+       break;
+    case 'c':
+       /* Switch to the next registered device */
+       chr->focus++;
+       if (chr->focus >= mux_drv.mux_cnt)
+           chr->focus = 0;
+       break;
+    case 'p':
+      pci_info ();
+      break;
+    }
+    term_got_escape = 0;
+}
+
+static int mux_chr_can_read(void *opaque)
+{
+    CharDriverState *chr = opaque;
+    MuxDriver *d = chr->opaque;
+    if (d->chr_can_read[chr->focus])
+       return d->chr_can_read[chr->focus](d->ext_opaque[chr->focus]);
+    return 0;
+}
+
+static void mux_chr_read(void *opaque, const uint8_t *buf, int size)
+{
+    CharDriverState *chr = opaque;
+    MuxDriver *d = chr->opaque;
+    int i;
+    for(i = 0; i < size; i++)
+       d->chr_read[chr->focus](d->ext_opaque[chr->focus], &buf[i], 1);
+}
+
+static void mux_chr_event(void *opaque, int event)
+{
+    CharDriverState *chr = opaque;
+    MuxDriver *d = chr->opaque;
+    int i;
+
+    /* Send the event to all registered listeners */
+    for (i = 0; i < d->mux_cnt; i++)
+        if (d->chr_event[i])
+            d->chr_event[i](d->ext_opaque[i], event);
+}
+
+static void mux_chr_update_read_handler(CharDriverState *chr)
+{
+    MuxDriver *d = chr->opaque;
+
+    printf ("mux_chr_update_read_handler: %p\n", chr);
+    if (d->mux_cnt >= MAX_MUX) {
+        printf("Cannot add I/O handlers, MUX array is full\n");
+        return;
+    }
+    d->ext_opaque[d->mux_cnt] = chr->handler_opaque;
+    d->chr_can_read[d->mux_cnt] = chr->chr_can_read;
+    d->chr_read[d->mux_cnt] = chr->chr_read;
+    d->chr_event[d->mux_cnt] = chr->chr_event;
+#if 0 /* Crash dom0!! -> infinite recursion.  */
+    /* Fix up the real driver with mux routines */
+    if (d->mux_cnt == 0) {
+      printf ("mux_chr_update_read_handler (1)\n");
+        qemu_chr_add_handlers(&xc_chr, mux_chr_can_read, mux_chr_read,
+                              mux_chr_event, chr);
+      printf ("mux_chr_update_read_handler (2)\n");
+    }
+#endif
+    chr->focus = d->mux_cnt;
+    d->mux_cnt++;
+}
+
+CharDriverState *qemu_chr_open_xc(void)
+{
+    CharDriverState *chr = &xc_chr;
+    MuxDriver *d = &mux_drv;
+
+    chr->chr_write = mux_chr_write;
+
+    chr->opaque = d;
+    chr->focus = -1;
+    qemu_chr_add_handlers(chr, mux_chr_can_read, mux_chr_read,
+                         mux_chr_event, chr);
+    chr->chr_update_read_handler = mux_chr_update_read_handler;
+    return chr;
+}
+
+
+void vprintf(const char *fmt, va_list args)
+{
+    static char   buf[1024];
+    char *p;
+    
+    (void)vsnprintf(buf, sizeof(buf), fmt, args);
+ 
+    for (p = buf; *p; p++)
+      {
+       if (*p == '\n')
+         xencons_ring_send_no_notify ("\r", 1);
+       xencons_ring_send_no_notify (p, 1);
+      }
+    notify_remote_via_evtchn(xencons_evtchn);
+}
+
+void printk(const char *fmt, ...)
+{
+    va_list       args;
+    va_start(args, fmt);
+    vprintf(fmt, args);
+    va_end(args);        
+}
+
+int printf(const char *fmt, ...)
+{
+    va_list       args;
+    va_start(args, fmt);
+    vprintf(fmt, args);
+    va_end(args);        
+    return 0;
+}
+
+void term_printf(const char *fmt, ...)
+{
+    va_list       args;
+    va_start(args, fmt);
+    vprintf(fmt, args);
+    va_end(args);
+}
diff -r 092232fa1fbd extras/stubfw/console.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/console.h   Thu Nov 15 03:39:57 2007 +0100
@@ -0,0 +1,10 @@
+#include "types.h"
+#include <xen/io/console.h>
+
+//extern int xencons_ring_send_no_notify(const char *data, unsigned len);
+extern int xencons_ring_send(const char *data, unsigned len);
+
+extern void xencons_wait_send (void);
+
+extern void init_console (void *interface, int evtchn);
+
diff -r 092232fa1fbd extras/stubfw/event-asm.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/event-asm.S Sun Nov 11 04:03:45 2007 +0100
@@ -0,0 +1,236 @@
+#include "asm-offset.h"
+       
+#define FILL_REGS(R1, R2) \
+       ld8.fill R1=[r18],-16;\
+       ld8.fill R2=[r17],-16;\
+       ;;
+
+#define FILL_FP_REGS(F1, F2) \
+       ldf.fill F1=[r17],32;\
+       ldf.fill F2=[r18],32;\
+       ;;
+
+#define CB(R) IA64_CB_##R
+       
+       .globl callback_entry
+       .align 32
+       .proc callback_entry
+callback_entry:        
+       // r17=buffer,
+       mov r18=ar.unat
+       ;;
+       st8 [r17]=r18,CB(R1)-CB(UNAT)   // ar.unat, ??
+       ;;
+       add r18=CB(R2)-CB(R1),r17
+       ;; 
+       .mem.offset 0,0
+       st8.spill [r17]=r1,CB(R3)-CB(R1)
+       .mem.offset 8,0
+       st8.spill [r18]=r2,CB(R4)-CB(R2)
+       ;;
+       .mem.offset 0,0
+       st8.spill [r17]=r3,CB(R5)-CB(R3)
+       .mem.offset 8,0
+       st8.spill [r18]=r4,CB(R8)-CB(R4)
+       ;;
+       .mem.offset 0,0
+       st8.spill [r17]=r5,CB(R9)-CB(R5)
+       .mem.offset 8,0
+       st8.spill [r18]=r8,CB(R10)-CB(R8)
+       ;;
+       mov r8=pr
+       .mem.offset 0,0
+       st8.spill [r17]=r9,CB(R11)-CB(R9)
+       .mem.offset 8,0
+       st8.spill [r18]=r10,CB(R12)-CB(R10)
+       ;;
+       mov r9=b0
+       .mem.offset 0,0
+       st8.spill [r17]=r11,CB(R13)-CB(R11)
+       .mem.offset 8,0
+       st8.spill [r18]=r12,CB(R14)-CB(R12)
+       ;;
+       mov r10=b6
+       .mem.offset 0,0
+       st8.spill [r17]=r13,CB(R15)-CB(R13)
+       .mem.offset 8,0
+       st8.spill [r18]=r14,CB(PR)-CB(R14)
+       ;;
+       mov r11=b7
+       .mem.offset 0,0
+       st8.spill [r17]=r15,CB(B0)-CB(R15)
+       .mem.offset 8,0
+       st8 [r18]=r8,CB(B6)-CB(PR)
+       ;;
+       mov r8=ar.fpsr
+       .mem.offset 0,0
+       st8 [r17]=r9,CB(B7)-CB(B0)
+       .mem.offset 8,0
+       st8 [r18]=r10,CB(FPSR)-CB(B6)
+       ;;
+       mov r9=ar.rsc
+       .mem.offset 0,0
+       st8 [r17]=r11,CB(F6)-CB(B7)
+       .mem.offset 8,0
+       st8 [r18]=r8,CB(F7)-CB(FPSR)
+       ;;
+       mov r10=ar.pfs
+       stf.spill [r17]=f6,CB(F8)-CB(F6)
+       stf.spill [r18]=f7,CB(F9)-CB(F7)
+       ;;
+       mov r11=ar.ccv
+       stf.spill [r17]=f8,CB(F10)-CB(F8)
+       stf.spill [r18]=f9,CB(F11)-CB(F9)
+       ;;
+       mov r8=ar.unat
+       stf.spill [r17]=f10,CB(RSC)-CB(F10)
+       stf.spill [r18]=f11,CB(PFS)-CB(F11)
+       ;;
+       // RSE in enforced lazy mode
+       mov ar.rsc=0 // lazy
+       .mem.offset 0,0
+       st8 [r17]=r9,CB(CCV)-CB(RSC)
+       .mem.offset 8,0
+       st8 [r18]=r10,CB(NATS)-CB(PFS)
+       ;;
+       mov r9=ar.csd
+       mov r10=ar.ssd
+       .mem.offset 0,0
+       st8 [r17]=r11,CB(CSD)-CB(CCV)
+       .mem.offset 8,0
+       st8 [r18]=r8,CB(SSD)-CB(NATS)
+       ;;
+       .mem.offset 0,0
+       st8 [r17]=r9,CB(IP)-CB(CSD)
+       .mem.offset 8,0
+       st8 [r18]=r10,CB(PSR)-CB(SSD)
+       ;;
+       mov r9=ar.bspstore
+       mov r8=ar.rnat
+       .mem.offset 0,0
+       st8 [r17]=r28,CB(CFM)-CB(IP)
+       .mem.offset 8,0
+       st8 [r18]=r29,CB(RSV)-CB(PSR)
+       ;;
+       .mem.offset 0,0
+       st8 [r17]=r30,CB(BSPSTORE)-CB(CFM)
+       .mem.offset 8,0
+       st8 [r18]=r31,CB(RNAT)-CB(RSV)
+       ;;
+       .mem.offset 0,0
+       st8 [r17]=r9,CB(NDIRTY)-CB(BSPSTORE)
+       .mem.offset 8,0
+       st8 [r18]=r8,CB(RBS)-CB(RNAT)
+       ;;
+       add r2=-CB(RBS),r18
+       mov ar.bspstore=r18     // the new bspstore
+       ;;
+       add r12=(1<<16)-16,r2   // 64KB stack
+       mov r11=ar.bsp
+       movl gp=__gp
+       ;;
+       sub r11=r11,r18 // ndirty bytes
+       mov ar.rsc=3 // eager
+       ;;
+       st8 [r17]=r11   // store ndirty
+       add r4=CB(UNAT)-CB(NDIRTY),r17
+       ;; 
+       alloc r15=ar.pfs,0,0,7,0
+       mov out0=r16            // cause
+       mov out1=r19
+       mov out2=r20
+       mov out3=r21
+       mov out4=r22
+       mov out5=r23
+       mov out6=r4
+       ;;
+       br.call.sptk.few rp = ia64_callback
+       ;;
+       alloc r15=ar.pfs,0,0,0,0
+       add r18=CB(BSPSTORE),r4
+       add r17=CB(NDIRTY),r4
+       mov r16=r8
+       ;;
+       mov r19=r9
+       mov r20=r10
+       ld8 r15=[r17],CB(RNAT)-CB(NDIRTY)       // ndirty
+       ;;
+       // RSE in enforced lazy mode
+       mov ar.rsc=0 // lazy
+       mov r21=r11
+       ld8 r9=[r18],CB(CFM)-CB(BSPSTORE)
+       ld8 r8=[r17],CB(RSV)-CB(RNAT)
+       shl r15=r15,16
+       ;;
+       mov ar.rsc=r15          // loadrs+lazy
+       ld8 r30=[r18],CB(IP)-CB(CFM)
+       ld8 r31=[r17],CB(PSR)-CB(RSV)
+       ;;
+       loadrs
+       ld8 r28=[r18],CB(CCV)-CB(IP)
+       ld8 r29=[r17],CB(NATS)-CB(PSR)
+       ;; 
+       mov ar.bspstore=r9
+       ld8 r10=[r18],CB(CSD)-CB(CCV)
+       ld8 r11=[r17],CB(SSD)-CB(NATS)
+       ;;
+       mov ar.unat=r11
+       mov ar.rnat=r8
+       mov ar.ccv=r10
+       ;;
+       ld8 r10=[r18],CB(RSC)-CB(CSD)
+       ld8 r11=[r17],CB(PFS)-CB(SSD)
+       ;;
+       mov ar.csd=r10
+       mov ar.ssd=r11
+       ld8 r8=[r18],CB(F10)-CB(RSC)
+       ld8 r9=[r17],CB(F11)-CB(PFS)
+       ;;
+       ldf.fill f10=[r18],CB(F8)-CB(F10)
+       ldf.fill f11=[r17],CB(F9)-CB(F11)
+       mov ar.rsc=r8
+       ;;
+       ldf.fill f8=[r18],CB(F6)-CB(F8)
+       ldf.fill f9=[r17],CB(F7)-CB(F9)
+       mov ar.pfs=r9
+       ;;
+       ldf.fill f6=[r18],CB(B7)-CB(F6)
+       ldf.fill f7=[r17],CB(FPSR)-CB(F7)
+       ;;
+       ld8 r8=[r18],CB(B0)-CB(B7)
+       ld8 r9=[r17],CB(B6)-CB(FPSR)
+       ;; 
+       mov b7=r8
+       ld8 r10=[r18],CB(R15)-CB(B0)
+       ld8 r11=[r17],CB(PR)-CB(B6)
+       mov ar.fpsr=r9
+       ;;
+       ld8.fill r15=[r18],CB(R13)-CB(R15)
+       ld8 r8=[r17],CB(R14)-CB(PR)
+       mov b0=r10
+       ;;
+       ld8.fill r13=[r18],CB(R11)-CB(R13)
+       ld8.fill r14=[r17],CB(R12)-CB(R14)
+       mov b6=r11
+       ;;
+       ld8.fill r11=[r18],CB(R9)-CB(R11)
+       ld8.fill r12=[r17],CB(R10)-CB(R12)
+       mov pr=r8
+       ;;
+       ld8.fill r9=[r18],CB(R5)-CB(R9)
+       ld8.fill r10=[r17],CB(R8)-CB(R10)
+       ;;
+       ld8.fill r5=[r18],CB(R3)-CB(R5)
+       ld8.fill r8=[r17],CB(R4)-CB(R8)
+       ;;
+       ld8.fill r3=[r18],CB(R1)-CB(R3)
+       ld8.fill r4=[r17],CB(R2)-CB(R4)
+       ;;
+       ld8.fill r1=[r18],CB(UNAT)-CB(R1)
+       ld8.fill r2=[r17]
+       ;;
+       ld8 r18=[r18]
+       ;;
+       mov ar.unat=r18
+       break 0x01 //HVMSTUB_HYPERPRIVOP_CALLBACK_RETURN
+       .endp callback_entry
diff -r 092232fa1fbd extras/stubfw/events.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/events.c    Thu Nov 15 03:38:38 2007 +0100
@@ -0,0 +1,200 @@
+#include "types.h"
+#include "lib.h"
+#include "os.h"
+#include "events.h"
+
+#define NR_EVS 1024
+
+/* this represents a event handler. Chaining or sharing is not allowed */
+typedef struct _ev_action_t {
+       evtchn_handler_t handler;
+       void *data;
+    u32 count;
+} ev_action_t;
+
+static ev_action_t ev_actions[NR_EVS];
+static void default_handler(evtchn_port_t port, void *data);
+
+static unsigned long bound_ports[NR_EVS/(8*sizeof(unsigned long))];
+
+void unbind_all_ports(void)
+{
+    int i;
+
+    for (i = 0; i < NR_EVS; i++)
+    {
+        if (test_and_clear_bit(i, bound_ports))
+        {
+            struct evtchn_close close;
+            mask_evtchn(i);
+            close.port = i;
+            HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
+        }
+    }
+}
+  
+/*
+ * Demux events to different handlers.
+ */
+static int do_event(evtchn_port_t port)
+{
+    ev_action_t  *action;
+    if (port >= NR_EVS) {
+        printk("Port number too large: %d\n", port);
+       goto out;
+    }
+
+    action = &ev_actions[port];
+    action->count++;
+
+    /* call the handler */
+    action->handler(port, action->data);
+
+ out:
+    clear_evtchn(port);
+
+    return 1;
+
+}
+
+evtchn_port_t bind_evtchn(evtchn_port_t port, evtchn_handler_t handler,
+                         void *data)
+{
+    if (ev_actions[port].handler != default_handler)
+        printk("WARN: Handler for port %d already registered, replacing\n",
+              port);
+
+    ev_actions[port].data = data;
+    wmb();
+    ev_actions[port].handler = handler;
+    
+    /* Finally unmask the port */
+    unmask_evtchn(port);
+    
+    return port;
+}
+
+void unbind_evtchn(evtchn_port_t port)
+{
+    if (ev_actions[port].handler == default_handler)
+       printk("WARN: No handler for port %d when unbinding\n", port);
+    ev_actions[port].handler = default_handler;
+    wmb();
+    ev_actions[port].data = NULL;
+}
+
+int bind_virq(uint32_t virq, evtchn_handler_t handler, void *data)
+{
+    evtchn_bind_virq_t op;
+
+    /* Try to bind the virq to a port */
+    op.virq = virq;
+    op.vcpu = smp_processor_id();
+    
+    if ( HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &op) != 0 ) {
+       printk("Failed to bind virtual IRQ %d\n", virq);
+       return 1;
+    }
+    set_bit(op.port,bound_ports);
+    bind_evtchn(op.port, handler, data);
+    return 0;
+}
+
+/*
+ * Initially all events are without a handler and disabled
+ */
+void init_events(void)
+{
+    int i;
+    /* inintialise event handler */
+    for ( i = 0; i < NR_EVS; i++ ) {
+        ev_actions[i].handler = default_handler;
+        mask_evtchn(i);
+    }
+}
+
+static void default_handler(evtchn_port_t port, void *ignore)
+{
+    printk("[Port %d] - event received\n", port);
+}
+
+/* Create a port available to the pal for exchanging notifications.
+   Returns the result of the hypervisor call. */
+
+/* Unfortunate confusion of terminology: the port is unbound as far
+   as Xen is concerned, but we automatically bind a handler to it
+   from inside mini-os. */
+
+int evtchn_alloc_unbound(domid_t pal, evtchn_handler_t handler,
+                        void *data, evtchn_port_t *port)
+{
+    evtchn_alloc_unbound_t op;
+    op.dom = DOMID_SELF;
+    op.remote_dom = pal;
+    int err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
+    if (err)
+       return err;
+    *port = bind_evtchn(op.port, handler, data);
+    return err;
+}
+
+/* Connect to a port so as to allow the exchange of notifications with
+   the pal. Returns the result of the hypervisor call. */
+
+int evtchn_bind_interdomain(domid_t pal, evtchn_port_t remote_port,
+                           evtchn_handler_t handler, void *data,
+                           evtchn_port_t *local_port)
+{
+    evtchn_bind_interdomain_t op;
+    op.remote_dom = pal;
+    op.remote_port = remote_port;
+    int err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, &op);
+    if (err)
+       return err;
+    set_bit(op.local_port,bound_ports);
+    evtchn_port_t port = op.local_port;
+    clear_evtchn(port);              /* Without, handler gets invoked now! */
+    *local_port = bind_evtchn(port, handler, data);
+    return err;
+}
+
+void do_hypervisor_callback(void)
+{
+    unsigned long  l1, l2, l1i, l2i;
+    unsigned int   port;
+    int            cpu = 0;
+    volatile shared_info_t *s = shared_info;
+    volatile vcpu_info_t   *vcpu_info = &s->vcpu_info[cpu];
+
+   
+    vcpu_info->evtchn_upcall_pending = 0;
+    /* NB. No need for a barrier here -- XCHG is a barrier on x86. */
+    l1 = xchg((unsigned long *)&vcpu_info->evtchn_pending_sel, 0);
+    while ( l1 != 0 )
+    {
+        l1i = __ffs(l1);
+        l1 &= ~(1 << l1i);
+        
+        while ( (l2 = active_evtchns(cpu, s, l1i)) != 0 )
+        {
+            l2i = __ffs(l2);
+            l2 &= ~(1 << l2i);
+
+            port = (l1i << 5) + l2i;
+           do_event (port);
+           clear_evtchn (port);
+        }
+    }
+}
+
+void
+poll_evtchn (evtchn_port_t port)
+{
+  evtchn_port_t p = port;
+  sched_poll_t poll;
+  
+  set_xen_guest_handle (poll.ports, &p);
+  poll.nr_ports = 1;
+  poll.timeout = 100000UL; //0000000UL;
+  HYPERVISOR_poll (&poll);
+}
diff -r 092232fa1fbd extras/stubfw/gnttab.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/gnttab.c    Sat Nov 17 02:53:17 2007 +0100
@@ -0,0 +1,197 @@
+/* 
+ ****************************************************************************
+ * (C) 2006 - Cambridge University
+ ****************************************************************************
+ *
+ *        File: gnttab.c
+ *      Author: Steven Smith (sos22@xxxxxxxxx) 
+ *     Changes: Grzegorz Milos (gm281@xxxxxxxxx)
+ *              
+ *        Date: July 2006
+ * 
+ * Environment: Xen Minimal OS
+ * Description: Simple grant tables implementation. About as stupid as it's
+ *  possible to be and still work.
+ *
+ ****************************************************************************
+ */
+#include "os.h"
+#include "lib.h"
+//#include "mm.h"
+#include "gnttab.h"
+
+#define NR_RESERVED_ENTRIES 8
+
+/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
+#ifdef __ia64__
+#define NR_GRANT_FRAMES 1
+#else
+#define NR_GRANT_FRAMES 4
+#endif
+#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
+
+static grant_entry_t *gnttab_table;
+static grant_ref_t gnttab_list[NR_GRANT_ENTRIES];
+
+static void
+put_free_entry(grant_ref_t ref)
+{
+    gnttab_list[ref] = gnttab_list[0];
+    gnttab_list[0]  = ref;
+
+}
+
+static grant_ref_t
+get_free_entry(void)
+{
+    grant_ref_t ref = gnttab_list[0];
+    if (ref != GRANT_INVALID_REF)
+       gnttab_list[0] = gnttab_list[ref];
+    return ref;
+}
+
+grant_ref_t
+gnttab_grant_access(domid_t domid, unsigned long frame, int readonly)
+{
+    grant_ref_t ref;
+
+    ref = get_free_entry();
+    if (ref == GRANT_INVALID_REF)
+       return GRANT_INVALID_REF;
+    gnttab_table[ref].frame = frame;
+    gnttab_table[ref].domid = domid;
+    wmb();
+    gnttab_table[ref].flags =
+       GTF_permit_access | (readonly ? GTF_readonly : 0);
+
+    return ref;
+}
+
+grant_ref_t
+gnttab_grant_transfer(domid_t domid, unsigned long pfn)
+{
+    grant_ref_t ref;
+
+    ref = get_free_entry();
+    gnttab_table[ref].frame = pfn;
+    gnttab_table[ref].domid = domid;
+    wmb();
+    gnttab_table[ref].flags = GTF_accept_transfer;
+
+    return ref;
+}
+
+int
+gnttab_end_access(grant_ref_t ref)
+{
+    u16 flags, nflags;
+
+    nflags = gnttab_table[ref].flags;
+    do {
+        if ((flags = nflags) & (GTF_reading|GTF_writing)) {
+            printk("WARNING: g.e. still in use!\n");
+            return 0;
+        }
+    } while ((nflags = synch_cmpxchg(&gnttab_table[ref].flags, flags, 0)) !=
+            flags);
+
+    put_free_entry(ref);
+    return 1;
+}
+
+unsigned long
+gnttab_end_transfer(grant_ref_t ref)
+{
+    unsigned long frame;
+    u16 flags;
+
+    while (!((flags = gnttab_table[ref].flags) & GTF_transfer_committed)) {
+        if (synch_cmpxchg(&gnttab_table[ref].flags, flags, 0) == flags) {
+            printk("Release unused transfer grant.\n");
+            put_free_entry(ref);
+            return 0;
+        }
+    }
+
+    /* If a transfer is in progress then wait until it is completed. */
+    while (!(flags & GTF_transfer_completed)) {
+        flags = gnttab_table[ref].flags;
+    }
+
+    /* Read the frame number /after/ reading completion status. */
+    rmb();
+    frame = gnttab_table[ref].frame;
+
+    put_free_entry(ref);
+
+    return frame;
+}
+
+void *
+alloc_pages (int nbr)
+{
+    static unsigned long start_addr = 0xff700000;
+    void *res;
+
+    res = (void *)start_addr;
+    start_addr += nbr * PAGE_SIZE;
+    if (start_addr >= 0xff800000) {
+      printk ("alloc_pages(%d): no more memory\n", nbr);
+      exit();
+    }
+    return res;
+}
+
+grant_ref_t
+gnttab_alloc_and_grant(void **map)
+{
+    void *res = alloc_pages (1);
+
+    return gnttab_grant_access(0, addr_to_mfn (res), 0);
+}
+
+static const char * const gnttabop_error_msgs[] = GNTTABOP_error_msgs;
+
+const char *
+gnttabop_error(int16_t status)
+{
+    status = -status;
+    if (status < 0 || status >= ARRAY_SIZE(gnttabop_error_msgs))
+       return "bad status";
+    else
+        return gnttabop_error_msgs[status];
+}
+
+#if 0
+xen_pfn_t
+gnttab_pfn_to_mfn (xen_pfn_t pfn)
+{
+    xen_pfn_t xpfn = pfn;
+    xen_translate_gpfn_list_t xlat;
+
+    xlat.domid = DOMID_SELF;
+    xlat.nr_gpfns = 1;
+    set_xen_guest_handle(xlat.gpfn_list, &xpfn);
+    HYPERCALL_translate_();
+}
+#endif
+
+void
+init_gnttab(void)
+{
+    struct gnttab_setup_table setup;
+    unsigned long frames[NR_GRANT_FRAMES];
+    int i;
+
+    gnttab_list[0] = GRANT_INVALID_REF;
+    for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
+        put_free_entry(i);
+
+    setup.dom = DOMID_SELF;
+    setup.nr_frames = NR_GRANT_FRAMES;
+    set_xen_guest_handle(setup.frame_list, frames);
+
+    HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
+    gnttab_table = (grant_entry_t*)(frames[0] << PAGE_SHIFT); /* IA64  */
+    printk("gnttab_table mapped at %p.\n", gnttab_table);
+}
diff -r 092232fa1fbd extras/stubfw/hobs.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/hobs.c      Sun Nov 11 02:08:36 2007 +0100
@@ -0,0 +1,197 @@
+#include "lib.h"
+
+#define PERROR(x)
+
+#define HOB_SIGNATURE         0x3436474953424f48        // "HOBSIG64"
+#define GFW_HOB_START         ((4UL<<30)-(14UL<<20))    // 4G - 14M
+#define GFW_HOB_SIZE          (1UL<<20)                 // 1M
+
+typedef struct {
+    unsigned long signature;
+    unsigned int  type;
+    unsigned int  length;
+} HOB_GENERIC_HEADER;
+
+/*
+ * INFO HOB is the first data data in one HOB list
+ * it contains the control information of the HOB list
+ */
+typedef struct {
+    HOB_GENERIC_HEADER  header;
+    unsigned long       length;    // current length of hob
+    unsigned long       cur_pos;   // current poisiton of hob
+    unsigned long       buf_size;  // size of hob buffer
+} HOB_INFO;
+
+typedef struct{
+    unsigned long start;
+    unsigned long size;
+} hob_mem_t;
+
+typedef enum {
+    HOB_TYPE_INFO=0,
+    HOB_TYPE_TERMINAL,
+    HOB_TYPE_MEM,
+    HOB_TYPE_PAL_BUS_GET_FEATURES_DATA,
+    HOB_TYPE_PAL_CACHE_SUMMARY,
+    HOB_TYPE_PAL_MEM_ATTRIB,
+    HOB_TYPE_PAL_CACHE_INFO,
+    HOB_TYPE_PAL_CACHE_PROT_INFO,
+    HOB_TYPE_PAL_DEBUG_INFO,
+    HOB_TYPE_PAL_FIXED_ADDR,
+    HOB_TYPE_PAL_FREQ_BASE,
+    HOB_TYPE_PAL_FREQ_RATIOS,
+    HOB_TYPE_PAL_HALT_INFO,
+    HOB_TYPE_PAL_PERF_MON_INFO,
+    HOB_TYPE_PAL_PROC_GET_FEATURES,
+    HOB_TYPE_PAL_PTCE_INFO,
+    HOB_TYPE_PAL_REGISTER_INFO,
+    HOB_TYPE_PAL_RSE_INFO,
+    HOB_TYPE_PAL_TEST_INFO,
+    HOB_TYPE_PAL_VM_SUMMARY,
+    HOB_TYPE_PAL_VM_INFO,
+    HOB_TYPE_PAL_VM_PAGE_SIZE,
+    HOB_TYPE_NR_VCPU,
+    HOB_TYPE_NVRAM,
+    HOB_TYPE_MAX
+} hob_type_t;
+
+static int hob_init(char  *buffer ,unsigned long buf_size);
+static int add_mem_hob(char* hob_buf, unsigned long dom_mem_size);
+static int add_vcpus_hob(char* hob_buf, unsigned long nr_vcpu);
+static int add_nvram_hob(void* hob_buf, unsigned long nvram_addr);
+
+static int
+hob_init(char *buffer, unsigned long buf_size)
+{
+    HOB_INFO *phit;
+    HOB_GENERIC_HEADER *terminal;
+
+    if (sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER) > buf_size) {
+        // buffer too small
+        return -1;
+    }
+
+    phit = (HOB_INFO*)buffer;
+    phit->header.signature = HOB_SIGNATURE;
+    phit->header.type = HOB_TYPE_INFO;
+    phit->header.length = sizeof(HOB_INFO);
+    phit->length = sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER);
+    phit->cur_pos = 0;
+    phit->buf_size = buf_size;
+
+    terminal = (HOB_GENERIC_HEADER*)(buffer + sizeof(HOB_INFO));
+    terminal->signature = HOB_SIGNATURE;
+    terminal->type = HOB_TYPE_TERMINAL;
+    terminal->length = sizeof(HOB_GENERIC_HEADER);
+
+    return 0;
+}
+
+/*
+ *  Add a new HOB to the HOB List.
+ *
+ *  hob_start  -  start address of hob buffer
+ *  type       -  type of the hob to be added
+ *  data       -  data of the hob to be added
+ *  data_size  -  size of the data
+ */
+static int
+hob_add(char* hob_start, int type, void* data, int data_size)
+{
+    HOB_INFO *phit;
+    HOB_GENERIC_HEADER *newhob, *tail;
+
+    phit = (HOB_INFO*)hob_start;
+
+    if (phit->length + data_size > phit->buf_size) {
+        // no space for new hob
+        return -1;
+    }
+
+    //append new HOB
+    newhob = (HOB_GENERIC_HEADER*)(hob_start + phit->length -
+                                   sizeof(HOB_GENERIC_HEADER));
+    newhob->signature = HOB_SIGNATURE;
+    newhob->type = type;
+    newhob->length = data_size + sizeof(HOB_GENERIC_HEADER);
+    memcpy((char*)newhob + sizeof(HOB_GENERIC_HEADER), data, data_size);
+
+    // append terminal HOB
+    tail = (HOB_GENERIC_HEADER*)(hob_start + phit->length + data_size);
+    tail->signature = HOB_SIGNATURE;
+    tail->type = HOB_TYPE_TERMINAL;
+    tail->length = sizeof(HOB_GENERIC_HEADER);
+
+    // adjust HOB list length
+    phit->length += sizeof(HOB_GENERIC_HEADER) + data_size;
+
+    return 0;
+}
+
+
+#define MIN(x, y) ((x) < (y)) ? (x) : (y)
+static int
+add_mem_hob(char* hob_buf, unsigned long dom_mem_size)
+{
+    hob_mem_t memhob;
+
+    // less than 3G
+    memhob.start = 0;
+    memhob.size = MIN(dom_mem_size, 0xC0000000);
+
+    if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0)
+        return -1;
+
+    if (dom_mem_size > 0xC0000000) {
+        // 4G ~ 4G+remain
+        memhob.start = 0x100000000; //4G
+        memhob.size = dom_mem_size - 0xC0000000;
+        if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0)
+            return -1;
+    }
+    return 0;
+}
+
+static int 
+add_vcpus_hob(char* hob_buf, unsigned long vcpus)
+{
+    return hob_add(hob_buf, HOB_TYPE_NR_VCPU, &vcpus, sizeof(vcpus));
+}
+
+static int
+add_nvram_hob(void *hob_buf, unsigned long nvram_addr)
+{
+    return hob_add(hob_buf, HOB_TYPE_NVRAM, &nvram_addr, sizeof(nvram_addr));
+}
+
+int
+build_hob(unsigned long dom_mem_size, unsigned long vcpus,
+         unsigned long nvram_addr)
+{
+    char* hob_buf = (char *)GFW_HOB_START;
+    unsigned long hob_buf_size = GFW_HOB_SIZE;
+
+    //Init HOB List
+    if (hob_init(hob_buf, hob_buf_size) < 0) {
+        PERROR("buffer too small");
+       return -1;
+    }
+
+    if (add_mem_hob(hob_buf,dom_mem_size) < 0) {
+        PERROR("Add memory hob failed, buffer too small");
+       return -1;
+    }
+
+    if (add_vcpus_hob(hob_buf, vcpus) < 0) {
+        PERROR("Add NR_VCPU hob failed, buffer too small");
+       return -1;
+    }
+
+    if (add_nvram_hob( hob_buf, nvram_addr ) < 0) {
+        PERROR("Add nvram hob failed, buffer too small");
+       return -1;
+    }
+
+    return 0;
+}
diff -r 092232fa1fbd extras/stubfw/include/atomic.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/include/atomic.h    Wed Nov 07 00:40:13 2007 +0100
@@ -0,0 +1,508 @@
+/*
+ * This code is mostly taken from FreeBSD machine/atomic.h
+ * Changes: Dietmar Hahn <dietmar.hahn@xxxxxxxxxxxxxxxxxxx>
+ *
+ ****************************************************************************
+ * Copyright (c) 1998 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _MACHINE_ATOMIC_H_
+#define _MACHINE_ATOMIC_H_
+
+/*
+ * Various simple arithmetic on memory which is atomic in the presence
+ * of interrupts and SMP safe.
+ */
+
+#if !defined(__ASSEMBLY__)
+
+#include <types.h>
+
+
+/*
+ * Everything is built out of cmpxchg.
+ */
+#define IA64_CMPXCHG(sz, sem, p, cmpval, newval, ret)          \
+       __asm __volatile (                                      \
+               "mov ar.ccv=%2;;\n\t"                           \
+               "cmpxchg" #sz "." #sem " %0=%4,%3,ar.ccv\n\t"   \
+               : "=r" (ret), "=m" (*p)                         \
+               : "r" (cmpval), "r" (newval), "m" (*p)          \
+               : "memory")
+
+
+/*
+ * Some common forms of cmpxch.
+ */
+
+static __inline uint8_t
+ia64_cmpxchg_acq_8(volatile uint8_t* p, uint8_t cmpval, uint8_t newval)
+{
+       uint8_t ret;
+
+       IA64_CMPXCHG(1, acq, p, cmpval, newval, ret);
+       return (ret);
+}
+
+static __inline uint16_t
+ia64_cmpxchg_acq_16(volatile uint16_t* p, uint16_t cmpval, uint16_t newval)
+{
+       uint16_t ret;
+
+       IA64_CMPXCHG(2, acq, p, cmpval, newval, ret);
+       return (ret);
+}
+
+static __inline uint32_t
+ia64_cmpxchg_acq_32(volatile uint32_t* p, uint32_t cmpval, uint32_t newval)
+{
+       uint32_t ret;
+
+       IA64_CMPXCHG(4, acq, p, cmpval, newval, ret);
+       return (ret);
+}
+
+static __inline uint32_t
+ia64_cmpxchg_rel_32(volatile uint32_t* p, uint32_t cmpval, uint32_t newval)
+{
+       uint32_t ret;
+
+       IA64_CMPXCHG(4, rel, p, cmpval, newval, ret);
+       return (ret);
+}
+
+static __inline uint64_t
+ia64_cmpxchg_acq_64(volatile uint64_t* p, uint64_t cmpval, uint64_t newval)
+{
+       uint64_t ret;
+
+       IA64_CMPXCHG(8, acq, p, cmpval, newval, ret);
+       return (ret);
+}
+
+static __inline uint64_t
+ia64_cmpxchg_rel_64(volatile uint64_t* p, uint64_t cmpval, uint64_t newval)
+{
+       uint64_t ret;
+
+       IA64_CMPXCHG(8, rel, p, cmpval, newval, ret);
+       return (ret);
+}
+
+#define ATOMIC_STORE_LOAD(type, width, size)                   \
+static __inline uint##width##_t                                \
+ia64_ld_acq_##width(volatile uint##width##_t* p)               \
+{                                                              \
+       uint##width##_t v;                                      \
+                                                               \
+       __asm __volatile ("ld" size ".acq %0=%1"                \
+                         : "=r" (v)                            \
+                         : "m" (*p)                            \
+                         : "memory");                          \
+       return (v);                                             \
+}                                                              \
+                                                               \
+static __inline uint##width##_t                                \
+atomic_load_acq_##width(volatile uint##width##_t* p)           \
+{                                                              \
+       uint##width##_t v;                                      \
+                                                               \
+       __asm __volatile ("ld" size ".acq %0=%1"                \
+                         : "=r" (v)                            \
+                         : "m" (*p)                            \
+                         : "memory");                          \
+       return (v);                                             \
+}                                                              \
+                                                               \
+static __inline uint##width##_t                                \
+atomic_load_acq_##type(volatile uint##width##_t* p)            \
+{                                                              \
+       uint##width##_t v;                                      \
+                                                               \
+       __asm __volatile ("ld" size ".acq %0=%1"                \
+                         : "=r" (v)                            \
+                         : "m" (*p)                            \
+                         : "memory");                          \
+       return (v);                                             \
+}                                                              \
+                                                               \
+static __inline void                                           \
+ia64_st_rel_##width(volatile uint##width##_t* p, uint##width##_t v)\
+{                                                              \
+       __asm __volatile ("st" size ".rel %0=%1"                \
+                         : "=m" (*p)                           \
+                         : "r" (v)                             \
+                         : "memory");                          \
+}                                                              \
+                                                               \
+static __inline void                                           \
+atomic_store_rel_##width(volatile uint##width##_t* p, uint##width##_t v)\
+{                                                              \
+       __asm __volatile ("st" size ".rel %0=%1"                \
+                         : "=m" (*p)                           \
+                         : "r" (v)                             \
+                         : "memory");                          \
+}                                                              \
+                                                               \
+static __inline void                                           \
+atomic_store_rel_##type(volatile uint##width##_t* p, uint##width##_t v)\
+{                                                              \
+       __asm __volatile ("st" size ".rel %0=%1"                \
+                         : "=m" (*p)                           \
+                         : "r" (v)                             \
+                         : "memory");                          \
+}
+
+ATOMIC_STORE_LOAD(char, 8, "1")
+ATOMIC_STORE_LOAD(short, 16, "2")
+ATOMIC_STORE_LOAD(int, 32, "4")
+ATOMIC_STORE_LOAD(long, 64, "8")
+
+#undef ATOMIC_STORE_LOAD
+
+#define IA64_ATOMIC(sz, type, name, width, op)                 \
+                                                                       \
+static __inline type                                                   \
+atomic_##name##_acq_##width(volatile type *p, type v)          \
+{                                                                      \
+       type old, ret;                                                  \
+       do {                                                            \
+               old = *p;                                               \
+               IA64_CMPXCHG(sz, acq, p, old, old op v, ret);   \
+       } while (ret != old);                                           \
+       return(ret);                                                    \
+}                                                                      \
+                                                                       \
+static __inline type                                                   \
+atomic_##name##_rel_##width(volatile type *p, type v)          \
+{                                                                      \
+       type old, ret;                                                  \
+       do {                                                            \
+               old = *p;                                               \
+               IA64_CMPXCHG(sz, rel, p, old, old op v, ret);   \
+       } while (ret != old);                                           \
+       return(ret);                                                    \
+}
+
+IA64_ATOMIC(1, uint8_t,  set,  8,      |)
+IA64_ATOMIC(2, uint16_t, set,  16,     |)
+IA64_ATOMIC(4, uint32_t, set,  32,     |)
+IA64_ATOMIC(8, uint64_t, set,  64,     |)
+
+IA64_ATOMIC(1, uint8_t,  clear,        8,      &~)
+IA64_ATOMIC(2, uint16_t, clear,        16,     &~)
+IA64_ATOMIC(4, uint32_t, clear,        32,     &~)
+IA64_ATOMIC(8, uint64_t, clear,        64,     &~)
+
+IA64_ATOMIC(1, uint8_t,  add,  8,      +)
+IA64_ATOMIC(2, uint16_t, add,  16,     +)
+IA64_ATOMIC(4, uint32_t, add,  32,     +)
+IA64_ATOMIC(8, uint64_t, add,  64,     +)
+
+IA64_ATOMIC(1, uint8_t,  subtract,     8,      -)
+IA64_ATOMIC(2, uint16_t, subtract,     16,     -)
+IA64_ATOMIC(4, uint32_t, subtract,     32,     -)
+IA64_ATOMIC(8, uint64_t, subtract,     64,     -)
+
+#undef IA64_ATOMIC
+#undef IA64_CMPXCHG
+
+#define atomic_set_8                   atomic_set_acq_8
+#define        atomic_clear_8                  atomic_clear_acq_8
+#define atomic_add_8                   atomic_add_acq_8
+#define        atomic_subtract_8               atomic_subtract_acq_8
+
+#define atomic_set_16                  atomic_set_acq_16
+#define        atomic_clear_16                 atomic_clear_acq_16
+#define atomic_add_16                  atomic_add_acq_16
+#define        atomic_subtract_16              atomic_subtract_acq_16
+
+#define atomic_set_32                  atomic_set_acq_32
+#define        atomic_clear_32                 atomic_clear_acq_32
+#define atomic_add_32                  atomic_add_acq_32
+#define        atomic_subtract_32              atomic_subtract_acq_32
+
+#define atomic_set_64                  atomic_set_acq_64
+#define        atomic_clear_64                 atomic_clear_acq_64
+#define atomic_add_64                  atomic_add_acq_64
+#define        atomic_subtract_64              atomic_subtract_acq_64
+
+#define atomic_set_char                        atomic_set_8
+#define atomic_clear_char              atomic_clear_8
+#define atomic_add_char                        atomic_add_8
+#define atomic_subtract_char           atomic_subtract_8
+#define atomic_set_acq_char            atomic_set_acq_8
+#define atomic_clear_acq_char          atomic_clear_acq_8
+#define atomic_add_acq_char            atomic_add_acq_8
+#define atomic_subtract_acq_char       atomic_subtract_acq_8
+#define atomic_set_rel_char            atomic_set_rel_8
+#define atomic_clear_rel_char          atomic_clear_rel_8
+#define atomic_add_rel_char            atomic_add_rel_8
+#define atomic_subtract_rel_char       atomic_subtract_rel_8
+
+#define atomic_set_short               atomic_set_16
+#define atomic_clear_short             atomic_clear_16
+#define atomic_add_short               atomic_add_16
+#define atomic_subtract_short          atomic_subtract_16
+#define atomic_set_acq_short           atomic_set_acq_16
+#define atomic_clear_acq_short         atomic_clear_acq_16
+#define atomic_add_acq_short           atomic_add_acq_16
+#define atomic_subtract_acq_short      atomic_subtract_acq_16
+#define atomic_set_rel_short           atomic_set_rel_16
+#define atomic_clear_rel_short         atomic_clear_rel_16
+#define atomic_add_rel_short           atomic_add_rel_16
+#define atomic_subtract_rel_short      atomic_subtract_rel_16
+
+#define atomic_set_int                 atomic_set_32
+#define atomic_clear_int               atomic_clear_32
+#define atomic_add_int                 atomic_add_32
+#define atomic_subtract_int            atomic_subtract_32
+#define atomic_set_acq_int             atomic_set_acq_32
+#define atomic_clear_acq_int           atomic_clear_acq_32
+#define atomic_add_acq_int             atomic_add_acq_32
+#define atomic_subtract_acq_int                atomic_subtract_acq_32
+#define atomic_set_rel_int             atomic_set_rel_32
+#define atomic_clear_rel_int           atomic_clear_rel_32
+#define atomic_add_rel_int             atomic_add_rel_32
+#define atomic_subtract_rel_int                atomic_subtract_rel_32
+
+#define atomic_set_long                        atomic_set_64
+#define atomic_clear_long              atomic_clear_64
+#define atomic_add_long                        atomic_add_64
+#define atomic_subtract_long           atomic_subtract_64
+#define atomic_set_acq_long            atomic_set_acq_64
+#define atomic_clear_acq_long          atomic_clear_acq_64
+#define atomic_add_acq_long            atomic_add_acq_64
+#define atomic_subtract_acq_long       atomic_subtract_acq_64
+#define atomic_set_rel_long            atomic_set_rel_64
+#define atomic_clear_rel_long          atomic_clear_rel_64
+#define atomic_add_rel_long            atomic_add_rel_64
+#define atomic_subtract_rel_long       atomic_subtract_rel_64
+
+/*
+ * Atomically compare the value stored at *p with cmpval and if the
+ * two values are equal, update the value of *p with newval. Returns
+ * zero if the compare failed, nonzero otherwise.
+ */
+static __inline int
+atomic_cmpset_acq_32(volatile uint32_t* p, uint32_t cmpval, uint32_t newval)
+{
+       return ia64_cmpxchg_acq_32(p, cmpval, newval) == cmpval;
+}
+
+static __inline int
+atomic_cmpset_rel_32(volatile uint32_t* p, uint32_t cmpval, uint32_t newval)
+{
+       return ia64_cmpxchg_rel_32(p, cmpval, newval) == cmpval;
+}
+
+/*
+ * Atomically compare the value stored at *p with cmpval and if the
+ * two values are equal, update the value of *p with newval. Returns
+ * zero if the compare failed, nonzero otherwise.
+ */
+static __inline int
+atomic_cmpset_acq_64(volatile uint64_t* p, uint64_t cmpval, uint64_t newval)
+{
+       return ia64_cmpxchg_acq_64(p, cmpval, newval) == cmpval;
+}
+
+static __inline int
+atomic_cmpset_rel_64(volatile uint64_t* p, uint64_t cmpval, uint64_t newval)
+{
+       return ia64_cmpxchg_rel_64(p, cmpval, newval) == cmpval;
+}
+
+#define atomic_cmpset_32               atomic_cmpset_acq_32
+#define atomic_cmpset_64               atomic_cmpset_acq_64
+#define        atomic_cmpset_int               atomic_cmpset_32
+#define        atomic_cmpset_long              atomic_cmpset_64
+#define atomic_cmpset_acq_int          atomic_cmpset_acq_32
+#define atomic_cmpset_rel_int          atomic_cmpset_rel_32
+#define atomic_cmpset_acq_long         atomic_cmpset_acq_64
+#define atomic_cmpset_rel_long         atomic_cmpset_rel_64
+
+static __inline int
+atomic_cmpset_acq_ptr(volatile void *dst, void *exp, void *src)
+{
+        return atomic_cmpset_acq_long((volatile u_long *)dst,
+                                     (u_long)exp, (u_long)src);
+}
+
+static __inline int
+atomic_cmpset_rel_ptr(volatile void *dst, void *exp, void *src)
+{
+        return atomic_cmpset_rel_long((volatile u_long *)dst,
+                                     (u_long)exp, (u_long)src);
+}
+
+#define        atomic_cmpset_ptr       atomic_cmpset_acq_ptr
+
+static __inline void *
+atomic_load_acq_ptr(volatile void *p)
+{
+       return (void *)atomic_load_acq_long((volatile u_long *)p);
+}
+
+static __inline void
+atomic_store_rel_ptr(volatile void *p, void *v)
+{
+       atomic_store_rel_long((volatile u_long *)p, (u_long)v);
+}
+
+#define IA64_ATOMIC_PTR(NAME)                          \
+static __inline void                                   \
+atomic_##NAME##_ptr(volatile void *p, uintptr_t v)     \
+{                                                      \
+       atomic_##NAME##_long((volatile u_long *)p, v);  \
+}                                                      \
+                                                       \
+static __inline void                                   \
+atomic_##NAME##_acq_ptr(volatile void *p, uintptr_t v) \
+{                                                      \
+       atomic_##NAME##_acq_long((volatile u_long *)p, v);\
+}                                                      \
+                                                       \
+static __inline void                                   \
+atomic_##NAME##_rel_ptr(volatile void *p, uintptr_t v) \
+{                                                      \
+       atomic_##NAME##_rel_long((volatile u_long *)p, v);\
+}
+
+IA64_ATOMIC_PTR(set)
+IA64_ATOMIC_PTR(clear)
+IA64_ATOMIC_PTR(add)
+IA64_ATOMIC_PTR(subtract)
+
+#undef IA64_ATOMIC_PTR
+
+static __inline uint32_t
+atomic_readandclear_32(volatile uint32_t* p)
+{
+       uint32_t val;
+       do {
+               val = *p;
+       } while (!atomic_cmpset_32(p, val, 0));
+       return val;
+}
+
+static __inline uint64_t
+atomic_readandclear_64(volatile uint64_t* p)
+{
+       uint64_t val;
+       do {
+               val = *p;
+       } while (!atomic_cmpset_64(p, val, 0));
+       return val;
+}
+
+#define atomic_readandclear_int        atomic_readandclear_32
+#define atomic_readandclear_long       atomic_readandclear_64
+
+
+/* Some bit operations */
+
+static inline void
+set_bit(int num, volatile void *addr)
+{
+       uint32_t bit, b, old, new;
+       volatile uint32_t *p;
+       p = (volatile uint32_t *) addr + (num >> 5);
+       b = 1 << (num & 31);
+       bit = b;
+       do
+       {
+               old = *p;
+               new = old | bit;
+       } while(ia64_cmpxchg_acq_32(p, old, new) != old);
+}
+
+static __inline__ void
+clear_bit(int num, volatile void *addr)
+{
+       uint32_t mask, m,  old, new;
+       volatile uint32_t *p;
+       p = (volatile uint32_t *) addr + (num >> 5);
+       m = ~(1 << (num & 31));
+       mask = m;
+       do {
+               old = *p;
+               new = old & mask;
+       } while (ia64_cmpxchg_acq_32(p, old, new) != old);
+}
+
+static __inline__ int
+test_bit(int num, const volatile void *addr)
+{
+       uint32_t val = 1;
+        return val & (((const volatile uint32_t *) addr)[num >> 5] >> (num & 
31));
+}
+
+/*
+ * test_and_set_bit - Set a bit and return its old value
+ * num: Bit to set
+ * addr: Address to count from
+ */
+static inline int
+test_and_set_bit (int num, volatile void *addr)
+{
+        uint32_t bit, b, old, new;
+        volatile uint32_t *m;
+
+        m = (volatile uint32_t *) addr + (num >> 5);
+        b = 1 << (num & 31);
+        bit = b;
+        do {
+                old = *m;
+                new = old | bit;
+        } while (ia64_cmpxchg_acq_32(m, old, new) != old);
+        return (old & bit) != 0;
+}
+
+/*
+ * test_and_clear_bit - Clear a bit and return its old value
+ * num: Bit to set
+ * addr: Address to count from
+ */
+static
+inline int test_and_clear_bit(int num, volatile unsigned long * addr)
+{
+        uint32_t bit, b, old, new;
+        volatile uint32_t* a;
+
+        a = (volatile uint32_t *) addr + (num >> 5);
+        b = ~(1 << (num & 31));
+        bit = b;
+        do {
+                old = *a;
+                new = old & bit;
+        } while (ia64_cmpxchg_acq_32(a, old, new) != old);
+        return (old & ~bit) != 0;
+}
+
+
+#endif /* !defined(__ASSEMBLY__) */
+
+#endif /* ! _MACHINE_ATOMIC_H_ */
diff -r 092232fa1fbd extras/stubfw/include/callback.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/include/callback.h  Thu Nov 08 04:43:55 2007 +0100
@@ -0,0 +1,43 @@
+#include "ia64_fpu.h"
+
+struct ia64_cb_regs {
+  unsigned long unat;
+  unsigned long _pad1;
+  unsigned long r1;
+  unsigned long r2;
+  unsigned long r3;
+  unsigned long r4;
+  unsigned long r5;
+  unsigned long r8;
+  unsigned long r9;
+  unsigned long r10;
+  unsigned long r11;
+  unsigned long r12;
+  unsigned long r13;
+  unsigned long r14;
+  unsigned long r15;
+  unsigned long pr;
+  unsigned long b0;
+  unsigned long b6;
+  unsigned long b7;
+  unsigned long fpsr;
+  ia64_fpreg_t  f6;
+  ia64_fpreg_t  f7;
+  ia64_fpreg_t  f8;
+  ia64_fpreg_t  f9;
+  ia64_fpreg_t  f10;
+  ia64_fpreg_t  f11;
+  unsigned long rsc;
+  unsigned long pfs;
+  unsigned long ccv;
+  unsigned long nats;
+  unsigned long ip;
+  unsigned long psr;
+  unsigned long cfm;
+  unsigned long rsv;
+  unsigned long bspstore;
+  unsigned long rnat;
+  unsigned long ndirty;
+};
+
+  
diff -r 092232fa1fbd extras/stubfw/include/ctype.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/include/ctype.h     Wed Nov 07 00:40:13 2007 +0100
@@ -0,0 +1,79 @@
+#ifndef _CTYPE_H
+#define _CTYPE_H
+
+/*
+ * NOTE! This ctype does not handle EOF like the standard C
+ * library is required to.
+ */
+
+#define _U     0x01    /* upper */
+#define _L     0x02    /* lower */
+#define _D     0x04    /* digit */
+#define _C     0x08    /* cntrl */
+#define _P     0x10    /* punct */
+#define _S     0x20    /* white space (space/lf/tab) */
+#define _X     0x40    /* hex digit */
+#define _SP    0x80    /* hard space (0x20) */
+
+
+unsigned char _ctype[] = {
+_C,_C,_C,_C,_C,_C,_C,_C,                        /* 0-7 */
+_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C,         /* 8-15 */
+_C,_C,_C,_C,_C,_C,_C,_C,                        /* 16-23 */
+_C,_C,_C,_C,_C,_C,_C,_C,                        /* 24-31 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,                    /* 32-39 */
+_P,_P,_P,_P,_P,_P,_P,_P,                        /* 40-47 */
+_D,_D,_D,_D,_D,_D,_D,_D,                        /* 48-55 */
+_D,_D,_P,_P,_P,_P,_P,_P,                        /* 56-63 */
+_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U,      /* 64-71 */
+_U,_U,_U,_U,_U,_U,_U,_U,                        /* 72-79 */
+_U,_U,_U,_U,_U,_U,_U,_U,                        /* 80-87 */
+_U,_U,_U,_P,_P,_P,_P,_P,                        /* 88-95 */
+_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L,      /* 96-103 */
+_L,_L,_L,_L,_L,_L,_L,_L,                        /* 104-111 */
+_L,_L,_L,_L,_L,_L,_L,_L,                        /* 112-119 */
+_L,_L,_L,_P,_P,_P,_P,_C,                        /* 120-127 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                /* 128-143 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                /* 144-159 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,   /* 160-175 */
+_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,       /* 176-191 */
+_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,       /* 192-207 */
+_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L,       /* 208-223 */
+_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,       /* 224-239 */
+_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L};      /* 240-255 */
+
+#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
+
+#define isalnum(c)     ((__ismask(c)&(_U|_L|_D)) != 0)
+#define isalpha(c)     ((__ismask(c)&(_U|_L)) != 0)
+#define iscntrl(c)     ((__ismask(c)&(_C)) != 0)
+#define isdigit(c)     ((__ismask(c)&(_D)) != 0)
+#define isgraph(c)     ((__ismask(c)&(_P|_U|_L|_D)) != 0)
+#define islower(c)     ((__ismask(c)&(_L)) != 0)
+#define isprint(c)     ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
+#define ispunct(c)     ((__ismask(c)&(_P)) != 0)
+#define isspace(c)     ((__ismask(c)&(_S)) != 0)
+#define isupper(c)     ((__ismask(c)&(_U)) != 0)
+#define isxdigit(c)    ((__ismask(c)&(_D|_X)) != 0)
+
+#define isascii(c) (((unsigned char)(c))<=0x7f)
+#define toascii(c) (((unsigned char)(c))&0x7f)
+
+static inline unsigned char __tolower(unsigned char c)
+{
+       if (isupper(c))
+               c -= 'A'-'a';
+       return c;
+}
+
+static inline unsigned char __toupper(unsigned char c)
+{
+       if (islower(c))
+               c -= 'a'-'A';
+       return c;
+}
+
+#define tolower(c) __tolower(c)
+#define toupper(c) __toupper(c)
+
+#endif
diff -r 092232fa1fbd extras/stubfw/include/err.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/include/err.h       Wed Nov 07 00:40:13 2007 +0100
@@ -0,0 +1,31 @@
+#ifndef _ERR_H
+#define _ERR_H
+
+#include <errno.h>
+
+/*
+ * Kernel pointers have redundant information, so we can use a
+ * scheme where we can return either an error code or a dentry
+ * pointer with the same return value.
+ *
+ * This should be a per-architecture thing, to allow different
+ * error and pointer decisions.
+ */
+#define IS_ERR_VALUE(x) ((x) > (unsigned long)-1000L)
+
+static inline void *ERR_PTR(long error)
+{
+       return (void *) error;
+}
+
+static inline long PTR_ERR(const void *ptr)
+{
+       return (long) ptr;
+}
+
+static inline long IS_ERR(const void *ptr)
+{
+       return IS_ERR_VALUE((unsigned long)ptr);
+}
+
+#endif /* _LINUX_ERR_H */
diff -r 092232fa1fbd extras/stubfw/include/errno-base.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/include/errno-base.h        Wed Nov 07 00:40:13 2007 +0100
@@ -0,0 +1,39 @@
+#ifndef _ERRNO_BASE_H
+#define _ERRNO_BASE_H
+
+#define        EPERM            1      /* Operation not permitted */
+#define        ENOENT           2      /* No such file or directory */
+#define        ESRCH            3      /* No such process */
+#define        EINTR            4      /* Interrupted system call */
+#define        EIO              5      /* I/O error */
+#define        ENXIO            6      /* No such device or address */
+#define        E2BIG            7      /* Argument list too long */
+#define        ENOEXEC          8      /* Exec format error */
+#define        EBADF            9      /* Bad file number */
+#define        ECHILD          10      /* No child processes */
+#define        EAGAIN          11      /* Try again */
+#define        ENOMEM          12      /* Out of memory */
+#define        EACCES          13      /* Permission denied */
+#define        EFAULT          14      /* Bad address */
+#define        ENOTBLK         15      /* Block device required */
+#define        EBUSY           16      /* Device or resource busy */
+#define        EEXIST          17      /* File exists */
+#define        EXDEV           18      /* Cross-device link */
+#define        ENODEV          19      /* No such device */
+#define        ENOTDIR         20      /* Not a directory */
+#define        EISDIR          21      /* Is a directory */
+#define        EINVAL          22      /* Invalid argument */
+#define        ENFILE          23      /* File table overflow */
+#define        EMFILE          24      /* Too many open files */
+#define        ENOTTY          25      /* Not a typewriter */
+#define        ETXTBSY         26      /* Text file busy */
+#define        EFBIG           27      /* File too large */
+#define        ENOSPC          28      /* No space left on device */
+#define        ESPIPE          29      /* Illegal seek */
+#define        EROFS           30      /* Read-only file system */
+#define        EMLINK          31      /* Too many links */
+#define        EPIPE           32      /* Broken pipe */
+#define        EDOM            33      /* Math argument out of domain of func 
*/
+#define        ERANGE          34      /* Math result not representable */
+
+#endif
diff -r 092232fa1fbd extras/stubfw/include/errno.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/include/errno.h     Thu Nov 15 02:10:03 2007 +0100
@@ -0,0 +1,110 @@
+#ifndef _ERRNO_H
+#define _ERRNO_H
+
+#include <errno-base.h>
+
+#define        EDEADLK         35      /* Resource deadlock would occur */
+#define        ENAMETOOLONG    36      /* File name too long */
+#define        ENOLCK          37      /* No record locks available */
+#define        ENOSYS          38      /* Function not implemented */
+#define        ENOTEMPTY       39      /* Directory not empty */
+#define        ELOOP           40      /* Too many symbolic links encountered 
*/
+#define        EWOULDBLOCK     EAGAIN  /* Operation would block */
+#define        ENOMSG          42      /* No message of desired type */
+#define        EIDRM           43      /* Identifier removed */
+#define        ECHRNG          44      /* Channel number out of range */
+#define        EL2NSYNC        45      /* Level 2 not synchronized */
+#define        EL3HLT          46      /* Level 3 halted */
+#define        EL3RST          47      /* Level 3 reset */
+#define        ELNRNG          48      /* Link number out of range */
+#define        EUNATCH         49      /* Protocol driver not attached */
+#define        ENOCSI          50      /* No CSI structure available */
+#define        EL2HLT          51      /* Level 2 halted */
+#define        EBADE           52      /* Invalid exchange */
+#define        EBADR           53      /* Invalid request descriptor */
+#define        EXFULL          54      /* Exchange full */
+#define        ENOANO          55      /* No anode */
+#define        EBADRQC         56      /* Invalid request code */
+#define        EBADSLT         57      /* Invalid slot */
+
+#define        EDEADLOCK       EDEADLK
+
+#define        EBFONT          59      /* Bad font file format */
+#define        ENOSTR          60      /* Device not a stream */
+#define        ENODATA         61      /* No data available */
+#define        ETIME           62      /* Timer expired */
+#define        ENOSR           63      /* Out of streams resources */
+#define        ENONET          64      /* Machine is not on the network */
+#define        ENOPKG          65      /* Package not installed */
+#define        EREMOTE         66      /* Object is remote */
+#define        ENOLINK         67      /* Link has been severed */
+#define        EADV            68      /* Advertise error */
+#define        ESRMNT          69      /* Srmount error */
+#define        ECOMM           70      /* Communication error on send */
+#define        EPROTO          71      /* Protocol error */
+#define        EMULTIHOP       72      /* Multihop attempted */
+#define        EDOTDOT         73      /* RFS specific error */
+#define        EBADMSG         74      /* Not a data message */
+#define        EOVERFLOW       75      /* Value too large for defined data 
type */
+#define        ENOTUNIQ        76      /* Name not unique on network */
+#define        EBADFD          77      /* File descriptor in bad state */
+#define        EREMCHG         78      /* Remote address changed */
+#define        ELIBACC         79      /* Can not access a needed shared 
library */
+#define        ELIBBAD         80      /* Accessing a corrupted shared library 
*/
+#define        ELIBSCN         81      /* .lib section in a.out corrupted */
+#define        ELIBMAX         82      /* Attempting to link in too many 
shared libraries */
+#define        ELIBEXEC        83      /* Cannot exec a shared library 
directly */
+#define        EILSEQ          84      /* Illegal byte sequence */
+#define        ERESTART        85      /* Interrupted system call should be 
restarted */
+#define        ESTRPIPE        86      /* Streams pipe error */
+#define        EUSERS          87      /* Too many users */
+#define        ENOTSOCK        88      /* Socket operation on non-socket */
+#define        EDESTADDRREQ    89      /* Destination address required */
+#define        EMSGSIZE        90      /* Message too long */
+#define        EPROTOTYPE      91      /* Protocol wrong type for socket */
+#define        ENOPROTOOPT     92      /* Protocol not available */
+#define        EPROTONOSUPPORT 93      /* Protocol not supported */
+#define        ESOCKTNOSUPPORT 94      /* Socket type not supported */
+#define        EOPNOTSUPP      95      /* Operation not supported on transport 
endpoint */
+#define        EPFNOSUPPORT    96      /* Protocol family not supported */
+#define        EAFNOSUPPORT    97      /* Address family not supported by 
protocol */
+#define        EADDRINUSE      98      /* Address already in use */
+#define        EADDRNOTAVAIL   99      /* Cannot assign requested address */
+#define        ENETDOWN        100     /* Network is down */
+#define        ENETUNREACH     101     /* Network is unreachable */
+#define        ENETRESET       102     /* Network dropped connection because 
of reset */
+#define        ECONNABORTED    103     /* Software caused connection abort */
+#define        ECONNRESET      104     /* Connection reset by peer */
+#define        ENOBUFS         105     /* No buffer space available */
+#define        EISCONN         106     /* Transport endpoint is already 
connected */
+#define        ENOTCONN        107     /* Transport endpoint is not connected 
*/
+#define        ESHUTDOWN       108     /* Cannot send after transport endpoint 
shutdown */
+#define        ETOOMANYREFS    109     /* Too many references: cannot splice */
+#define        ETIMEDOUT       110     /* Connection timed out */
+#define        ECONNREFUSED    111     /* Connection refused */
+#define        EHOSTDOWN       112     /* Host is down */
+#define        EHOSTUNREACH    113     /* No route to host */
+#define        EALREADY        114     /* Operation already in progress */
+#define        EINPROGRESS     115     /* Operation now in progress */
+#define        ESTALE          116     /* Stale NFS file handle */
+#define        EUCLEAN         117     /* Structure needs cleaning */
+#define        ENOTNAM         118     /* Not a XENIX named type file */
+#define        ENAVAIL         119     /* No XENIX semaphores available */
+#define        EISNAM          120     /* Is a named type file */
+#define        EREMOTEIO       121     /* Remote I/O error */
+#define        EDQUOT          122     /* Quota exceeded */
+
+#define        ENOMEDIUM       123     /* No medium found */
+#define        EMEDIUMTYPE     124     /* Wrong medium type */
+#define        ECANCELED       125     /* Operation Canceled */
+#define        ENOKEY          126     /* Required key not available */
+#define        EKEYEXPIRED     127     /* Key has expired */
+#define        EKEYREVOKED     128     /* Key has been revoked */
+#define        EKEYREJECTED    129     /* Key was rejected by service */
+
+/* for robust mutexes */
+#define        EOWNERDEAD      130     /* Owner died */
+#define        ENOTRECOVERABLE 131     /* State not recoverable */
+
+#define ENOTSUP         150
+#endif
diff -r 092232fa1fbd extras/stubfw/include/events.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/include/events.h    Fri Nov 16 03:46:33 2007 +0100
@@ -0,0 +1,90 @@
+/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ * (C) 2005 - Grzegorz Milos - Intel Reseach Cambridge
+ ****************************************************************************
+ *
+ *        File: events.h
+ *      Author: Rolf Neugebauer (neugebar@xxxxxxxxxxxxx)
+ *     Changes: Grzegorz Milos (gm281@xxxxxxxxx)
+ *              
+ *        Date: Jul 2003, changes Jun 2005
+ * 
+ * Environment: Xen Minimal OS
+ * Description: Deals with events on the event channels
+ *
+ ****************************************************************************
+ */
+
+#ifndef _EVENTS_H_
+#define _EVENTS_H_
+
+#include "xen/event_channel.h"
+
+extern volatile struct shared_info *shared_info;
+
+typedef void (*evtchn_handler_t)(evtchn_port_t, void *);
+
+/* prototypes */
+int bind_virq(uint32_t virq, evtchn_handler_t handler, void *data);
+evtchn_port_t bind_evtchn(evtchn_port_t port, evtchn_handler_t handler,
+                                                 void *data);
+void unbind_evtchn(evtchn_port_t port);
+void init_events(void);
+int evtchn_alloc_unbound(domid_t pal, evtchn_handler_t handler,
+                                                void *data, evtchn_port_t 
*port);
+int evtchn_bind_interdomain(domid_t pal, evtchn_port_t remote_port,
+                                                       evtchn_handler_t 
handler, void *data,
+                                                       evtchn_port_t 
*local_port);
+void unbind_all_ports(void);
+
+static inline int notify_remote_via_evtchn(evtchn_port_t port)
+{
+    evtchn_send_t op;
+    op.port = port;
+    return HYPERVISOR_event_channel_op(EVTCHNOP_send, &op);
+}
+
+
+#define active_evtchns(cpu,sh,idx)              \
+    ((sh)->evtchn_pending[idx] &                \
+     ~(sh)->evtchn_mask[idx])
+
+static inline void clear_evtchn(u32 port)
+{
+  volatile shared_info_t *s = shared_info;
+  synch_clear_bit(port, &s->evtchn_pending[0]);
+}
+
+static inline void mask_evtchn(u32 port)
+{
+    synch_set_bit(port, &shared_info->evtchn_mask[0]);
+}
+
+static inline void unmask_evtchn(u32 port)
+{
+  volatile shared_info_t *s = shared_info;
+  volatile vcpu_info_t *vcpu_info = &s->vcpu_info[smp_processor_id()];
+
+  synch_clear_bit(port, &s->evtchn_mask[0]);
+  
+  /*
+   * The following is basically the equivalent of 'hw_resend_irq'. Just like
+   * a real IO-APIC we 'lose the interrupt edge' if the channel is masked.
+   */
+  if (  synch_test_bit        (port,    &s->evtchn_pending[0]) && 
+       !synch_test_and_set_bit(port>>5, &vcpu_info->evtchn_pending_sel) )
+    {
+      vcpu_info->evtchn_upcall_pending = 1;
+#if 0
+      if ( !vcpu_info->evtchn_upcall_mask )
+                 force_evtchn_callback();
+#endif
+    }
+}
+
+extern void do_hypervisor_callback(void);
+
+extern void poll_evtchn (evtchn_port_t port);
+
+#endif /* _EVENTS_H_ */
diff -r 092232fa1fbd extras/stubfw/include/gnttab.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/include/gnttab.h    Sat Nov 17 02:51:02 2007 +0100
@@ -0,0 +1,20 @@
+#ifndef __GNTTAB_H__
+#define __GNTTAB_H__
+
+#include <xen/grant_table.h>
+
+#define GRANT_INVALID_REF ((grant_ref_t)-1)
+
+void *alloc_free_page (size_t len);
+void *alloc_pages (int nbr);
+
+void init_gnttab(void);
+grant_ref_t gnttab_alloc_and_grant(void **map);
+grant_ref_t gnttab_grant_access(domid_t domid, unsigned long frame,
+                               int readonly);
+grant_ref_t gnttab_grant_transfer(domid_t domid, unsigned long pfn);
+unsigned long gnttab_end_transfer(grant_ref_t gref);
+int gnttab_end_access(grant_ref_t ref);
+const char *gnttabop_error(int16_t status);
+
+#endif /* !__GNTTAB_H__ */
diff -r 092232fa1fbd extras/stubfw/include/hypercall-ia64.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/include/hypercall-ia64.h    Thu Nov 22 04:05:26 2007 +0100
@@ -0,0 +1,349 @@
+/******************************************************************************
+ * hypercall.h
+ * 
+ * Mini-OS-specific hypervisor handling for ia64.
+ * 
+ * Copyright (c) 2002-2004, K A Fraser
+ * Changes: Dietmar Hahn <dietmar.hahn@xxxxxxxxxxxxxxxxxx>
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __HYPERCALL_H__
+#define __HYPERCALL_H__
+
+#include "errno.h"     /* ENOSYS() */
+#include <xen/event_channel.h>
+#include <xen/grant_table.h>
+#include <xen/sched.h>
+#include <xen/version.h>
+#include <xen/memory.h>
+#include <xen/hvm/hvm_op.h>
+#include "lib.h"
+
+#define PAGE_SHIFT 14
+#define PAGE_SIZE (1 << PAGE_SHIFT)
+#define addr_to_mfn(ADDR) (((unsigned long)ADDR) >> PAGE_SHIFT)
+
+#define get_xen_guest_handle(val, hnd)  do { val = (hnd).p; } while (0)
+
+#ifndef _HYPERVISOR_H_
+# error "please don't include this file directly"
+#endif
+
+// See linux/compiler.h
+#define likely(x)       __builtin_expect(!!(x), 1)
+#define unlikely(x)     __builtin_expect(!!(x), 0)
+
+extern unsigned long __hypercall(unsigned long a1, unsigned long a2,
+                                 unsigned long a3, unsigned long a4,
+                                 unsigned long a5, unsigned long cmd);
+extern unsigned long __hvmstub_hypercall(unsigned long a1, unsigned long a2,
+                                        unsigned long a3, unsigned long a4,
+                                        unsigned long cmd);
+/*
+ * Assembler stubs for hyper-calls.
+ */
+
+#define _hypercall0(type, name)                                        \
+({                                                             \
+       long __res;                                             \
+       __res = __hypercall(0, 0, 0, 0, 0,                      \
+                           __HYPERVISOR_##name);               \
+       (type)__res;                                            \
+})
+
+#define _hypercall1(type, name, a1)                            \
+({                                                             \
+       long __res;                                             \
+       __res = __hypercall((unsigned long)a1,                  \
+                           0, 0, 0, 0, __HYPERVISOR_##name);   \
+       (type)__res;                                            \
+})
+
+#define _hypercall2(type, name, a1, a2)                                \
+({                                                             \
+       long __res;                                             \
+       __res = __hypercall((unsigned long)a1,                  \
+                           (unsigned long)a2,                  \
+                           0, 0, 0, __HYPERVISOR_##name);      \
+       (type)__res;                                            \
+})
+
+#define _hypercall3(type, name, a1, a2, a3)                    \
+({                                                             \
+       long __res;                                             \
+       __res = __hypercall((unsigned long)a1,                  \
+                           (unsigned long)a2,                  \
+                           (unsigned long)a3,                  \
+                           0, 0, __HYPERVISOR_##name);         \
+       (type)__res;                                            \
+})
+
+#define _hypercall4(type, name, a1, a2, a3, a4)                        \
+({                                                             \
+       long __res;                                             \
+       __res = __hypercall((unsigned long)a1,                  \
+                           (unsigned long)a2,                  \
+                           (unsigned long)a3,                  \
+                           (unsigned long)a4,                  \
+                           0, __HYPERVISOR_##name);            \
+       (type)__res;                                            \
+})
+
+#define _hypercall5(type, name, a1, a2, a3, a4, a5)            \
+({                                                             \
+       long __res;                                             \
+       __res = __hypercall((unsigned long)a1,                  \
+                           (unsigned long)a2,                  \
+                           (unsigned long)a3,                  \
+                           (unsigned long)a4,                  \
+                           (unsigned long)a5,                  \
+                           __HYPERVISOR_##name);               \
+       (type)__res;                                            \
+})
+
+
+struct xencomm_handle;
+
+/* Inline version.  To be used only on linear space (kernel space).  */
+static inline struct xencomm_handle *
+xencomm_create_inline(void *buffer)
+{
+       unsigned long paddr;
+
+       paddr = (unsigned long)buffer;
+       return (struct xencomm_handle *)(paddr | XENCOMM_INLINE_FLAG);
+}
+
+static inline int
+xencomm_arch_event_channel_op(int cmd, void *arg)
+{
+       int rc;
+       struct xencomm_handle *newArg;
+
+       newArg = xencomm_create_inline(arg);
+       rc = _hypercall2(int, event_channel_op, cmd, newArg);
+       return rc;
+}
+#define HYPERVISOR_event_channel_op xencomm_arch_event_channel_op
+
+static inline int
+xencomm_arch_xen_version(int cmd, struct xencomm_handle *arg)
+{
+       return _hypercall2(int, xen_version, cmd, arg);
+}
+
+static inline int
+xencomm_arch_xen_feature(int cmd, struct xencomm_handle *arg)
+{
+       struct xencomm_handle *newArg;
+
+       newArg = xencomm_create_inline(arg);
+       return _hypercall2(int, xen_version, cmd, newArg);
+}
+
+static inline int
+HYPERVISOR_xen_version(int cmd, void *arg)
+{
+       switch(cmd) {
+               case XENVER_version:
+                       return xencomm_arch_xen_version(cmd, 0);
+               case XENVER_get_features:
+                       return xencomm_arch_xen_feature(cmd, arg);
+               default:
+                       return -1;
+       }
+}
+
+static inline int
+xencomm_arch_console_io(int cmd, int count, char *str)
+{
+       struct xencomm_handle *newStr;
+
+       newStr = xencomm_create_inline(str);
+       return _hypercall3(int, console_io, cmd, count, newStr);
+}
+
+
+#define HYPERVISOR_console_io xencomm_arch_console_io
+
+static inline int
+xencomm_arch_sched_op(int cmd, void *arg)
+{
+       struct xencomm_handle *newArg;
+
+       newArg = xencomm_create_inline(arg);
+       return _hypercall2(int, sched_op, cmd, newArg);
+}
+
+#define HYPERVISOR_sched_op xencomm_arch_sched_op
+
+static inline int
+xencomm_arch_callback_op(int cmd, void *arg)
+{
+       struct xencomm_handle *newArg;
+
+       newArg = xencomm_create_inline(arg);
+       return _hypercall2(int, callback_op, cmd, newArg);
+}
+#define HYPERVISOR_callback_op xencomm_arch_callback_op
+
+static inline int
+HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
+{
+       switch (cmd) {
+       case GNTTABOP_map_grant_ref:
+               break;
+       case GNTTABOP_unmap_grant_ref:
+               break;
+       case GNTTABOP_setup_table:
+       {
+               struct gnttab_setup_table *setup = uop;
+               void *frame;
+
+               if (count != 1)
+                       return -EINVAL;
+               get_xen_guest_handle(frame, setup->frame_list);
+               set_xen_guest_handle(setup->frame_list,
+                                    (void *)xencomm_create_inline (frame));
+               break;
+       }
+       case GNTTABOP_dump_table:
+               break;
+       case GNTTABOP_transfer:
+               break;
+       case GNTTABOP_copy:
+               break;
+       default:
+               printk("%s: unknown mini grant table op %d\n", __func__, cmd);
+               exit ();
+       }
+
+       uop = xencomm_create_inline (uop);
+
+       return _hypercall3(int, grant_table_op, cmd, uop, count);
+}
+
+static inline int
+HYPERVISOR_opt_feature(void *arg)
+{
+       struct xencomm_handle *new_arg;
+
+       new_arg = xencomm_create_inline(arg);
+
+       return _hypercall1(int, opt_feature, new_arg);
+}
+
+static inline int
+HYPERVISOR_yield(
+       void)
+{
+       int rc = HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
+
+       return rc;
+}
+
+static inline int
+HYPERVISOR_block(
+       void)
+{
+       int rc = HYPERVISOR_sched_op(SCHEDOP_block, NULL);
+
+       return rc;
+}
+
+static inline int
+HYPERVISOR_poll(sched_poll_t *p)
+{
+  evtchn_port_t *ports;
+  get_xen_guest_handle(ports, p->ports);
+  set_xen_guest_handle (p->ports,
+                       (evtchn_port_t*)xencomm_create_inline (ports));
+  return HYPERVISOR_sched_op(SCHEDOP_poll, p);
+}
+
+static inline int
+xencomm_arch_hypercall_memory_op(unsigned int cmd, struct xencomm_handle *arg)
+{
+       return _hypercall2(int, memory_op, cmd, arg);
+}
+
+static inline int
+HYPERVISOR_add_to_physmap(struct xen_add_to_physmap *xatp)
+{
+  return xencomm_arch_hypercall_memory_op(XENMEM_add_to_physmap,
+                                         xencomm_create_inline(xatp));
+}
+                               
+#define HVMSTUB_HYPERCALL_SET_CALLBACK 0x801
+     
+static inline int
+HYPERVISOR_HVMSTUB_set_callback(const void *func, void *buf)
+{
+  return __hvmstub_hypercall ((unsigned long)func, (unsigned long)buf,
+                             0, 0, HVMSTUB_HYPERCALL_SET_CALLBACK);
+}
+
+#define HVMSTUB_HYPERCALL_FW_START 0x802
+     
+static inline int
+HYPERVISOR_HVMSTUB_fw_start(unsigned long ip, unsigned long psr)
+{
+  return __hvmstub_hypercall (ip, psr,
+                             0, 0, HVMSTUB_HYPERCALL_FW_START);
+}
+
+static inline int
+HYPERVISOR_hvmop (int cmd, void *arg)
+{
+  return _hypercall2(int, hvm_op, cmd, xencomm_create_inline (arg));
+}
+
+static inline int
+HYPERVISOR_hvm_set_isa_irq_level(domid_t domid, int irq, int level)
+{
+  xen_hvm_set_isa_irq_level_t op;
+  op.domid = domid;
+  op.isa_irq = irq;
+  op.level = level;
+  return HYPERVISOR_hvmop (HVMOP_set_isa_irq_level, &op);
+}
+
+static inline int
+HYPERVISOR_hvm_set_pci_intx_level(domid_t domid,
+                                 int domain, int bus, int device, int intx,
+                                 int level)
+{
+  xen_hvm_set_pci_intx_level_t op;
+  op.domid = domid;
+  op.domain = domain;
+  op.bus = bus;
+  op.device = device;
+  op.intx = intx;
+  op.level = level;
+  return HYPERVISOR_hvmop (HVMOP_set_isa_irq_level, &op);
+}
+#endif /* __HYPERCALL_H__ */
diff -r 092232fa1fbd extras/stubfw/include/hypervisor.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/include/hypervisor.h        Tue Nov 13 01:32:03 2007 +0100
@@ -0,0 +1,28 @@
+/******************************************************************************
+ * hypervisor.h
+ * 
+ * Hypervisor handling.
+ * 
+ *
+ * Copyright (c) 2002, K A Fraser
+ * Copyright (c) 2005, Grzegorz Milos
+ * Updates: Aravindh Puthiyaparambil <aravindh.puthiyaparambil@xxxxxxxxxx>
+ * Updates: Dietmar Hahn <dietmar.hahn@xxxxxxxxxxxxxxxxxxx> for ia64
+ */
+
+#ifndef _HYPERVISOR_H_
+#define _HYPERVISOR_H_
+
+#include <types.h>
+#include <xen/xen.h>
+#if defined(__i386__)
+#include <hypercall-x86_32.h>
+#elif defined(__x86_64__)
+#include <hypercall-x86_64.h>
+#elif defined(__ia64__)
+#include <hypercall-ia64.h>
+#else
+#error "Unsupported architecture"
+#endif
+
+#endif /* __HYPERVISOR_H__ */
diff -r 092232fa1fbd extras/stubfw/include/ia64_cpu.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/include/ia64_cpu.h  Wed Nov 07 00:40:13 2007 +0100
@@ -0,0 +1,776 @@
+/*
+ * Done by Dietmar Hahn <dietmar.hahn@xxxxxxxxxxxxxxxxxxx>
+ * This code is mostly taken from FreeBSD.
+ *
+ *
+ ****************************************************************************
+ * Copyright (c) 2000 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _IA64_CPU_H_
+#define _IA64_CPU_H_
+
+#include "ia64_fpu.h"
+
+/*
+ * Definition of Region Register bits (RR)
+ *
+ * RR bit field positions
+ */
+#define IA64_RR_VE             0
+#define IA64_RR_MBZ0           1
+#define IA64_RR_PS             2
+#define IA64_RR_PS_LEN         6
+#define IA64_RR_RID            8
+#define IA64_RR_RID_LEN                24
+#define IA64_RR_MBZ1           32
+
+#define IA64_RR_IDX_POS                61
+
+#define IA64_RR_VAL(size,rid) (((size) << IA64_RR_PS) | ((rid) << IA64_RR_RID))
+
+/*
+ * Define Protection Key Register (PKR)
+ *
+ * PKR bit field positions
+ */
+#define IA64_PKR_V             0
+#define IA64_PKR_WD            1
+#define IA64_PKR_RD            2
+#define IA64_PKR_XD            3
+#define IA64_PKR_MBZ0          4
+#define IA64_PKR_KEY           8
+#define IA64_PKR_KEY_LEN       24
+#define IA64_PKR_MBZ1          32
+
+#define IA64_PKR_VALID         (1 << IA64_PKR_V)
+
+
+/*
+ * ITIR bit field positions
+ */
+
+#define        IA64_ITIR_MBZ0          0
+#define        IA64_ITIR_PS            2
+#define        IA64_ITIR_PS_LEN        6
+#define        IA64_ITIR_KEY           8
+#define        IA64_ITIR_KEY_LEN       24
+#define        IA64_ITIR_MBZ1          32
+#define        IA64_ITIR_MBZ1_LEN      16
+#define        IA64_ITIR_PPN           48
+#define        IA64_ITIR_PPN_LEN       15
+#define        IA64_ITIR_MBZ2          63
+
+/*
+ * Definition of PSR and IPSR bits.
+ */
+#define IA64_PSR_BE            0x0000000000000002
+#define IA64_PSR_UP            0x0000000000000004
+#define IA64_PSR_AC            0x0000000000000008
+#define IA64_PSR_MFL           0x0000000000000010
+#define IA64_PSR_MFH_BIT       5
+#define IA64_PSR_MFH           (1 << IA64_PSR_MFH_BIT)
+#define IA64_PSR_UMASK         (IA64_PSR_BE | IA64_PSR_UP |    \
+                               IA64_PSR_AC | IA64_PSR_MFL |    \
+                               IA64_PSR_MFH)
+#define IA64_PSR_IC_BIT                13
+#define IA64_PSR_IC            (1<<IA64_PSR_IC_BIT) /*0x0000000000002000*/
+#define IA64_PSR_I_BIT         14
+#define IA64_PSR_I             (1<<IA64_PSR_I_BIT) /*0x0000000000004000*/
+#define IA64_PSR_PK            0x0000000000008000
+#define IA64_PSR_DT            0x0000000000020000
+#define IA64_PSR_DFL           0x0000000000040000
+#define IA64_PSR_DFH           0x0000000000080000
+#define IA64_PSR_SP            0x0000000000100000
+#define IA64_PSR_PP            0x0000000000200000
+#define IA64_PSR_DI            0x0000000000400000
+#define IA64_PSR_SI            0x0000000000800000
+#define IA64_PSR_DB            0x0000000001000000
+#define IA64_PSR_LP            0x0000000002000000
+#define IA64_PSR_TB            0x0000000004000000
+#define IA64_PSR_RT            0x0000000008000000
+#define IA64_PSR_CPL           0x0000000300000000
+#define IA64_PSR_CPL_KERN      0x0000000000000000
+#define IA64_PSR_CPL_1         0x0000000100000000
+#define IA64_PSR_CPL_2         0x0000000200000000
+#define IA64_PSR_CPL_USER      0x0000000300000000
+#define IA64_PSR_IS            0x0000000400000000
+#define IA64_PSR_MC            0x0000000800000000
+#define IA64_PSR_IT            0x0000001000000000
+#define IA64_PSR_ID            0x0000002000000000
+#define IA64_PSR_DA            0x0000004000000000
+#define IA64_PSR_DD            0x0000008000000000
+#define IA64_PSR_SS            0x0000010000000000
+#define IA64_PSR_RI            0x0000060000000000
+#define IA64_PSR_RI_0          0x0000000000000000
+#define IA64_PSR_RI_1          0x0000020000000000
+#define IA64_PSR_RI_2          0x0000040000000000
+#define IA64_PSR_RI_SHIFT      41
+#define IA64_PSR_ED            0x0000080000000000
+#define IA64_PSR_BN            0x0000100000000000
+#define IA64_PSR_IA            0x0000200000000000
+
+
+/* Endianess of mini-os. */
+#if defined(BIG_ENDIAN)
+#define MOS_IA64_PSR_BE        IA64_PSR_BE
+#else
+#define MOS_IA64_PSR_BE        0
+#endif
+
+#define STARTUP_PSR (IA64_PSR_IT | IA64_PSR_PK | \
+                    IA64_PSR_DT | IA64_PSR_RT | MOS_IA64_PSR_BE | \
+                    IA64_PSR_BN | IA64_PSR_CPL_KERN | IA64_PSR_AC)
+
+#define MOS_SYS_PSR (IA64_PSR_IC | IA64_PSR_I | IA64_PSR_IT | \
+                    IA64_PSR_DT | IA64_PSR_RT | MOS_IA64_PSR_BE | \
+                    IA64_PSR_BN | IA64_PSR_CPL_KERN | IA64_PSR_AC)
+
+#define MOS_USR_PSR (IA64_PSR_IC | IA64_PSR_I | IA64_PSR_IT | \
+                    IA64_PSR_DT | IA64_PSR_RT | MOS_IA64_PSR_BE | \
+                    IA64_PSR_BN | IA64_PSR_CPL_USER | IA64_PSR_AC)
+
+/*
+ * Definition of ISR bits.
+ */
+#define IA64_ISR_CODE  0x000000000000ffff
+#define IA64_ISR_VECTOR        0x0000000000ff0000
+#define IA64_ISR_X     0x0000000100000000
+#define IA64_ISR_W     0x0000000200000000
+#define IA64_ISR_R     0x0000000400000000
+#define IA64_ISR_NA    0x0000000800000000
+#define IA64_ISR_SP    0x0000001000000000
+#define IA64_ISR_RS    0x0000002000000000
+#define IA64_ISR_IR    0x0000004000000000
+#define IA64_ISR_NI    0x0000008000000000
+#define IA64_ISR_SO    0x0000010000000000
+#define IA64_ISR_EI    0x0000060000000000
+#define IA64_ISR_EI_0  0x0000000000000000
+#define IA64_ISR_EI_1  0x0000020000000000
+#define IA64_ISR_EI_2  0x0000040000000000
+#define IA64_ISR_ED    0x0000080000000000
+
+/*
+ * DCR bit positions
+ */
+#define IA64_DCR_PP            0
+#define IA64_DCR_BE            1
+#define IA64_DCR_LC            2
+#define IA64_DCR_MBZ0          4
+#define IA64_DCR_MBZ0_V                0xf
+#define IA64_DCR_DM            8
+#define IA64_DCR_DP            9
+#define IA64_DCR_DK            10
+#define IA64_DCR_DX            11
+#define IA64_DCR_DR            12
+#define IA64_DCR_DA            13
+#define IA64_DCR_DD            14
+#define IA64_DCR_DEFER_ALL     0x7f00
+#define IA64_DCR_MBZ1          2
+#define IA64_DCR_MBZ1_V                0xffffffffffffULL
+
+
+       /* Endianess of DCR register. */
+#if defined(BIG_ENDIAN)
+#define MOS_IA64_DCR_BE        (1 << IA64_DCR_BE)
+#else
+#define MOS_IA64_DCR_BE        (0 << IA64_DCR_BE)
+#endif
+
+#define IA64_DCR_DEFAULT (MOS_IA64_DCR_BE)
+
+/*
+ * Vector numbers for various ia64 interrupts.
+ */
+#define IA64_VEC_VHPT                          0
+#define IA64_VEC_ITLB                          1
+#define IA64_VEC_DTLB                          2
+#define IA64_VEC_ALT_ITLB                      3
+#define IA64_VEC_ALT_DTLB                      4
+#define IA64_VEC_NESTED_DTLB                   5
+#define IA64_VEC_IKEY_MISS                     6
+#define IA64_VEC_DKEY_MISS                     7
+#define IA64_VEC_DIRTY_BIT                     8
+#define IA64_VEC_INST_ACCESS                   9
+#define IA64_VEC_DATA_ACCESS                   10
+#define IA64_VEC_BREAK                         11
+#define IA64_VEC_EXT_INTR                      12
+#define IA64_VEC_PAGE_NOT_PRESENT              20
+#define IA64_VEC_KEY_PERMISSION                        21
+#define IA64_VEC_INST_ACCESS_RIGHTS            22
+#define IA64_VEC_DATA_ACCESS_RIGHTS            23
+#define IA64_VEC_GENERAL_EXCEPTION             24
+#define IA64_VEC_DISABLED_FP                   25
+#define IA64_VEC_NAT_CONSUMPTION               26
+#define IA64_VEC_SPECULATION                   27
+#define IA64_VEC_DEBUG                         29
+#define IA64_VEC_UNALIGNED_REFERENCE           30
+#define IA64_VEC_UNSUPP_DATA_REFERENCE         31
+#define IA64_VEC_FLOATING_POINT_FAULT          32
+#define IA64_VEC_FLOATING_POINT_TRAP           33
+#define IA64_VEC_LOWER_PRIVILEGE_TRANSFER      34
+#define IA64_VEC_TAKEN_BRANCH_TRAP             35
+#define IA64_VEC_SINGLE_STEP_TRAP              36
+#define IA64_VEC_IA32_EXCEPTION                        45
+#define IA64_VEC_IA32_INTERCEPT                        46
+#define IA64_VEC_IA32_INTERRUPT                        47
+
+/*
+ * Define hardware RSE Configuration Register
+ *
+ * RS Configuration (RSC) bit field positions
+ */
+
+#define IA64_RSC_MODE       0
+#define IA64_RSC_PL         2
+#define IA64_RSC_BE         4
+#define IA64_RSC_MBZ0       5
+#define IA64_RSC_MBZ0_V     0x3ff
+#define IA64_RSC_LOADRS     16
+#define IA64_RSC_LOADRS_LEN 14
+#define IA64_RSC_MBZ1       30
+#define IA64_RSC_MBZ1_V     0x3ffffffffULL
+
+/*
+ * RSC modes
+ */
+#define IA64_RSC_MODE_LY (0x0)                 /* Lazy */
+#define IA64_RSC_MODE_SI (0x1)                 /* Store intensive */
+#define IA64_RSC_MODE_LI (0x2)                 /* Load intensive */
+#define IA64_RSC_MODE_EA (0x3)                 /* Eager */
+
+/* RSE endian mode. */
+#if defined(BIG_ENDIAN)
+#define MOS_IA64_RSC_BE        1               /* Big endian rse. */
+#else
+#define MOS_IA64_RSC_BE        0               /* Little endian rse. */
+#endif
+
+#define IA64_RSE_EAGER ((IA64_RSC_MODE_EA<<IA64_RSC_MODE) |    \
+                          (MOS_IA64_RSC_BE << IA64_RSC_BE)     )
+
+#define IA64_RSE_LAZY ((IA64_RSC_MODE_LY<<IA64_RSC_MODE) |     \
+                          (MOS_IA64_RSC_BE << IA64_RSC_BE)     )
+
+
+
+#ifndef __ASSEMBLY__
+
+/* ia64 function descriptor and global pointer */
+struct ia64_fdesc
+{
+       uint64_t        func;
+       uint64_t        gp;
+};
+typedef struct ia64_fdesc ia64_fdesc_t;
+
+#define FDESC_FUNC(fn)  (((struct ia64_fdesc *) fn)->func)
+#define FDESC_GP(fn)    (((struct ia64_fdesc *) fn)->gp)
+
+
+/*
+ * Various special ia64 instructions.
+ */
+
+/*
+ * Memory Fence.
+ */
+static __inline void
+ia64_mf(void)
+{
+       __asm __volatile("mf" ::: "memory");
+}
+
+static __inline void
+ia64_mf_a(void)
+{
+       __asm __volatile("mf.a");
+}
+
+/*
+ * Flush Cache.
+ */
+static __inline void
+ia64_fc(uint64_t va)
+{
+       __asm __volatile("fc %0" :: "r"(va));
+}
+
+/*
+ * Sync instruction stream.
+ */
+static __inline void
+ia64_sync_i(void)
+{
+       __asm __volatile("sync.i");
+}
+
+/*
+ * Calculate address in VHPT for va.
+ */
+static __inline uint64_t
+ia64_thash(uint64_t va)
+{
+       uint64_t result;
+       __asm __volatile("thash %0=%1" : "=r" (result) : "r" (va));
+       return result;
+}
+
+/*
+ * Calculate VHPT tag for va.
+ */
+static __inline uint64_t
+ia64_ttag(uint64_t va)
+{
+       uint64_t result;
+       __asm __volatile("ttag %0=%1" : "=r" (result) : "r" (va));
+       return result;
+}
+
+/*
+ * Convert virtual address to physical.
+ */
+static __inline uint64_t
+ia64_tpa(uint64_t va)
+{
+       uint64_t result;
+       __asm __volatile("tpa %0=%1" : "=r" (result) : "r" (va));
+       return result;
+}
+
+/*
+ * Generate a ptc.e instruction.
+ */
+static __inline void
+ia64_ptc_e(uint64_t v)
+{
+       __asm __volatile("ptc.e %0;; srlz.d;;" :: "r"(v));
+}
+
+/*
+ * Generate a ptc.g instruction.
+ */
+static __inline void
+ia64_ptc_g(uint64_t va, uint64_t size)
+{
+       __asm __volatile("ptc.g %0,%1;; srlz.d;;" :: "r"(va), "r"(size<<2));
+}
+
+/*
+ * Generate a ptc.ga instruction.
+ */
+static __inline void
+ia64_ptc_ga(uint64_t va, uint64_t size)
+{
+       __asm __volatile("ptc.ga %0,%1;; srlz.d;;" :: "r"(va), "r"(size<<2));
+}
+
+/*
+ * Generate a ptc.l instruction.
+ */
+static __inline void
+ia64_ptc_l(uint64_t va, uint64_t size)
+{
+       __asm __volatile("ptc.l %0,%1;; srlz.d;;" :: "r"(va), "r"(size<<2));
+}
+
+/*
+ * Read the value of psr.
+ */
+static __inline uint64_t
+ia64_get_psr(void)
+{
+       uint64_t result;
+       __asm __volatile("mov %0=psr;;" : "=r" (result));
+       return result;
+}
+
+static __inline void
+ia64_set_psr(uint64_t v)
+{
+       __asm __volatile("mov psr.l=%0" :: "r" (v));
+}
+
+static __inline void
+ia64_srlz_d(void)
+{
+       __asm __volatile("srlz.d;;");
+}
+
+static __inline void
+disable_intr(void)
+{
+       __asm __volatile ("rsm psr.ic|psr.i");
+}
+
+static __inline void
+enable_intr(void)
+{
+       __asm __volatile ("ssm psr.ic|psr.i");
+}
+
+/*
+ * Define accessors for application registers.
+ */
+
+#define IA64_AR(name)                                                  \
+                                                                       \
+static __inline uint64_t                                               \
+ia64_get_##name(void)                                                  \
+{                                                                      \
+       uint64_t result;                                                \
+       __asm __volatile(";;mov %0=ar." #name ";;" : "=r" (result));    \
+       return result;                                                  \
+}                                                                      \
+                                                                       \
+static __inline void                                                   \
+ia64_set_##name(uint64_t v)                                            \
+{                                                                      \
+       __asm __volatile("mov ar." #name "=%0" :: "r" (v));             \
+}
+
+IA64_AR(k0)
+IA64_AR(k1)
+IA64_AR(k2)
+IA64_AR(k3)
+IA64_AR(k4)
+IA64_AR(k5)
+IA64_AR(k6)
+IA64_AR(k7)
+
+IA64_AR(rsc)
+IA64_AR(bsp)
+IA64_AR(bspstore)
+IA64_AR(rnat)
+
+IA64_AR(fcr)
+
+IA64_AR(eflag)
+IA64_AR(csd)
+IA64_AR(ssd)
+IA64_AR(cflg)
+IA64_AR(fsr)
+IA64_AR(fir)
+IA64_AR(fdr)
+
+IA64_AR(ccv)
+
+IA64_AR(unat)
+
+IA64_AR(fpsr)
+
+IA64_AR(itc)
+
+IA64_AR(pfs)
+IA64_AR(lc)
+IA64_AR(ec)
+
+/*
+ * Define accessors for control registers.
+ */
+
+#define IA64_CR(name)                                          \
+                                                               \
+static __inline uint64_t                                       \
+ia64_get_##name(void)                                          \
+{                                                              \
+       uint64_t result;                                        \
+       __asm __volatile("mov %0=cr." #name : "=r" (result));   \
+       return result;                                          \
+}                                                              \
+                                                               \
+static __inline void                                           \
+ia64_set_##name(uint64_t v)                                    \
+{                                                              \
+       __asm __volatile("mov cr." #name "=%0" :: "r" (v));     \
+}
+
+IA64_CR(dcr)
+IA64_CR(itm)
+IA64_CR(iva)
+
+IA64_CR(pta)
+
+IA64_CR(ipsr)
+IA64_CR(isr)
+
+IA64_CR(iip)
+IA64_CR(ifa)
+IA64_CR(itir)
+IA64_CR(iipa)
+IA64_CR(ifs)
+IA64_CR(iim)
+IA64_CR(iha)
+
+IA64_CR(lid)
+IA64_CR(ivr)
+IA64_CR(tpr)
+IA64_CR(eoi)
+IA64_CR(irr0)
+IA64_CR(irr1)
+IA64_CR(irr2)
+IA64_CR(irr3)
+IA64_CR(itv)
+IA64_CR(pmv)
+IA64_CR(cmcv)
+
+IA64_CR(lrr0)
+IA64_CR(lrr1)
+
+#define IA64_GR(name)                                          \
+                                                               \
+static __inline uint64_t                                       \
+ia64_get_##name(void)                                          \
+{                                                              \
+       uint64_t result;                                        \
+       __asm __volatile("mov %0=" #name : "=r" (result));      \
+       return result;                                          \
+}                                                              \
+                                                               \
+static __inline void                                           \
+ia64_set_##name(uint64_t v)                                    \
+{                                                              \
+       __asm __volatile("mov " #name "=%0" :: "r" (v));        \
+}
+
+IA64_GR(sp)
+IA64_GR(b0)
+IA64_GR(r13)   // tp
+
+
+/*
+ * Write a region register.
+ */
+static __inline void
+ia64_set_rr(uint64_t rrbase, uint64_t v)
+{
+       __asm __volatile("mov rr[%0]=%1;; srlz.d;;"
+                        :: "r"(rrbase), "r"(v) : "memory");
+}
+
+/*
+ * Read a region register.
+ */
+static __inline uint64_t
+ia64_get_rr(uint64_t rrbase)
+{
+       uint64_t v;
+       __asm __volatile("mov %1=rr[%0];;"
+                        : "=r" (v) : "r"(rrbase) : "memory");
+       return v;
+}
+
+
+/*
+ * Read a CPUID register.
+ */
+static __inline uint64_t
+ia64_get_cpuid(int i)
+{
+       uint64_t result;
+       __asm __volatile("mov %0=cpuid[%1]"
+                        : "=r" (result) : "r"(i));
+       return result;
+}
+
+
+struct trap_frame
+{
+       uint64_t        rsc;
+       uint64_t        ndirty;         /* number of dirty regs */
+       uint64_t        ssd;
+       uint64_t        iip;            /* interrupted ip */
+       uint64_t        ipsr;           /* interrupted psr */
+       uint64_t        ifs;            /* interruption func status register */
+
+       uint16_t        trap_num;       /* Trap num, index in trap_vec */
+       uint64_t        cfm;            /* current frame marker */
+       uint64_t        pfs;            /* previous function state ar64 */
+       uint64_t        bsp;            /* backing store pointer ar17 */
+       uint64_t        rnat;           /* rse nat collection ar19 */
+       uint64_t        csd;            /* comp and store data reg ar25 */
+       uint64_t        ccv;            /* comp and xchange val reg ar32 */
+       uint64_t        unat;           /* */
+       uint64_t        fpsr;           /* floating point state reg ar40 */
+       uint64_t        pr;             /* predicate regs 0-63 */
+
+       uint64_t        gp;             /* the gp pointer */
+       uint64_t        sp;             /* stack pointer */
+       uint64_t        tp;             /* thread pointer */
+
+       uint64_t        r2;             /* global reg 2 */
+       uint64_t        r3;
+       uint64_t        r8;
+       uint64_t        r9;
+       uint64_t        r10;
+       uint64_t        r11;
+       uint64_t        r14;
+       uint64_t        r15;
+       uint64_t        r16;
+       uint64_t        r17;
+       uint64_t        r18;
+       uint64_t        r19;
+       uint64_t        r20;
+       uint64_t        r21;
+       uint64_t        r22;
+       uint64_t        r23;
+       uint64_t        r24;
+       uint64_t        r25;
+       uint64_t        r26;
+       uint64_t        r27;
+       uint64_t        r28;
+       uint64_t        r29;
+       uint64_t        r30;
+       uint64_t        r31;
+
+       uint64_t        b0;
+       uint64_t        b6;
+       uint64_t        b7;
+
+       ia64_fpreg_t    f6;           /* floating point register 6 */
+       ia64_fpreg_t    f7;
+       ia64_fpreg_t    f8;
+       ia64_fpreg_t    f9;
+       ia64_fpreg_t    f10;
+       ia64_fpreg_t    f11;
+
+       uint64_t        ifa;            /* interruption faulting address */
+       uint64_t        isr;            /* interruption status register */
+       uint64_t        iim;            /* interruption immediate register */
+};
+
+typedef struct trap_frame trap_frame_t;
+
+
+#endif  /* __ASSEMBLY__ */
+
+/* Page access parameters. */
+#define PTE_P_SHIFT    0
+#define PTE_P          1
+
+#define PTE_MA_SHIFT   2
+#define PTE_MA_WB      0
+
+#define PTE_A_SHIFT    5
+#define PTE_A          1
+#define PTE_D_SHIFT    6
+#define PTE_D          1
+
+#define PTE_AR_SHIFT   9
+#define PTE_AR_R       0
+#define PTE_AR_RX      1
+#define PTE_AR_RW      2
+#define PTE_AR_RWX     3
+#define PTE_AR_R_RW    4
+#define PTE_AR_RX_RWX  5
+#define PTE_AR_RWX_RW  6
+/* privilege level */
+#define PTE_PL_SHIFT   7
+#define PTE_PL_KERN    0       /* used for kernel */
+/* page size */
+#define PTE_PS_4K      12
+#define PTE_PS_8K      13
+#define PTE_PS_16K     14
+#define PTE_PS_64K     16
+#define PTE_PS_256K    18
+#define PTE_PS_1M      20
+#define PTE_PS_4M      22
+#define PTE_PS_16M     24
+#define PTE_PS_64M     26
+#define PTE_PS_256M    28
+
+
+       /* Some offsets for ia64_pte_t. */
+#define PTE_OFF_P      0
+#define PTE_OFF_MA     3
+#define PTE_OFF_A      5
+#define PTE_OFF_D      6
+#define PTE_OFF_PL     7
+#define PTE_OFF_AR     9
+#define PTE_OFF_PPN    12
+#define PTE_OFF_ED     52
+
+#if !defined(_ASM) && !defined(__ASSEMBLY__)
+/*
+ * A short-format VHPT entry. Also matches the TLB insertion format.
+ */
+typedef struct
+{
+#if defined(BIG_ENDIAN)
+       uint64_t pte_ig :11;    /* bits 53..63 */
+       uint64_t pte_ed :1;     /* bits 52..52 */
+       uint64_t pte_rv2:2;     /* bits 50..51 */
+       uint64_t pte_ppn:38;    /* bits 12..49 */
+       uint64_t pte_ar :3;     /* bits 9..11 */
+       uint64_t pte_pl :2;     /* bits 7..8 */
+       uint64_t pte_d  :1;     /* bits 6..6 */
+       uint64_t pte_a  :1;     /* bits 5..5 */
+       uint64_t pte_ma :3;     /* bits 2..4 */
+       uint64_t pte_rv1:1;     /* bits 1..1 */
+       uint64_t pte_p  :1;     /* bits 0..0 */
+#else
+       uint64_t pte_p  :1;     /* bits 0..0 */
+       uint64_t pte_rv1:1;     /* bits 1..1 */
+       uint64_t pte_ma :3;     /* bits 2..4 */
+       uint64_t pte_a  :1;     /* bits 5..5 */
+       uint64_t pte_d  :1;     /* bits 6..6 */
+       uint64_t pte_pl :2;     /* bits 7..8 */
+       uint64_t pte_ar :3;     /* bits 9..11 */
+       uint64_t pte_ppn:38;    /* bits 12..49 */
+       uint64_t pte_rv2:2;     /* bits 50..51 */
+       uint64_t pte_ed :1;     /* bits 52..52 */
+       uint64_t pte_ig :11;    /* bits 53..63 */
+#endif
+} ia64_pte_t;
+
+
+/*
+ * A long-format VHPT entry.
+ */
+typedef struct
+{
+       uint64_t pte_p          :1;     /* bits 0..0 */
+       uint64_t pte_rv1        :1;     /* bits 1..1 */
+       uint64_t pte_ma         :3;     /* bits 2..4 */
+       uint64_t pte_a          :1;     /* bits 5..5 */
+       uint64_t pte_d          :1;     /* bits 6..6 */
+       uint64_t pte_pl         :2;     /* bits 7..8 */
+       uint64_t pte_ar         :3;     /* bits 9..11 */
+       uint64_t pte_ppn        :38;    /* bits 12..49 */
+       uint64_t pte_rv2        :2;     /* bits 50..51 */
+       uint64_t pte_ed         :1;     /* bits 52..52 */
+       uint64_t pte_ig         :11;    /* bits 53..63 */
+       uint64_t pte_rv3        :2;     /* bits 0..1 */
+       uint64_t pte_ps         :6;     /* bits 2..7 */
+       uint64_t pte_key        :24;    /* bits 8..31 */
+       uint64_t pte_rv4        :32;    /* bits 32..63 */
+       uint64_t pte_tag;               /* includes ti */
+       uint64_t pte_chain;             /* pa of collision chain */
+} ia64_lpte_t;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _IA64_CPU_H_ */
diff -r 092232fa1fbd extras/stubfw/include/ia64_fpu.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/include/ia64_fpu.h  Wed Nov 07 00:40:13 2007 +0100
@@ -0,0 +1,99 @@
+/*
+ * Done by Dietmar Hahn <dietmar.hahn@xxxxxxxxxxxxxxxxxxx>
+ * This code is mostly taken from FreeBSD.
+ *
+ ****************************************************************************
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _IA64_FPU_H_
+#define _IA64_FPU_H_
+
+#include "os.h"
+
+/*
+ * Floating point status register bits.
+ */
+#define IA64_FPSR_TRAP_VD      UL_CONST(0x0000000000000001)
+#define IA64_FPSR_TRAP_DD      UL_CONST(0x0000000000000002)
+#define IA64_FPSR_TRAP_ZD      UL_CONST(0x0000000000000004)
+#define IA64_FPSR_TRAP_OD      UL_CONST(0x0000000000000008)
+#define IA64_FPSR_TRAP_UD      UL_CONST(0x0000000000000010)
+#define IA64_FPSR_TRAP_ID      UL_CONST(0x0000000000000020)
+#define IA64_FPSR_SF(i,v)      ((v) << ((i)*13+6))
+
+#define IA64_SF_FTZ            UL_CONST(0x0001)
+#define IA64_SF_WRE            UL_CONST(0x0002)
+#define IA64_SF_PC             UL_CONST(0x000c)
+#define IA64_SF_PC_0           UL_CONST(0x0000)
+#define IA64_SF_PC_1           UL_CONST(0x0004)
+#define IA64_SF_PC_2           UL_CONST(0x0008)
+#define IA64_SF_PC_3           UL_CONST(0x000c)
+#define IA64_SF_RC             UL_CONST(0x0030)
+#define IA64_SF_RC_NEAREST     UL_CONST(0x0000)
+#define IA64_SF_RC_NEGINF      UL_CONST(0x0010)
+#define IA64_SF_RC_POSINF      UL_CONST(0x0020)
+#define IA64_SF_RC_TRUNC       UL_CONST(0x0030)
+#define IA64_SF_TD             UL_CONST(0x0040)
+#define IA64_SF_V              UL_CONST(0x0080)
+#define IA64_SF_D              UL_CONST(0x0100)
+#define IA64_SF_Z              UL_CONST(0x0200)
+#define IA64_SF_O              UL_CONST(0x0400)
+#define IA64_SF_U              UL_CONST(0x0800)
+#define IA64_SF_I              UL_CONST(0x1000)
+
+#define IA64_SF_DEFAULT        (IA64_SF_PC_3 | IA64_SF_RC_NEAREST)
+
+#define IA64_FPSR_DEFAULT      (IA64_FPSR_TRAP_VD                      \
+                                | IA64_FPSR_TRAP_DD                    \
+                                | IA64_FPSR_TRAP_ZD                    \
+                                | IA64_FPSR_TRAP_OD                    \
+                                | IA64_FPSR_TRAP_UD                    \
+                                | IA64_FPSR_TRAP_ID                    \
+                                | IA64_FPSR_SF(0, IA64_SF_DEFAULT)     \
+                                | IA64_FPSR_SF(1, (IA64_SF_DEFAULT     \
+                                                   | IA64_SF_TD        \
+                                                   | IA64_SF_WRE))     \
+                                | IA64_FPSR_SF(2, (IA64_SF_DEFAULT     \
+                                                   | IA64_SF_TD))      \
+                                | IA64_FPSR_SF(3, (IA64_SF_DEFAULT     \
+                                                   | IA64_SF_TD)))
+
+
+#ifndef __ASSEMBLY__
+
+       /* This is from sys/cdefs.h in FreeBSD */
+#define __aligned(x)    __attribute__((__aligned__(x)))
+
+       /* A single Floating Point register. */
+struct ia64_fpreg
+{
+       uint8_t fpr_bits[16];
+} __aligned(16);
+
+typedef struct ia64_fpreg ia64_fpreg_t;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _IA64_FPU_H_ */
diff -r 092232fa1fbd extras/stubfw/include/lib.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/include/lib.h       Wed Nov 14 03:17:18 2007 +0100
@@ -0,0 +1,121 @@
+/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ ****************************************************************************
+ *
+ *        File: lib.h
+ *      Author: Rolf Neugebauer (neugebar@xxxxxxxxxxxxx)
+ *     Changes: 
+ *              
+ *        Date: Aug 2003
+ * 
+ * Environment: Xen Minimal OS
+ * Description: Random useful library functions, contains some freebsd stuff
+ *
+ ****************************************************************************
+ * $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
+ ****************************************************************************
+ *
+ *-
+ * Copyright (c) 1991, 1993
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *      @(#)stdarg.h    8.1 (Berkeley) 6/10/93
+ * $FreeBSD: src/sys/i386/include/stdarg.h,v 1.10 1999/08/28 00:44:26 peter 
Exp $
+ */
+
+#ifndef _LIB_H_
+#define _LIB_H_
+
+#include <stdarg.h>
+#include <stddef.h>
+
+/* printing */
+#define _p(_x) ((void *)(unsigned long)(_x))
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
+int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
+int snprintf(char * buf, size_t size, const char *fmt, ...);
+int scnprintf(char * buf, size_t size, const char *fmt, ...);
+int vsprintf(char *buf, const char *fmt, va_list args);
+int sprintf(char * buf, const char *fmt, ...);
+int vsscanf(const char * buf, const char * fmt, va_list args);
+int sscanf(const char * buf, const char * fmt, ...);
+
+long simple_strtol(const char *cp,char **endp,unsigned int base);
+unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base);
+long long simple_strtoll(const char *cp,char **endp,unsigned int base);
+unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int 
base);
+
+
+void printk(const char *fmt, ...);
+void vprintf(const char *fmt, va_list args);
+void exit (void) __attribute__ ((noreturn));
+
+/* string and memory manipulation */
+int    memcmp(const void *cs, const void *ct, size_t count);
+void  *memcpy(void *dest, const void *src, size_t count);
+int    strncmp(const char *cs, const char *ct, size_t count);
+int    strcmp(const char *cs, const char *ct);
+char  *strcpy(char *dest, const char *src);
+char  *strncpy(char *dest, const char *src, size_t count);
+void  *memset(void *s,int c, size_t count);
+size_t strnlen(const char *s, size_t count);
+size_t strlen(const char *s);
+char  *strchr(const char *s, int c);
+char  *strstr(const char *s1, const char *s2);
+char * strcat(char * dest, const char * src);
+char  *strdup(const char *s);
+
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+struct kvec {
+    void *iov_base;
+    size_t iov_len;
+};
+
+#define ASSERT(x)                                              \
+do {                                                           \
+       if (!(x)) {                                                \
+               printk("ASSERTION FAILED: %s at %s:%d.\n",             \
+                          # x ,                                           \
+                          __FILE__,                                       \
+                          __LINE__);                                      \
+        BUG();                                                 \
+       }                                                          \
+} while(0)
+
+/* Consistency check as much as possible. */
+void sanity_check(void);
+
+void pstrcpy(char *buf, int buf_size, const char *str);
+
+#endif /* _LIB_H_ */
diff -r 092232fa1fbd extras/stubfw/include/os.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/include/os.h        Fri Nov 16 03:46:13 2007 +0100
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2007 - Dietmar Hahn <dietmar.hahn@xxxxxxxxxxxxxxxxxxx>
+ *
+ ****************************************************************************
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+#if !defined(__OS_H__)
+#define __OS_H__
+
+#if !defined(__ASSEMBLY__)
+
+#include <stddef.h>
+#include "types.h"
+#include "xen/xen.h"
+#include "hypervisor.h"
+#include "ia64_cpu.h"
+#include "atomic.h"
+
+
+typedef uint64_t paddr_t;              /* Physical address. */
+typedef uint64_t caddr_t;              /* rr7/kernel memory address. */
+
+
+void do_exit(void);
+void arch_init(start_info_t *si);      /* in common.c */
+void arch_print_info(void);            /* in common.c */
+
+#define smp_processor_id() 0
+
+static inline uint64_t
+xchg8(uint64_t* ptr, uint64_t x)                                               
\
+{
+        uint64_t oldVal;
+        asm volatile ("xchg8 %0=[%1],%2" : "=r" (oldVal)
+                      : "r" (ptr), "r" (x) : "memory");
+        return oldVal;
+}
+#define xchg xchg8
+
+// Counts the number of 1-bits in x.
+#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+# define get_popcnt(x)         __builtin_popcountl(x)
+#else
+# define get_popcnt(x)                                 \
+  ({                                                   \
+       uint64_t num;                                   \
+       asm ("popcnt %0=%1" : "=r" (num) : "r" (x));    \
+       num;                                            \
+  })
+#endif
+
+/**
+ * __ffs - find first bit in word.
+ * @x: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static inline unsigned long
+__ffs (unsigned long x)
+{
+       unsigned long result;
+
+       result = get_popcnt((x-1) & ~x);
+       return result;
+}
+
+
+static inline void
+synch_clear_bit(int num, volatile void *addr)
+{
+       clear_bit(num, addr);
+}
+
+static inline void
+synch_set_bit(int num, volatile void *addr)
+{
+       set_bit(num, addr);
+}
+
+static inline int
+synch_test_bit(int nr, const volatile void *addr)
+{
+       return test_bit(nr, addr);
+}
+
+static inline int
+synch_test_and_set_bit(int num, volatile void * addr)
+{
+       return test_and_set_bit(num, addr);
+}
+
+
+#define synch_cmpxchg(ptr, old, new) \
+((__typeof__(*(ptr)))__synch_cmpxchg((ptr),\
+                                     (unsigned long)(old), \
+                                     (unsigned long)(new), \
+                                     sizeof(*(ptr))))
+
+static inline unsigned long
+__synch_cmpxchg(volatile void *ptr, uint64_t old, uint64_t new, int size)
+{
+       switch (size)
+       {
+               case 1:
+                       return ia64_cmpxchg_acq_8(ptr, old, new);
+               case 2:
+                       return ia64_cmpxchg_acq_16(ptr, old, new);
+               case 4:
+                       return ia64_cmpxchg_acq_32(ptr, old, new);
+               case 8:
+                       return ia64_cmpxchg_acq_64(ptr, old, new);
+       }
+       return ia64_cmpxchg_acq_64(ptr, old, new);
+}
+
+#if 0
+/*
+ * Force a proper event-channel callback from Xen after clearing the
+ * callback mask. We do this in a very simple manner, by making a call
+ * down into Xen. The pending flag will be checked by Xen on return.
+ */
+static inline void
+force_evtchn_callback(void)
+{
+       (void)HYPERVISOR_xen_version(0, NULL);
+}
+#endif
+
+extern shared_info_t *HYPERVISOR_shared_info;
+
+static inline int
+HYPERVISOR_shutdown(unsigned int reason)
+{
+       struct sched_shutdown sched_shutdown = {
+               .reason = reason
+       };
+
+       int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
+
+       return rc;
+}
+
+
+/*
+ * This code is from the originally os.h and should be put in a
+ * common header file!
+ */
+
+/* 
+ * The use of 'barrier' in the following reflects their use as local-lock
+ * operations. Reentrancy must be prevented (e.g., __cli()) /before/ following
+ * critical operations are executed. All critical operations must complete
+ * /before/ reentrancy is permitted (e.g., __sti()). Alpha architecture also
+ * includes these barriers, for example.
+ */
+
+#define __cli()                                                                
\
+do {                                                                   \
+       vcpu_info_t *_vcpu;                                             \
+       _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \
+       _vcpu->evtchn_upcall_mask = SWAP(1);                            \
+       barrier();                                                      \
+} while (0)
+
+#define __sti()                                                                
\
+do {                                                                   \
+       vcpu_info_t *_vcpu;                                             \
+       barrier();                                                      \
+       _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \
+       _vcpu->evtchn_upcall_mask = 0;                                  \
+       barrier(); /* unmask then check (avoid races) */                \
+       if (unlikely(SWAP(_vcpu->evtchn_upcall_pending)))               \
+               force_evtchn_callback();                                \
+} while (0)
+
+#define __save_flags(x)                                                        
\
+do {                                                                   \
+       vcpu_info_t *_vcpu;                                             \
+       _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \
+       (x) = SWAP(_vcpu->evtchn_upcall_mask);                          \
+} while (0)
+
+#define __restore_flags(x)                                             \
+do {                                                                   \
+       vcpu_info_t *_vcpu;                                             \
+       barrier();                                                      \
+       _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \
+       if ((_vcpu->evtchn_upcall_mask = (x)) == 0) {                   \
+               barrier(); /* unmask then check (avoid races) */        \
+               if ( unlikely(SWAP(_vcpu->evtchn_upcall_pending)) )     \
+                       force_evtchn_callback();                        \
+       }\
+} while (0)
+
+#define safe_halt()            ((void)0)
+
+#define __save_and_cli(x)                                              \
+do {                                                                   \
+       vcpu_info_t *_vcpu;                                             \
+       _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \
+       (x) = SWAP(_vcpu->evtchn_upcall_mask);                          \
+       _vcpu->evtchn_upcall_mask = SWAP(1);                            \
+       barrier();                                                      \
+} while (0)
+
+#define local_irq_save(x)      __save_and_cli(x)
+#define local_irq_restore(x)   __restore_flags(x)
+#define local_save_flags(x)    __save_flags(x)
+#define local_irq_disable()    __cli()
+#define local_irq_enable()     __sti()
+
+#define irqs_disabled()                        \
+       
SWAP(HYPERVISOR_shared_info->vcpu_info[smp_processor_id()].evtchn_upcall_mask)
+
+/* This is a barrier for the compiler only, NOT the processor! */
+#define barrier() __asm__ __volatile__("": : :"memory")
+
+#define mb()   ia64_mf()
+#define rmb()  mb()
+#define wmb()  mb()
+
+
+#define BUG()  \
+       { printk("mini-os BUG at %s:%d!\n", __FILE__, __LINE__); exit(); }
+
+#define PRINT_BV(_fmt, _params...)             \
+       if (bootverbose)                        \
+               printk(_fmt , ## _params)
+
+#endif /* !defined(__ASSEMBLY__) */
+
+#if defined(__ASSEMBLY__)
+
+#define UL_CONST(x)    x
+#define UL_TYPE(x)     x
+
+#else /* defined(__ASSEMBLY__) */
+
+#define UL_CONST(x)    x##UL
+#define UL_TYPE(x)     ((uint64_t)x)
+
+#endif /* defined(__ASSEMBLY__) */
+
+#endif /* !defined(__OS_H__) */
diff -r 092232fa1fbd extras/stubfw/include/types.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/include/types.h     Wed Nov 07 00:40:13 2007 +0100
@@ -0,0 +1,72 @@
+/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ ****************************************************************************
+ *
+ *        File: types.h
+ *      Author: Rolf Neugebauer (neugebar@xxxxxxxxxxxxx)
+ *     Changes: 
+ *              
+ *        Date: May 2003
+ * 
+ * Environment: Xen Minimal OS
+ * Description: a random collection of type definitions
+ *
+ ****************************************************************************
+ * $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
+ ****************************************************************************
+ */
+
+#ifndef _TYPES_H_
+#define _TYPES_H_
+
+typedef signed char         s8;
+typedef unsigned char       u8;
+typedef signed short        s16;
+typedef unsigned short      u16;
+typedef signed int          s32;
+typedef unsigned int        u32;
+#ifdef __i386__
+typedef signed long long    s64;
+typedef unsigned long long  u64;
+#elif defined(__x86_64__) || defined(__ia64__)
+typedef signed long         s64;
+typedef unsigned long       u64;
+#endif
+
+/* FreeBSD compat types */
+typedef unsigned char       u_char;
+typedef unsigned int        u_int;
+typedef unsigned long       u_long;
+#ifdef __i386__
+typedef long long           quad_t;
+typedef unsigned long long  u_quad_t;
+typedef unsigned int        uintptr_t;
+
+#if !defined(CONFIG_X86_PAE)
+typedef struct { unsigned long pte_low; } pte_t;
+#else
+typedef struct { unsigned long pte_low, pte_high; } pte_t;
+#endif /* CONFIG_X86_PAE */
+
+#elif defined(__x86_64__) || defined(__ia64__)
+typedef long                quad_t;
+typedef unsigned long       u_quad_t;
+typedef unsigned long       uintptr_t;
+
+typedef struct { unsigned long pte; } pte_t;
+#endif /* __i386__ || __x86_64__ */
+
+typedef  u8 uint8_t;
+typedef  s8 int8_t;
+typedef u16 uint16_t;
+typedef s16 int16_t;
+typedef u32 uint32_t;
+typedef s32 int32_t;
+typedef u64 uint64_t;
+typedef s64 int64_t;
+
+
+#define INT_MAX         ((int)(~0U>>1))
+#define UINT_MAX            (~0U)
+#endif /* _TYPES_H_ */
diff -r 092232fa1fbd extras/stubfw/include/xenbus.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/include/xenbus.h    Wed Nov 14 03:26:31 2007 +0100
@@ -0,0 +1,62 @@
+#ifndef XENBUS_H__
+#define XENBUS_H__
+
+typedef unsigned long xenbus_transaction_t;
+#define XBT_NIL ((xenbus_transaction_t)0)
+struct xenbus_req;
+
+/* Initialize the XenBus system. */
+void init_xenbus(void *interface, int evtchn);
+
+struct xenbus_req *xenbus_allocate_req (char *buf, int size);
+
+/* Read the value associated with a path.  Returns a malloc'd error
+   string on failure and sets *value to NULL.  On success, *value is
+   set to a malloc'd copy of the value. */
+const char *xenbus_read(struct xenbus_req *r, xenbus_transaction_t xbt, const 
char *path, char **value);
+
+const char *xenbus_watch_path(struct xenbus_req *r, xenbus_transaction_t xbt, 
const char *path);
+const char*xenbus_wait_for_value(struct xenbus_req *r,
+                                const char* path, const char* value);
+
+/* Associates a value with a path.  Returns a malloc'd error string on
+   failure. */
+const char *xenbus_write(struct xenbus_req *r, xenbus_transaction_t xbt, const 
char *path, const char *value);
+
+/* Removes the value associated with a path.  Returns a malloc'd error
+   string on failure. */
+const char *xenbus_rm(struct xenbus_req *r, xenbus_transaction_t xbt, const 
char *path);
+
+/* List the contents of a directory.  Returns a malloc'd error string
+   on failure and sets *contents to NULL.  On success, *contents is
+   set to a malloc'd array of pointers to malloc'd strings.  The array
+   is NULL terminated.  May block. */
+const char *xenbus_ls(struct xenbus_req *r, xenbus_transaction_t xbt,
+                     const char *dir, char **contents, int *contents_len);
+
+/* Reads permissions associated with a path.  Returns a malloc'd error
+   string on failure and sets *value to NULL.  On success, *value is
+   set to a malloc'd copy of the value. */
+const char *xenbus_get_perms(struct xenbus_req *r, xenbus_transaction_t xbt, 
const char *path, char **value);
+
+/* Sets the permissions associated with a path.  Returns a malloc'd
+   error string on failure. */
+const char *xenbus_set_perms(struct xenbus_req *r, xenbus_transaction_t xbt, 
const char *path, domid_t dom, char perm);
+
+/* Start a xenbus transaction.  Returns the transaction in xbt on
+   success or a malloc'd error string otherwise. */
+const char *xenbus_transaction_start(struct xenbus_req *r, 
xenbus_transaction_t *xbt);
+
+/* End a xenbus transaction.  Returns a malloc'd error string if it
+   fails.  abort says whether the transaction should be aborted.
+   Returns 1 in *retry iff the transaction should be retried. */
+const char *xenbus_transaction_end(struct xenbus_req *r, xenbus_transaction_t,
+                                  int abort, int *retry);
+
+/* Read path and parse it as an integer.  Returns -1 on error. */
+int xenbus_read_integer(struct xenbus_req *r, char *path);
+
+/* Send a debug message to xenbus.  Can block. */
+void xenbus_debug_msg(struct xenbus_req *r, const char *msg);
+
+#endif /* XENBUS_H__ */
diff -r 092232fa1fbd extras/stubfw/ioemu.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/ioemu.c     Wed Nov 21 16:00:38 2007 +0100
@@ -0,0 +1,397 @@
+#include "ioemu/vl.h"
+#include "console.h"
+#include "hypervisor.h"
+
+//#define DEBUG_IOPORT
+#define DEBUG_UNUSED_IOPORT
+//#define DEBUG_IOSAPIC
+
+void pstrcpy(char *buf, int buf_size, const char *str)
+{
+    int c;
+    char *q = buf;
+
+    if (buf_size <= 0)
+        return;
+
+    for(;;) {
+        c = *str++;
+        if (c == 0 || q >= buf + buf_size - 1)
+            break;
+        *q++ = c;
+    }
+    *q = '\0';
+}
+
+extern char end;
+static char *heap_ptr = &end;
+
+void *qemu_mallocz(size_t size)
+{
+  void *res;
+
+  /* Align.  */
+  size = (size + 0x0f) & ~0x0fUL;
+
+  res = heap_ptr;
+  heap_ptr += size;
+  memset (res, 0, size);
+
+  return res;
+}
+
+static void disp_ioport_map (void);
+
+void hw_error(const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    printf("ioemu: hardware error: ");
+    vprintf(fmt, ap);
+    printf("\n");
+
+    disp_ioport_map ();
+    exit ();
+}
+
+struct ioport_map {
+  uint16_t base;
+  uint16_t end;
+  uint16_t off;
+};
+
+#define IOPORT_MAP_SIZE 16
+static int ioport_map_len;
+static int ioport_map_off;
+static struct ioport_map ioport_map[IOPORT_MAP_SIZE];
+
+static void disp_ioport_map (void)
+{
+    int i;
+
+    printf ("map_len=%d, map_off=%d\n", ioport_map_len, ioport_map_off);
+    for (i = 0; i < ioport_map_len; i++) {
+       printf ("%d: base=%4x end=%4x off=%d\n",
+               i, ioport_map[i].base, ioport_map[i].end, ioport_map[i].off);
+    }
+}
+    
+static int find_ioport(uint16_t port)
+{
+  int i;
+  for (i = 1; i < ioport_map_len; i++)
+    if (port >= ioport_map[i].base && port <= ioport_map[i].end)
+      return ioport_map[i].off + port - ioport_map[i].base;
+  return 0;
+}
+
+static int find_ioport_or_allocate(uint16_t port)
+{
+    int m = find_ioport (port);
+    if (m)
+       return m;
+    m = ioport_map_len - 1;
+    if (port == ioport_map[m].end + 1) {
+       /* Extend last one.  */
+       ioport_map[m].end++;
+       return ioport_map_off++;
+    }
+    if (ioport_map_len == IOPORT_MAP_SIZE)
+       hw_error ("ioport allocate: no more map");
+    m = ioport_map_len++;
+    ioport_map[m].base = port;
+    ioport_map[m].end = port;
+    ioport_map[m].off = ioport_map_off;
+    return ioport_map_off++;
+}
+
+#define MAX_IOPORTS 128
+static void *ioport_opaque_x[MAX_IOPORTS];
+static IOPortReadFunc *ioport_read_table_x[3][MAX_IOPORTS];
+static IOPortWriteFunc *ioport_write_table_x[3][MAX_IOPORTS];
+
+#ifdef DEBUG_UNUSED_IOPORT
+static int
+report_unused_port (uint32_t port)
+{
+  /* VGA.  */
+  if ((port & ~0x1f) == 0x3c0)
+    return 0;
+  /* Keyboard.  */
+  if ((port & ~0x4) == 0x60)
+    return 0;
+  /* PNP  */
+  if ((port & ~0x01) == 0x4d0)
+    return 0;
+  return 1;
+}
+#endif
+
+uint32_t default_ioport_readb(void *opaque, uint32_t address)
+{
+#ifdef DEBUG_UNUSED_IOPORT
+    if (report_unused_port (address))
+       printf("unused inb: port=0x%04x\n", address);
+#endif
+    return 0xff;
+}
+
+void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data)
+{
+#ifdef DEBUG_UNUSED_IOPORT
+    if (report_unused_port (address))
+       printf("unused outb: port=0x%04x data=0x%02x\n", address, data);
+#endif
+}
+
+/* default is to make two byte accesses */
+uint32_t default_ioport_readw(void *opaque, uint32_t address)
+{
+    uint32_t data;
+    data = cpu_inb(address);
+    data |= cpu_inb(address + 1) << 8;
+    return data;
+}
+
+void default_ioport_writew(void *opaque, uint32_t address, uint32_t data)
+{
+  cpu_outb(address, data & 0xff);
+  cpu_outb(address, (data >> 8) & 0xff);
+}
+
+uint32_t default_ioport_readl(void *opaque, uint32_t address)
+{
+#ifdef DEBUG_UNUSED_IOPORT
+    if (report_unused_port (address))
+       printf("unused inl: port=0x%04x\n", address);
+#endif
+    return 0xffffffff;
+}
+
+void default_ioport_writel(void *opaque, uint32_t address, uint32_t data)
+{
+#ifdef DEBUG_UNUSED_IOPORT
+    if (report_unused_port (address))
+       printf("unused outl: port=0x%04x data=0x%02x\n", address, data);
+#endif
+}
+
+void init_ioports(void)
+{
+  int i = 0;
+
+  for (i = 0; i < MAX_IOPORTS; i++) {
+    ioport_read_table_x[0][i] = default_ioport_readb;
+    ioport_write_table_x[0][i] = default_ioport_writeb;
+    ioport_read_table_x[1][i] = default_ioport_readw;
+    ioport_write_table_x[1][i] = default_ioport_writew;
+    ioport_read_table_x[2][i] = default_ioport_readl;
+    ioport_write_table_x[2][i] = default_ioport_writel;
+  }
+  ioport_map_len = 1;
+  ioport_map_off = 1;
+}
+
+/* size is the word size in byte */
+int register_ioport_read(int start, int length, int size,
+                         IOPortReadFunc *func, void *opaque)
+{
+    int i, bsize;
+
+    if (size == 1) {
+        bsize = 0;
+    } else if (size == 2) {
+        bsize = 1;
+    } else if (size == 4) {
+        bsize = 2;
+    } else {
+        hw_error("register_ioport_read: invalid size");
+        return -1;
+    }
+    for(i = start; i < start + length; i += size) {
+       int m = find_ioport_or_allocate (i);
+        ioport_read_table_x[bsize][m] = func;
+        if (ioport_opaque_x[m] != NULL && ioport_opaque_x[m] != opaque)
+            hw_error("register_ioport_read: invalid opaque");
+        ioport_opaque_x[m] = opaque;
+    }
+    return 0;
+}
+
+/* size is the word size in byte */
+int register_ioport_write(int start, int length, int size,
+                          IOPortWriteFunc *func, void *opaque)
+{
+    int i, bsize;
+
+#if 0
+    printf ("register_ioport_write: start=%3x len=%3x size=%d opq=%lx\n",
+           start, length, size, opaque);
+#endif
+    if (size == 1) {
+        bsize = 0;
+    } else if (size == 2) {
+        bsize = 1;
+    } else if (size == 4) {
+        bsize = 2;
+    } else {
+        hw_error("register_ioport_write: invalid size");
+        return -1;
+    }
+    for(i = start; i < start + length; i += size) {
+       int m = find_ioport_or_allocate (i);
+        ioport_write_table_x[bsize][m] = func;
+        if (ioport_opaque_x[m] != NULL && ioport_opaque_x[m] != opaque)
+            hw_error("register_ioport_write: invalid opaque");
+        ioport_opaque_x[m] = opaque;
+    }
+    return 0;
+}
+
+#if 0
+void isa_unassign_ioport(int start, int length)
+{
+    int i;
+
+    for(i = start; i < start + length; i++) {
+        ioport_read_table[0][i] = default_ioport_readb;
+        ioport_read_table[1][i] = default_ioport_readw;
+        ioport_read_table[2][i] = default_ioport_readl;
+
+        ioport_write_table[0][i] = default_ioport_writeb;
+        ioport_write_table[1][i] = default_ioport_writew;
+        ioport_write_table[2][i] = default_ioport_writel;
+    }
+}
+#endif
+
+/***********************************************************/
+
+void cpu_outb(int addr, int val)
+{
+    int m = find_ioport (addr);
+#ifdef DEBUG_IOPORT
+    printf("outb: %04x %02x\n", addr, val);
+#endif
+    ioport_write_table_x[0][m](ioport_opaque_x[m], addr, val);
+}
+
+void cpu_outw(int addr, int val)
+{
+    int m = find_ioport (addr);
+#ifdef DEBUG_IOPORT
+    printf("outw: %04x %04x\n", addr, val);
+#endif
+    ioport_write_table_x[1][m](ioport_opaque_x[m], addr, val);
+}
+
+void cpu_outl(int addr, int val)
+{
+    int m = find_ioport (addr);
+#ifdef DEBUG_IOPORT
+    printf("outl: %04x %08x\n", addr, val);
+#endif
+    ioport_write_table_x[2][m](ioport_opaque_x[m], addr, val);
+}
+
+int cpu_inb(int addr)
+{
+    int m = find_ioport (addr);
+    int val;
+    val = ioport_read_table_x[0][m](ioport_opaque_x[m], addr);
+#ifdef DEBUG_IOPORT
+    printf("inb : %04x %02x\n", addr, val);
+#endif
+    return val;
+}
+
+int cpu_inw(int addr)
+{
+    int m = find_ioport (addr);
+    int val;
+    val = ioport_read_table_x[1][m](ioport_opaque_x[m], addr);
+#ifdef DEBUG_IOPORT
+    printf("inw : %04x %04x\n", addr, val);
+#endif
+    return val;
+}
+
+int cpu_inl(int addr)
+{
+    int m = find_ioport (addr);
+    int val;
+    val = ioport_read_table_x[2][m](ioport_opaque_x[m], addr);
+#ifdef DEBUG_IOPORT
+    printf("inl : %04x %08x\n", addr, val);
+#endif
+    return val;
+}
+
+#define __ia64_fc(addr)        asm volatile ("fc %0" :: "r"(addr) : "memory")
+#define ia64_sync_i()  asm volatile (";; sync.i" ::: "memory")
+#define ia64_srlz_i()  asm volatile (";; srlz.i ;;" ::: "memory")
+
+/* IA64 has seperate I/D cache, with coherence maintained by DMA controller.
+ * So to emulate right behavior that guest OS is assumed, we need to flush
+ * I/D cache here.
+ */
+static void sync_icache(unsigned long address, int len)
+{
+    int l;
+
+    for(l = 0; l < (len + 32); l += 32)
+        __ia64_fc(address + l);
+
+    ia64_sync_i();
+    ia64_srlz_i();
+}
+
+void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
+                            int len, int is_write)
+{
+  if (is_write) {
+    memcpy ((void *)addr, buf, len);
+    sync_icache (addr, len);
+  }
+  else
+    memcpy (buf, (void *)addr, len);
+}
+
+BlockDriverState *bs_table[MAX_DISKS + 1];
+
+static uint8_t irq_level[48];
+static void iosapic_set_irq(void *opaque, int irq, int level)
+{
+    int res;
+
+    if (level == irq_level[irq])
+       return;
+
+    irq_level[irq] = level;
+
+#if defined(DEBUG_IOSAPIC)
+    printf("iospaic_set_irq: irq=%d level=%d\n", irq, level);
+#endif
+    if (irq < 16)
+       res = HYPERVISOR_hvm_set_isa_irq_level(DOMID_SELF, irq, level);
+    else {
+       int pci_irq = irq - 16;
+       res = HYPERVISOR_hvm_set_pci_intx_level
+           (DOMID_SELF, 0, 0, (pci_irq >> 2), (pci_irq & 3), level);
+    }
+    if (res != 0)
+       printk ("ioemu: can set irq level (irq=%d, err=%d)\n", irq, res);
+}
+
+qemu_irq *
+init_iosapic (void)
+{
+  qemu_irq *res;
+
+  res = qemu_allocate_irqs (iosapic_set_irq, NULL, 48);
+
+  return res;
+}
+
+
diff -r 092232fa1fbd extras/stubfw/ioemu/block.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/ioemu/block.c       Sat Nov 17 05:12:18 2007 +0100
@@ -0,0 +1,1386 @@
+/*
+ * QEMU System Emulator block driver
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "block_int.h"
+
+#ifdef _BSD
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/queue.h>
+#include <sys/disk.h>
+#endif
+
+
+#ifndef IOEMU
+typedef struct BlockDriverAIOCBSync {
+    BlockDriverAIOCB common;
+    QEMUBH *bh;
+    int ret;
+} BlockDriverAIOCBSync;
+#else
+typedef struct BlockDriverAIOCBSync {
+    int ret;
+} BlockDriverAIOCBSync;
+
+#endif
+
+static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque);
+static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque);
+
+static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb);
+#ifndef IOEMU
+static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
+                        uint8_t *buf, int nb_sectors);
+static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
+                         const uint8_t *buf, int nb_sectors);
+#endif
+
+static BlockDriverState *bdrv_first;
+//static BlockDriver *first_drv;
+
+#ifndef IOEMU
+int path_is_absolute(const char *path)
+{
+    const char *p;
+#ifdef _WIN32
+    /* specific case for names like: "\\.\d:" */
+    if (*path == '/' || *path == '\\')
+        return 1;
+#endif
+    p = strchr(path, ':');
+    if (p)
+        p++;
+    else
+        p = path;
+#ifdef _WIN32
+    return (*p == '/' || *p == '\\');
+#else
+    return (*p == '/');
+#endif
+}
+
+/* if filename is absolute, just copy it to dest. Otherwise, build a
+   path to it by considering it is relative to base_path. URL are
+   supported. */
+void path_combine(char *dest, int dest_size,
+                  const char *base_path,
+                  const char *filename)
+{
+    const char *p, *p1;
+    int len;
+
+    if (dest_size <= 0)
+        return;
+    if (path_is_absolute(filename)) {
+        pstrcpy(dest, dest_size, filename);
+    } else {
+        p = strchr(base_path, ':');
+        if (p)
+            p++;
+        else
+            p = base_path;
+        p1 = strrchr(base_path, '/');
+#ifdef _WIN32
+        {
+            const char *p2;
+            p2 = strrchr(base_path, '\\');
+            if (!p1 || p2 > p1)
+                p1 = p2;
+        }
+#endif
+        if (p1)
+            p1++;
+        else
+            p1 = base_path;
+        if (p1 > p)
+            p = p1;
+        len = p - base_path;
+        if (len > dest_size - 1)
+            len = dest_size - 1;
+        memcpy(dest, base_path, len);
+        dest[len] = '\0';
+        pstrcat(dest, dest_size, filename);
+    }
+}
+#endif
+
+void bdrv_register(BlockDriver *bdrv)
+{
+    if (!bdrv->bdrv_aio_read) {
+        /* add AIO emulation layer */
+        bdrv->bdrv_aio_read = bdrv_aio_read_em;
+        bdrv->bdrv_aio_write = bdrv_aio_write_em;
+        bdrv->bdrv_aio_cancel = bdrv_aio_cancel_em;
+        bdrv->aiocb_size = sizeof(BlockDriverAIOCBSync);
+    }
+#ifndef IOEMU
+    else if (!bdrv->bdrv_read && !bdrv->bdrv_pread) {
+        /* add synchronous IO emulation layer */
+        bdrv->bdrv_read = bdrv_read_em;
+        bdrv->bdrv_write = bdrv_write_em;
+    }
+    bdrv->next = first_drv;
+    first_drv = bdrv;
+#endif
+}
+
+/* create a new block device (by default it is empty) */
+BlockDriverState *bdrv_new(const char *device_name)
+{
+    BlockDriverState **pbs, *bs;
+
+    bs = qemu_mallocz(sizeof(BlockDriverState));
+    if(!bs)
+        return NULL;
+    pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
+    if (device_name[0] != '\0') {
+        /* insert at the end */
+        pbs = &bdrv_first;
+        while (*pbs != NULL)
+            pbs = &(*pbs)->next;
+        *pbs = bs;
+    }
+    return bs;
+}
+
+#ifndef IOEMU
+BlockDriver *bdrv_find_format(const char *format_name)
+{
+    BlockDriver *drv1;
+    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
+        if (!strcmp(drv1->format_name, format_name))
+            return drv1;
+    }
+    return NULL;
+}
+
+int bdrv_create(BlockDriver *drv,
+                const char *filename, int64_t size_in_sectors,
+                const char *backing_file, int flags)
+{
+    if (!drv->bdrv_create)
+        return -ENOTSUP;
+    return drv->bdrv_create(filename, size_in_sectors, backing_file, flags);
+}
+
+#ifdef _WIN32
+void get_tmp_filename(char *filename, int size)
+{
+    char temp_dir[MAX_PATH];
+
+    GetTempPath(MAX_PATH, temp_dir);
+    GetTempFileName(temp_dir, "qem", 0, filename);
+}
+#else
+void get_tmp_filename(char *filename, int size)
+{
+    int fd;
+    /* XXX: race condition possible */
+    pstrcpy(filename, size, "/tmp/vl.XXXXXX");
+    fd = mkstemp(filename);
+    close(fd);
+}
+#endif
+
+#ifdef _WIN32
+static int is_windows_drive_prefix(const char *filename)
+{
+    return (((filename[0] >= 'a' && filename[0] <= 'z') ||
+             (filename[0] >= 'A' && filename[0] <= 'Z')) &&
+            filename[1] == ':');
+}
+
+static int is_windows_drive(const char *filename)
+{
+    if (is_windows_drive_prefix(filename) &&
+        filename[2] == '\0')
+        return 1;
+    if (strstart(filename, "\\\\.\\", NULL) ||
+        strstart(filename, "//./", NULL))
+        return 1;
+    return 0;
+}
+#endif
+
+static BlockDriver *find_protocol(const char *filename)
+{
+    BlockDriver *drv1;
+    char protocol[128];
+    int len;
+    const char *p;
+
+#ifdef _WIN32
+    if (is_windows_drive(filename) ||
+        is_windows_drive_prefix(filename))
+        return &bdrv_raw;
+#endif
+    p = strchr(filename, ':');
+    if (!p)
+        return &bdrv_raw;
+    len = p - filename;
+    if (len > sizeof(protocol) - 1)
+        len = sizeof(protocol) - 1;
+    memcpy(protocol, filename, len);
+    protocol[len] = '\0';
+    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
+        if (drv1->protocol_name &&
+            !strcmp(drv1->protocol_name, protocol))
+            return drv1;
+    }
+    return NULL;
+}
+
+/* XXX: force raw format if block or character device ? It would
+   simplify the BSD case */
+static BlockDriver *find_image_format(const char *filename)
+{
+    int ret, score, score_max;
+    BlockDriver *drv1, *drv;
+    uint8_t buf[2048];
+    BlockDriverState *bs;
+
+    /* detect host devices. By convention, /dev/cdrom[N] is always
+       recognized as a host CDROM */
+    if (strstart(filename, "/dev/cdrom", NULL))
+        return &bdrv_host_device;
+#ifdef _WIN32
+    if (is_windows_drive(filename))
+        return &bdrv_host_device;
+#else
+    {
+        struct stat st;
+        if (stat(filename, &st) >= 0 &&
+            (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
+            return &bdrv_host_device;
+        }
+    }
+#endif
+
+    drv = find_protocol(filename);
+    /* no need to test disk image formats for vvfat */
+    if (drv == &bdrv_vvfat)
+        return drv;
+
+    ret = bdrv_file_open(&bs, filename, BDRV_O_RDONLY);
+    if (ret < 0)
+        return NULL;
+    ret = bdrv_pread(bs, 0, buf, sizeof(buf));
+    bdrv_delete(bs);
+    if (ret < 0) {
+        return NULL;
+    }
+
+    score_max = 0;
+    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
+        if (drv1->bdrv_probe) {
+            score = drv1->bdrv_probe(buf, ret, filename);
+            if (score > score_max) {
+                score_max = score;
+                drv = drv1;
+            }
+        }
+    }
+    return drv;
+}
+
+int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
+{
+    BlockDriverState *bs;
+    int ret;
+
+    bs = bdrv_new("");
+    if (!bs)
+        return -ENOMEM;
+    ret = bdrv_open2(bs, filename, flags | BDRV_O_FILE, NULL);
+    if (ret < 0) {
+        bdrv_delete(bs);
+        return ret;
+    }
+    *pbs = bs;
+    return 0;
+}
+
+int bdrv_open(BlockDriverState *bs, const char *filename, int flags)
+{
+    return bdrv_open2(bs, filename, flags, NULL);
+}
+
+int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
+               BlockDriver *drv)
+{
+    int ret, open_flags;
+    char tmp_filename[PATH_MAX];
+    char backing_filename[PATH_MAX];
+
+    bs->read_only = 0;
+    bs->is_temporary = 0;
+    bs->encrypted = 0;
+
+    if (flags & BDRV_O_SNAPSHOT) {
+        BlockDriverState *bs1;
+        int64_t total_size;
+
+        /* if snapshot, we create a temporary backing file and open it
+           instead of opening 'filename' directly */
+
+        /* if there is a backing file, use it */
+        bs1 = bdrv_new("");
+        if (!bs1) {
+            return -ENOMEM;
+        }
+        if (bdrv_open(bs1, filename, 0) < 0) {
+            bdrv_delete(bs1);
+            return -1;
+        }
+        total_size = bdrv_getlength(bs1) >> SECTOR_BITS;
+        bdrv_delete(bs1);
+
+        get_tmp_filename(tmp_filename, sizeof(tmp_filename));
+        realpath(filename, backing_filename);
+        if (bdrv_create(&bdrv_qcow2, tmp_filename,
+                        total_size, backing_filename, 0) < 0) {
+            return -1;
+        }
+        filename = tmp_filename;
+        bs->is_temporary = 1;
+    }
+
+    pstrcpy(bs->filename, sizeof(bs->filename), filename);
+    if (flags & BDRV_O_FILE) {
+        drv = find_protocol(filename);
+        if (!drv)
+            return -ENOENT;
+    } else {
+        if (!drv) {
+            drv = find_image_format(filename);
+            if (!drv)
+                return -1;
+        }
+    }
+    bs->drv = drv;
+    bs->opaque = qemu_mallocz(drv->instance_size);
+    if (bs->opaque == NULL && drv->instance_size > 0)
+        return -1;
+    /* Note: for compatibility, we open disk image files as RDWR, and
+       RDONLY as fallback */
+    if (!(flags & BDRV_O_FILE))
+        open_flags = BDRV_O_RDWR;
+    else
+        open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
+    ret = drv->bdrv_open(bs, filename, open_flags);
+    if (ret == -EACCES && !(flags & BDRV_O_FILE)) {
+        ret = drv->bdrv_open(bs, filename, BDRV_O_RDONLY);
+        bs->read_only = 1;
+    }
+    if (ret < 0) {
+        qemu_free(bs->opaque);
+        bs->opaque = NULL;
+        bs->drv = NULL;
+        return ret;
+    }
+    if (drv->bdrv_getlength) {
+        bs->total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
+    }
+#ifndef _WIN32
+    if (bs->is_temporary) {
+        unlink(filename);
+    }
+#endif
+    if (bs->backing_file[0] != '\0') {
+        /* if there is a backing file, use it */
+        bs->backing_hd = bdrv_new("");
+        if (!bs->backing_hd) {
+        fail:
+            bdrv_close(bs);
+            return -ENOMEM;
+        }
+        path_combine(backing_filename, sizeof(backing_filename),
+                     filename, bs->backing_file);
+        if (bdrv_open(bs->backing_hd, backing_filename, 0) < 0)
+            goto fail;
+    }
+
+    /* call the change callback */
+    bs->media_changed = 1;
+    if (bs->change_cb)
+        bs->change_cb(bs->change_opaque);
+
+    return 0;
+}
+#endif
+
+void bdrv_close(BlockDriverState *bs)
+{
+    if (bs->drv) {
+#ifndef IOEMU
+        if (bs->backing_hd)
+            bdrv_delete(bs->backing_hd);
+        bs->drv->bdrv_close(bs);
+        qemu_free(bs->opaque);
+#ifdef _WIN32
+        if (bs->is_temporary) {
+            unlink(bs->filename);
+        }
+#endif
+        bs->opaque = NULL;
+#endif
+        bs->drv = NULL;
+
+        /* call the change callback */
+        bs->media_changed = 1;
+        if (bs->change_cb)
+            bs->change_cb(bs->change_opaque);
+    }
+}
+
+#ifndef IOEMU
+void bdrv_delete(BlockDriverState *bs)
+{
+    /* XXX: remove the driver list */
+    bdrv_close(bs);
+    qemu_free(bs);
+}
+
+/* commit COW file into the raw image */
+int bdrv_commit(BlockDriverState *bs)
+{
+    BlockDriver *drv = bs->drv;
+    int64_t i, total_sectors;
+    int n, j;
+    unsigned char sector[512];
+
+    if (!drv)
+        return -ENOMEDIUM;
+
+    if (bs->read_only) {
+       return -EACCES;
+    }
+
+    if (!bs->backing_hd) {
+       return -ENOTSUP;
+    }
+
+    total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
+    for (i = 0; i < total_sectors;) {
+        if (drv->bdrv_is_allocated(bs, i, 65536, &n)) {
+            for(j = 0; j < n; j++) {
+                if (bdrv_read(bs, i, sector, 1) != 0) {
+                    return -EIO;
+                }
+
+                if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
+                    return -EIO;
+                }
+                i++;
+           }
+       } else {
+            i += n;
+        }
+    }
+
+    if (drv->bdrv_make_empty)
+       return drv->bdrv_make_empty(bs);
+
+    return 0;
+}
+#endif
+
+/* return < 0 if error. See bdrv_write() for the return codes */
+int bdrv_read(BlockDriverState *bs, int64_t sector_num,
+              uint8_t *buf, int nb_sectors)
+{
+    BlockDriver *drv = bs->drv;
+
+    if (!drv)
+        return -ENOMEDIUM;
+
+#ifdef IOEMU
+    if ((unsigned long)buf & SECTOR_MASK) {
+      printf ("bdrv_read: bad buf (%p) from %p\n",
+             buf, __builtin_return_address (0));
+    }
+#endif
+
+    if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
+            memcpy(buf, bs->boot_sector_data, 512);
+        sector_num++;
+        nb_sectors--;
+        buf += 512;
+        if (nb_sectors == 0)
+            return 0;
+    }
+    if (drv->bdrv_pread) {
+        int ret, len;
+        len = nb_sectors * 512;
+        ret = drv->bdrv_pread(bs, sector_num * 512, buf, len);
+        if (ret < 0)
+            return ret;
+        else if (ret != len)
+            return -EINVAL;
+        else
+            return 0;
+    } else {
+        return drv->bdrv_read(bs, sector_num, buf, nb_sectors);
+    }
+}
+
+/* Return < 0 if error. Important errors are:
+  -EIO         generic I/O error (may happen for all errors)
+  -ENOMEDIUM   No media inserted.
+  -EINVAL      Invalid sector number or nb_sectors
+  -EACCES      Trying to write a read-only device
+*/
+int bdrv_write(BlockDriverState *bs, int64_t sector_num,
+               const uint8_t *buf, int nb_sectors)
+{
+    BlockDriver *drv = bs->drv;
+    if (!bs->drv)
+        return -ENOMEDIUM;
+    if (bs->read_only)
+        return -EACCES;
+    if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
+        memcpy(bs->boot_sector_data, buf, 512);
+    }
+    if (drv->bdrv_pwrite) {
+        int ret, len;
+        len = nb_sectors * 512;
+        ret = drv->bdrv_pwrite(bs, sector_num * 512, buf, len);
+        if (ret < 0)
+            return ret;
+        else if (ret != len)
+            return -EIO;
+        else
+            return 0;
+    } else {
+        return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
+    }
+}
+
+#ifndef IOEMU
+static int bdrv_pread_em(BlockDriverState *bs, int64_t offset,
+                         uint8_t *buf, int count1)
+{
+    uint8_t tmp_buf[SECTOR_SIZE];
+    int len, nb_sectors, count;
+    int64_t sector_num;
+
+    count = count1;
+    /* first read to align to sector start */
+    len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
+    if (len > count)
+        len = count;
+    sector_num = offset >> SECTOR_BITS;
+    if (len > 0) {
+        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
+            return -EIO;
+        memcpy(buf, tmp_buf + (offset & (SECTOR_SIZE - 1)), len);
+        count -= len;
+        if (count == 0)
+            return count1;
+        sector_num++;
+        buf += len;
+    }
+
+    /* read the sectors "in place" */
+    nb_sectors = count >> SECTOR_BITS;
+    if (nb_sectors > 0) {
+        if (bdrv_read(bs, sector_num, buf, nb_sectors) < 0)
+            return -EIO;
+        sector_num += nb_sectors;
+        len = nb_sectors << SECTOR_BITS;
+        buf += len;
+        count -= len;
+    }
+
+    /* add data from the last sector */
+    if (count > 0) {
+        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
+            return -EIO;
+        memcpy(buf, tmp_buf, count);
+    }
+    return count1;
+}
+
+static int bdrv_pwrite_em(BlockDriverState *bs, int64_t offset,
+                          const uint8_t *buf, int count1)
+{
+    uint8_t tmp_buf[SECTOR_SIZE];
+    int len, nb_sectors, count;
+    int64_t sector_num;
+
+    count = count1;
+    /* first write to align to sector start */
+    len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
+    if (len > count)
+        len = count;
+    sector_num = offset >> SECTOR_BITS;
+    if (len > 0) {
+        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
+            return -EIO;
+        memcpy(tmp_buf + (offset & (SECTOR_SIZE - 1)), buf, len);
+        if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
+            return -EIO;
+        count -= len;
+        if (count == 0)
+            return count1;
+        sector_num++;
+        buf += len;
+    }
+
+    /* write the sectors "in place" */
+    nb_sectors = count >> SECTOR_BITS;
+    if (nb_sectors > 0) {
+        if (bdrv_write(bs, sector_num, buf, nb_sectors) < 0)
+            return -EIO;
+        sector_num += nb_sectors;
+        len = nb_sectors << SECTOR_BITS;
+        buf += len;
+        count -= len;
+    }
+
+    /* add data from the last sector */
+    if (count > 0) {
+        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
+            return -EIO;
+        memcpy(tmp_buf, buf, count);
+        if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
+            return -EIO;
+    }
+    return count1;
+}
+
+/**
+ * Read with byte offsets (needed only for file protocols)
+ */
+int bdrv_pread(BlockDriverState *bs, int64_t offset,
+               void *buf1, int count1)
+{
+    BlockDriver *drv = bs->drv;
+
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_pread)
+        return bdrv_pread_em(bs, offset, buf1, count1);
+    return drv->bdrv_pread(bs, offset, buf1, count1);
+}
+
+/**
+ * Write with byte offsets (needed only for file protocols)
+ */
+int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
+                const void *buf1, int count1)
+{
+    BlockDriver *drv = bs->drv;
+
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_pwrite)
+        return bdrv_pwrite_em(bs, offset, buf1, count1);
+    return drv->bdrv_pwrite(bs, offset, buf1, count1);
+}
+
+/**
+ * Truncate file to 'offset' bytes (needed only for file protocols)
+ */
+int bdrv_truncate(BlockDriverState *bs, int64_t offset)
+{
+    BlockDriver *drv = bs->drv;
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_truncate)
+        return -ENOTSUP;
+    return drv->bdrv_truncate(bs, offset);
+}
+#endif
+
+/**
+ * Length of a file in bytes. Return < 0 if error or unknown.
+ */
+int64_t bdrv_getlength(BlockDriverState *bs)
+{
+    BlockDriver *drv = bs->drv;
+    
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_getlength) {
+        /* legacy mode */
+        return bs->total_sectors * SECTOR_SIZE;
+    }
+    return drv->bdrv_getlength(bs);
+}
+
+/* return 0 as number of sectors if no device present or error */
+void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
+{
+    int64_t length;
+    length = bdrv_getlength(bs);
+    if (length < 0)
+        length = 0;
+    else
+        length = length >> SECTOR_BITS;
+    *nb_sectors_ptr = length;
+}
+
+/* force a given boot sector. */
+void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
+{
+    bs->boot_sector_enabled = 1;
+    if (size > 512)
+        size = 512;
+    memcpy(bs->boot_sector_data, data, size);
+    memset(bs->boot_sector_data + size, 0, 512 - size);
+}
+
+void bdrv_set_geometry_hint(BlockDriverState *bs,
+                            int cyls, int heads, int secs)
+{
+    bs->cyls = cyls;
+    bs->heads = heads;
+    bs->secs = secs;
+}
+
+void bdrv_set_type_hint(BlockDriverState *bs, int type)
+{
+    bs->type = type;
+    bs->removable = ((type == BDRV_TYPE_CDROM ||
+                      type == BDRV_TYPE_FLOPPY));
+}
+
+void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
+{
+    bs->translation = translation;
+}
+
+void bdrv_get_geometry_hint(BlockDriverState *bs,
+                            int *pcyls, int *pheads, int *psecs)
+{
+    *pcyls = bs->cyls;
+    *pheads = bs->heads;
+    *psecs = bs->secs;
+}
+
+int bdrv_get_type_hint(BlockDriverState *bs)
+{
+    return bs->type;
+}
+
+int bdrv_get_translation_hint(BlockDriverState *bs)
+{
+    return bs->translation;
+}
+
+int bdrv_is_removable(BlockDriverState *bs)
+{
+    return bs->removable;
+}
+
+int bdrv_is_read_only(BlockDriverState *bs)
+{
+    return bs->read_only;
+}
+
+/* XXX: no longer used */
+void bdrv_set_change_cb(BlockDriverState *bs,
+                        void (*change_cb)(void *opaque), void *opaque)
+{
+    bs->change_cb = change_cb;
+    bs->change_opaque = opaque;
+}
+
+#ifndef IOEMU
+int bdrv_is_encrypted(BlockDriverState *bs)
+{
+    if (bs->backing_hd && bs->backing_hd->encrypted)
+        return 1;
+    return bs->encrypted;
+}
+
+int bdrv_set_key(BlockDriverState *bs, const char *key)
+{
+    int ret;
+    if (bs->backing_hd && bs->backing_hd->encrypted) {
+        ret = bdrv_set_key(bs->backing_hd, key);
+        if (ret < 0)
+            return ret;
+        if (!bs->encrypted)
+            return 0;
+    }
+    if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
+        return -1;
+    return bs->drv->bdrv_set_key(bs, key);
+}
+
+void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
+{
+    if (!bs->drv) {
+        buf[0] = '\0';
+    } else {
+        pstrcpy(buf, buf_size, bs->drv->format_name);
+    }
+}
+
+void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
+                         void *opaque)
+{
+    BlockDriver *drv;
+
+    for (drv = first_drv; drv != NULL; drv = drv->next) {
+        it(opaque, drv->format_name);
+    }
+}
+
+BlockDriverState *bdrv_find(const char *name)
+{
+    BlockDriverState *bs;
+
+    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
+        if (!strcmp(name, bs->device_name))
+            return bs;
+    }
+    return NULL;
+}
+
+void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque)
+{
+    BlockDriverState *bs;
+
+    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
+        it(opaque, bs->device_name);
+    }
+}
+
+const char *bdrv_get_device_name(BlockDriverState *bs)
+{
+    return bs->device_name;
+}
+#endif
+
+void bdrv_flush(BlockDriverState *bs)
+{
+    if (bs->drv->bdrv_flush)
+        bs->drv->bdrv_flush(bs);
+    if (bs->backing_hd)
+        bdrv_flush(bs->backing_hd);
+}
+
+#ifndef IOEMU
+void bdrv_info(void)
+{
+    BlockDriverState *bs;
+
+    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
+        term_printf("%s:", bs->device_name);
+        term_printf(" type=");
+        switch(bs->type) {
+        case BDRV_TYPE_HD:
+            term_printf("hd");
+            break;
+        case BDRV_TYPE_CDROM:
+            term_printf("cdrom");
+            break;
+        case BDRV_TYPE_FLOPPY:
+            term_printf("floppy");
+            break;
+        }
+        term_printf(" removable=%d", bs->removable);
+        if (bs->removable) {
+            term_printf(" locked=%d", bs->locked);
+        }
+        if (bs->drv) {
+            term_printf(" file=");
+           term_print_filename(bs->filename);
+            if (bs->backing_file[0] != '\0') {
+                term_printf(" backing_file=");
+               term_print_filename(bs->backing_file);
+           }
+            term_printf(" ro=%d", bs->read_only);
+            term_printf(" drv=%s", bs->drv->format_name);
+            if (bs->encrypted)
+                term_printf(" encrypted");
+        } else {
+            term_printf(" [not inserted]");
+        }
+        term_printf("\n");
+    }
+}
+
+void bdrv_get_backing_filename(BlockDriverState *bs,
+                               char *filename, int filename_size)
+{
+    if (!bs->backing_hd) {
+        pstrcpy(filename, filename_size, "");
+    } else {
+        pstrcpy(filename, filename_size, bs->backing_file);
+    }
+}
+
+int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
+                          const uint8_t *buf, int nb_sectors)
+{
+    BlockDriver *drv = bs->drv;
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_write_compressed)
+        return -ENOTSUP;
+    return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
+}
+
+int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+{
+    BlockDriver *drv = bs->drv;
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_get_info)
+        return -ENOTSUP;
+    memset(bdi, 0, sizeof(*bdi));
+    return drv->bdrv_get_info(bs, bdi);
+}
+
+/**************************************************************/
+/* handling of snapshots */
+
+int bdrv_snapshot_create(BlockDriverState *bs,
+                         QEMUSnapshotInfo *sn_info)
+{
+    BlockDriver *drv = bs->drv;
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_snapshot_create)
+        return -ENOTSUP;
+    return drv->bdrv_snapshot_create(bs, sn_info);
+}
+
+int bdrv_snapshot_goto(BlockDriverState *bs,
+                       const char *snapshot_id)
+{
+    BlockDriver *drv = bs->drv;
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_snapshot_goto)
+        return -ENOTSUP;
+    return drv->bdrv_snapshot_goto(bs, snapshot_id);
+}
+
+int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
+{
+    BlockDriver *drv = bs->drv;
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_snapshot_delete)
+        return -ENOTSUP;
+    return drv->bdrv_snapshot_delete(bs, snapshot_id);
+}
+
+int bdrv_snapshot_list(BlockDriverState *bs,
+                       QEMUSnapshotInfo **psn_info)
+{
+    BlockDriver *drv = bs->drv;
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_snapshot_list)
+        return -ENOTSUP;
+    return drv->bdrv_snapshot_list(bs, psn_info);
+}
+
+#define NB_SUFFIXES 4
+
+char *get_human_readable_size(char *buf, int buf_size, int64_t size)
+{
+    static const char suffixes[NB_SUFFIXES] = "KMGT";
+    int64_t base;
+    int i;
+
+    if (size <= 999) {
+        snprintf(buf, buf_size, "%" PRId64, size);
+    } else {
+        base = 1024;
+        for(i = 0; i < NB_SUFFIXES; i++) {
+            if (size < (10 * base)) {
+                snprintf(buf, buf_size, "%0.1f%c",
+                         (double)size / base,
+                         suffixes[i]);
+                break;
+            } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
+                snprintf(buf, buf_size, "%" PRId64 "%c",
+                         ((size + (base >> 1)) / base),
+                         suffixes[i]);
+                break;
+            }
+            base = base * 1024;
+        }
+    }
+    return buf;
+}
+
+char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
+{
+    char buf1[128], date_buf[128], clock_buf[128];
+#ifdef _WIN32
+    struct tm *ptm;
+#else
+    struct tm tm;
+#endif
+    time_t ti;
+    int64_t secs;
+
+    if (!sn) {
+        snprintf(buf, buf_size,
+                 "%-10s%-20s%7s%20s%15s",
+                 "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
+    } else {
+        ti = sn->date_sec;
+#ifdef _WIN32
+        ptm = localtime(&ti);
+        strftime(date_buf, sizeof(date_buf),
+                 "%Y-%m-%d %H:%M:%S", ptm);
+#else
+        localtime_r(&ti, &tm);
+        strftime(date_buf, sizeof(date_buf),
+                 "%Y-%m-%d %H:%M:%S", &tm);
+#endif
+        secs = sn->vm_clock_nsec / 1000000000;
+        snprintf(clock_buf, sizeof(clock_buf),
+                 "%02d:%02d:%02d.%03d",
+                 (int)(secs / 3600),
+                 (int)((secs / 60) % 60),
+                 (int)(secs % 60),
+                 (int)((sn->vm_clock_nsec / 1000000) % 1000));
+        snprintf(buf, buf_size,
+                 "%-10s%-20s%7s%20s%15s",
+                 sn->id_str, sn->name,
+                 get_human_readable_size(buf1, sizeof(buf1), 
sn->vm_state_size),
+                 date_buf,
+                 clock_buf);
+    }
+    return buf;
+}
+#endif
+
+
+/**************************************************************/
+/* async I/Os */
+
+BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
+                                uint8_t *buf, int nb_sectors,
+                                BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BlockDriver *drv = bs->drv;
+
+    if (!drv)
+        return NULL;
+
+    /* XXX: we assume that nb_sectors == 0 is suppored by the async read */
+    if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
+        memcpy(buf, bs->boot_sector_data, 512);
+        sector_num++;
+        nb_sectors--;
+        buf += 512;
+    }
+
+    return drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque);
+}
+
+BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
+                                 const uint8_t *buf, int nb_sectors,
+                                 BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BlockDriver *drv = bs->drv;
+
+    if (!drv)
+        return NULL;
+    if (bs->read_only)
+        return NULL;
+    if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
+        memcpy(bs->boot_sector_data, buf, 512);
+    }
+
+    return drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque);
+}
+
+void bdrv_aio_cancel(BlockDriverAIOCB *acb)
+{
+    BlockDriver *drv = acb->bs->drv;
+
+    drv->bdrv_aio_cancel(acb);
+}
+
+/**************************************************************/
+/* async block device emulation */
+
+#ifdef IOEMU
+#define QEMU_TOOL
+#endif
+#ifdef QEMU_TOOL
+static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    int ret;
+    ret = bdrv_read(bs, sector_num, buf, nb_sectors);
+    cb(opaque, ret);
+    return NULL;
+}
+
+static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    int ret;
+    ret = bdrv_write(bs, sector_num, buf, nb_sectors);
+    cb(opaque, ret);
+    return NULL;
+}
+
+static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb)
+{
+}
+#else
+static void bdrv_aio_bh_cb(void *opaque)
+{
+    BlockDriverAIOCBSync *acb = opaque;
+    acb->common.cb(acb->common.opaque, acb->ret);
+    qemu_aio_release(acb);
+}
+
+static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BlockDriverAIOCBSync *acb;
+    int ret;
+
+    acb = qemu_aio_get(bs, cb, opaque);
+    if (!acb->bh)
+        acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
+    ret = bdrv_read(bs, sector_num, buf, nb_sectors);
+    acb->ret = ret;
+    qemu_bh_schedule(acb->bh);
+    return &acb->common;
+}
+
+static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BlockDriverAIOCBSync *acb;
+    int ret;
+
+    acb = qemu_aio_get(bs, cb, opaque);
+    if (!acb->bh)
+        acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
+    ret = bdrv_write(bs, sector_num, buf, nb_sectors);
+    acb->ret = ret;
+    qemu_bh_schedule(acb->bh);
+    return &acb->common;
+}
+
+static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
+{
+    BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
+    qemu_bh_cancel(acb->bh);
+    qemu_aio_release(acb);
+}
+#endif /* !QEMU_TOOL */
+
+#ifndef IOEMU
+
+/**************************************************************/
+/* sync block device emulation */
+
+static void bdrv_rw_em_cb(void *opaque, int ret)
+{
+    *(int *)opaque = ret;
+}
+
+#define NOT_DONE 0x7fffffff
+
+static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
+                        uint8_t *buf, int nb_sectors)
+{
+    int async_ret;
+    BlockDriverAIOCB *acb;
+
+    async_ret = NOT_DONE;
+    qemu_aio_wait_start();
+    acb = bdrv_aio_read(bs, sector_num, buf, nb_sectors,
+                        bdrv_rw_em_cb, &async_ret);
+    if (acb == NULL) {
+        qemu_aio_wait_end();
+        return -1;
+    }
+    while (async_ret == NOT_DONE) {
+        qemu_aio_wait();
+    }
+    qemu_aio_wait_end();
+    return async_ret;
+}
+
+static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
+                         const uint8_t *buf, int nb_sectors)
+{
+    int async_ret;
+    BlockDriverAIOCB *acb;
+
+    async_ret = NOT_DONE;
+    qemu_aio_wait_start();
+    acb = bdrv_aio_write(bs, sector_num, buf, nb_sectors,
+                         bdrv_rw_em_cb, &async_ret);
+    if (acb == NULL) {
+        qemu_aio_wait_end();
+        return -1;
+    }
+    while (async_ret == NOT_DONE) {
+        qemu_aio_wait();
+    }
+    qemu_aio_wait_end();
+    return async_ret;
+}
+
+void bdrv_init(void)
+{
+    bdrv_register(&bdrv_raw);
+    bdrv_register(&bdrv_host_device);
+#ifndef _WIN32
+    bdrv_register(&bdrv_cow);
+#endif
+    bdrv_register(&bdrv_qcow);
+    bdrv_register(&bdrv_vmdk);
+    bdrv_register(&bdrv_cloop);
+    bdrv_register(&bdrv_dmg);
+    bdrv_register(&bdrv_bochs);
+    bdrv_register(&bdrv_vpc);
+    bdrv_register(&bdrv_vvfat);
+    bdrv_register(&bdrv_qcow2);
+    bdrv_register(&bdrv_parallels);
+}
+
+void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
+                   void *opaque)
+{
+    BlockDriver *drv;
+    BlockDriverAIOCB *acb;
+
+    drv = bs->drv;
+    if (drv->free_aiocb) {
+        acb = drv->free_aiocb;
+        drv->free_aiocb = acb->next;
+    } else {
+        acb = qemu_mallocz(drv->aiocb_size);
+        if (!acb)
+            return NULL;
+    }
+    acb->bs = bs;
+    acb->cb = cb;
+    acb->opaque = opaque;
+    return acb;
+}
+
+void qemu_aio_release(void *p)
+{
+    BlockDriverAIOCB *acb = p;
+    BlockDriver *drv = acb->bs->drv;
+    acb->next = drv->free_aiocb;
+    drv->free_aiocb = acb;
+}
+#endif
+
+/**************************************************************/
+/* removable device support */
+
+/**
+ * Return TRUE if the media is present
+ */
+int bdrv_is_inserted(BlockDriverState *bs)
+{
+    BlockDriver *drv = bs->drv;
+    int ret;
+    if (!drv)
+        return 0;
+    if (!drv->bdrv_is_inserted)
+        return 1;
+    ret = drv->bdrv_is_inserted(bs);
+    return ret;
+}
+
+/**
+ * Return TRUE if the media changed since the last call to this
+ * function. It is currently only used for floppy disks
+ */
+int bdrv_media_changed(BlockDriverState *bs)
+{
+    BlockDriver *drv = bs->drv;
+    int ret;
+
+    if (!drv || !drv->bdrv_media_changed)
+        ret = -ENOTSUP;
+    else
+        ret = drv->bdrv_media_changed(bs);
+    if (ret == -ENOTSUP)
+        ret = bs->media_changed;
+    bs->media_changed = 0;
+    return ret;
+}
+
+/**
+ * If eject_flag is TRUE, eject the media. Otherwise, close the tray
+ */
+void bdrv_eject(BlockDriverState *bs, int eject_flag)
+{
+    BlockDriver *drv = bs->drv;
+    int ret;
+
+    if (!drv || !drv->bdrv_eject) {
+        ret = -ENOTSUP;
+    } else {
+        ret = drv->bdrv_eject(bs, eject_flag);
+    }
+    if (ret == -ENOTSUP) {
+        if (eject_flag)
+            bdrv_close(bs);
+    }
+}
+
+int bdrv_is_locked(BlockDriverState *bs)
+{
+    return bs->locked;
+}
+
+/**
+ * Lock or unlock the media (if it is locked, the user won't be able
+ * to eject it manually).
+ */
+void bdrv_set_locked(BlockDriverState *bs, int locked)
+{
+    BlockDriver *drv = bs->drv;
+
+    bs->locked = locked;
+    if (drv && drv->bdrv_set_locked) {
+        drv->bdrv_set_locked(bs, locked);
+    }
+}
diff -r 092232fa1fbd extras/stubfw/ioemu/block_int.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/ioemu/block_int.h   Thu Nov 15 02:08:10 2007 +0100
@@ -0,0 +1,136 @@
+/*
+ * QEMU System Emulator block driver
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef BLOCK_INT_H
+#define BLOCK_INT_H
+
+#define BLOCK_FLAG_ENCRYPT     1
+#define BLOCK_FLAG_COMPRESS    2
+#define BLOCK_FLAG_COMPAT6     4
+
+struct BlockDriver {
+    const char *format_name;
+    int instance_size;
+    int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
+    int (*bdrv_open)(BlockDriverState *bs, const char *filename, int flags);
+    int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
+                     uint8_t *buf, int nb_sectors);
+    int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
+                      const uint8_t *buf, int nb_sectors);
+    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);
+    int (*bdrv_make_empty)(BlockDriverState *bs);
+    /* aio */
+    BlockDriverAIOCB *(*bdrv_aio_read)(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque);
+    BlockDriverAIOCB *(*bdrv_aio_write)(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque);
+    void (*bdrv_aio_cancel)(BlockDriverAIOCB *acb);
+    int aiocb_size;
+
+    const char *protocol_name;
+    int (*bdrv_pread)(BlockDriverState *bs, int64_t offset,
+                      uint8_t *buf, int count);
+    int (*bdrv_pwrite)(BlockDriverState *bs, int64_t offset,
+                       const uint8_t *buf, int count);
+    int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
+    int64_t (*bdrv_getlength)(BlockDriverState *bs);
+    int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num,
+                                 const uint8_t *buf, int nb_sectors);
+
+    int (*bdrv_snapshot_create)(BlockDriverState *bs,
+                                QEMUSnapshotInfo *sn_info);
+    int (*bdrv_snapshot_goto)(BlockDriverState *bs,
+                              const char *snapshot_id);
+    int (*bdrv_snapshot_delete)(BlockDriverState *bs, const char *snapshot_id);
+    int (*bdrv_snapshot_list)(BlockDriverState *bs,
+                              QEMUSnapshotInfo **psn_info);
+    int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
+
+    /* removable device specific */
+    int (*bdrv_is_inserted)(BlockDriverState *bs);
+    int (*bdrv_media_changed)(BlockDriverState *bs);
+    int (*bdrv_eject)(BlockDriverState *bs, int eject_flag);
+    int (*bdrv_set_locked)(BlockDriverState *bs, int locked);
+
+    BlockDriverAIOCB *free_aiocb;
+    struct BlockDriver *next;
+};
+
+struct BlockDriverState {
+    int64_t total_sectors; /* if we are reading a disk image, give its
+                              size in sectors */
+    int read_only; /* if true, the media is read only */
+    int removable; /* if true, the media can be removed */
+    int locked;    /* if true, the media cannot temporarily be ejected */
+    int encrypted; /* if true, the media is encrypted */
+    /* event callback when inserting/removing */
+    void (*change_cb)(void *opaque);
+    void *change_opaque;
+
+    BlockDriver *drv; /* NULL means no media */
+    void *opaque;
+
+    int boot_sector_enabled;
+    uint8_t boot_sector_data[512];
+
+    char filename[1024];
+    char backing_file[1024]; /* if non zero, the image is a diff of
+                                this file image */
+    int is_temporary;
+    int media_changed;
+
+    BlockDriverState *backing_hd;
+    /* async read/write emulation */
+
+    void *sync_aiocb;
+
+    /* NOTE: the following infos are only hints for real hardware
+       drivers. They are not used by the block driver */
+    int cyls, heads, secs, translation;
+    int type;
+    char device_name[32];
+    BlockDriverState *next;
+};
+
+struct BlockDriverAIOCB {
+    BlockDriverState *bs;
+    BlockDriverCompletionFunc *cb;
+    void *opaque;
+    BlockDriverAIOCB *next;
+};
+
+void get_tmp_filename(char *filename, int size);
+
+void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
+                   void *opaque);
+void qemu_aio_release(void *p);
+
+#endif /* BLOCK_INT_H */
diff -r 092232fa1fbd extras/stubfw/ioemu/cdrom.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/ioemu/cdrom.c       Wed Nov 14 07:02:20 2007 +0100
@@ -0,0 +1,156 @@
+/*
+ * QEMU ATAPI CD-ROM Emulator
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* ??? Most of the ATAPI emulation is still in ide.c.  It should be moved
+   here.  */
+
+#include "vl.h"
+
+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;
+}
+
+/* same toc as bochs. Return -1 if error or the toc length */
+/* XXX: check this */
+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_be32wu((uint32_t *)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_be32wu((uint32_t *)q, nb_sectors);
+        q += 4;
+    }
+    len = q - buf;
+    cpu_to_be16wu((uint16_t *)buf, len - 2);
+    return len;
+}
+
+/* mostly same info as PearPc */
+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_be32wu((uint32_t *)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_be16wu((uint16_t *)buf, len - 2);
+    return len;
+}
+
+
diff -r 092232fa1fbd extras/stubfw/ioemu/ide.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/ioemu/ide.c Mon Nov 19 02:16:07 2007 +0100
@@ -0,0 +1,3709 @@
+/*
+ * QEMU IDE disk and CD-ROM Emulator
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ * Copyright (c) 2006 Openedhand Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+#ifdef IOEMU
+#include "gnttab.h"
+#include "hypervisor.h"
+#endif
+
+/* debug IDE devices */
+//#define DEBUG_IDE
+//#define DEBUG_IDE_ATAPI
+//#define DEBUG_AIO
+#define USE_DMA_CDROM
+
+/* Bits of HD_STATUS */
+#define ERR_STAT               0x01
+#define INDEX_STAT             0x02
+#define ECC_STAT               0x04    /* Corrected error */
+#define DRQ_STAT               0x08
+#define SEEK_STAT              0x10
+#define SRV_STAT               0x10
+#define WRERR_STAT             0x20
+#define READY_STAT             0x40
+#define BUSY_STAT              0x80
+
+/* Bits for HD_ERROR */
+#define MARK_ERR               0x01    /* Bad address mark */
+#define TRK0_ERR               0x02    /* couldn't find track 0 */
+#define ABRT_ERR               0x04    /* Command aborted */
+#define MCR_ERR                        0x08    /* media change request */
+#define ID_ERR                 0x10    /* ID field not found */
+#define MC_ERR                 0x20    /* media changed */
+#define ECC_ERR                        0x40    /* Uncorrectable ECC error */
+#define BBD_ERR                        0x80    /* pre-EIDE meaning:  block 
marked bad */
+#define ICRC_ERR               0x80    /* new meaning:  CRC error during 
transfer */
+
+/* Bits of HD_NSECTOR */
+#define CD                     0x01
+#define IO                     0x02
+#define REL                    0x04
+#define TAG_MASK               0xf8
+
+#define IDE_CMD_RESET           0x04
+#define IDE_CMD_DISABLE_IRQ     0x02
+
+/* ATA/ATAPI Commands pre T13 Spec */
+#define WIN_NOP                                0x00
+/*
+ *     0x01->0x02 Reserved
+ */
+#define CFA_REQ_EXT_ERROR_CODE         0x03 /* CFA Request Extended Error Code 
*/
+/*
+ *     0x04->0x07 Reserved
+ */
+#define WIN_SRST                       0x08 /* ATAPI soft reset command */
+#define WIN_DEVICE_RESET               0x08
+/*
+ *     0x09->0x0F Reserved
+ */
+#define WIN_RECAL                      0x10
+#define WIN_RESTORE                    WIN_RECAL
+/*
+ *     0x10->0x1F Reserved
+ */
+#define WIN_READ                       0x20 /* 28-Bit */
+#define WIN_READ_ONCE                  0x21 /* 28-Bit without retries */
+#define WIN_READ_LONG                  0x22 /* 28-Bit */
+#define WIN_READ_LONG_ONCE             0x23 /* 28-Bit without retries */
+#define WIN_READ_EXT                   0x24 /* 48-Bit */
+#define WIN_READDMA_EXT                        0x25 /* 48-Bit */
+#define WIN_READDMA_QUEUED_EXT         0x26 /* 48-Bit */
+#define WIN_READ_NATIVE_MAX_EXT                0x27 /* 48-Bit */
+/*
+ *     0x28
+ */
+#define WIN_MULTREAD_EXT               0x29 /* 48-Bit */
+/*
+ *     0x2A->0x2F Reserved
+ */
+#define WIN_WRITE                      0x30 /* 28-Bit */
+#define WIN_WRITE_ONCE                 0x31 /* 28-Bit without retries */
+#define WIN_WRITE_LONG                 0x32 /* 28-Bit */
+#define WIN_WRITE_LONG_ONCE            0x33 /* 28-Bit without retries */
+#define WIN_WRITE_EXT                  0x34 /* 48-Bit */
+#define WIN_WRITEDMA_EXT               0x35 /* 48-Bit */
+#define WIN_WRITEDMA_QUEUED_EXT                0x36 /* 48-Bit */
+#define WIN_SET_MAX_EXT                        0x37 /* 48-Bit */
+#define CFA_WRITE_SECT_WO_ERASE                0x38 /* CFA Write Sectors 
without erase */
+#define WIN_MULTWRITE_EXT              0x39 /* 48-Bit */
+/*
+ *     0x3A->0x3B Reserved
+ */
+#define WIN_WRITE_VERIFY               0x3C /* 28-Bit */
+/*
+ *     0x3D->0x3F Reserved
+ */
+#define WIN_VERIFY                     0x40 /* 28-Bit - Read Verify Sectors */
+#define WIN_VERIFY_ONCE                        0x41 /* 28-Bit - without 
retries */
+#define WIN_VERIFY_EXT                 0x42 /* 48-Bit */
+/*
+ *     0x43->0x4F Reserved
+ */
+#define WIN_FORMAT                     0x50
+/*
+ *     0x51->0x5F Reserved
+ */
+#define WIN_INIT                       0x60
+/*
+ *     0x61->0x5F Reserved
+ */
+#define WIN_SEEK                       0x70 /* 0x70-0x7F Reserved */
+#define CFA_TRANSLATE_SECTOR           0x87 /* CFA Translate Sector */
+#define WIN_DIAGNOSE                   0x90
+#define WIN_SPECIFY                    0x91 /* set drive geometry translation 
*/
+#define WIN_DOWNLOAD_MICROCODE         0x92
+#define WIN_STANDBYNOW2                        0x94
+#define CFA_IDLEIMMEDIATE              0x95 /* force drive to become "ready" */
+#define WIN_STANDBY2                   0x96
+#define WIN_SETIDLE2                   0x97
+#define WIN_CHECKPOWERMODE2            0x98
+#define WIN_SLEEPNOW2                  0x99
+/*
+ *     0x9A VENDOR
+ */
+#define WIN_PACKETCMD                  0xA0 /* Send a packet command. */
+#define WIN_PIDENTIFY                  0xA1 /* identify ATAPI device   */
+#define WIN_QUEUED_SERVICE             0xA2
+#define WIN_SMART                      0xB0 /* self-monitoring and reporting */
+#define CFA_ACCESS_METADATA_STORAGE    0xB8
+#define CFA_ERASE_SECTORS              0xC0 /* microdrives implement as NOP */
+#define WIN_MULTREAD                   0xC4 /* read sectors using multiple 
mode*/
+#define WIN_MULTWRITE                  0xC5 /* write sectors using multiple 
mode */
+#define WIN_SETMULT                    0xC6 /* enable/disable multiple mode */
+#define WIN_READDMA_QUEUED             0xC7 /* read sectors using Queued DMA 
transfers */
+#define WIN_READDMA                    0xC8 /* read sectors using DMA 
transfers */
+#define WIN_READDMA_ONCE               0xC9 /* 28-Bit - without retries */
+#define WIN_WRITEDMA                   0xCA /* write sectors using DMA 
transfers */
+#define WIN_WRITEDMA_ONCE              0xCB /* 28-Bit - without retries */
+#define WIN_WRITEDMA_QUEUED            0xCC /* write sectors using Queued DMA 
transfers */
+#define CFA_WRITE_MULTI_WO_ERASE       0xCD /* CFA Write multiple without 
erase */
+#define WIN_GETMEDIASTATUS             0xDA
+#define WIN_ACKMEDIACHANGE             0xDB /* ATA-1, ATA-2 vendor */
+#define WIN_POSTBOOT                   0xDC
+#define WIN_PREBOOT                    0xDD
+#define WIN_DOORLOCK                   0xDE /* lock door on removable drives */
+#define WIN_DOORUNLOCK                 0xDF /* unlock door on removable drives 
*/
+#define WIN_STANDBYNOW1                        0xE0
+#define WIN_IDLEIMMEDIATE              0xE1 /* force drive to become "ready" */
+#define WIN_STANDBY                    0xE2 /* Set device in Standby Mode */
+#define WIN_SETIDLE1                   0xE3
+#define WIN_READ_BUFFER                        0xE4 /* force read only 1 
sector */
+#define WIN_CHECKPOWERMODE1            0xE5
+#define WIN_SLEEPNOW1                  0xE6
+#define WIN_FLUSH_CACHE                        0xE7
+#define WIN_WRITE_BUFFER               0xE8 /* force write only 1 sector */
+#define WIN_WRITE_SAME                 0xE9 /* read ata-2 to use */
+       /* SET_FEATURES 0x22 or 0xDD */
+#define WIN_FLUSH_CACHE_EXT            0xEA /* 48-Bit */
+#define WIN_IDENTIFY                   0xEC /* ask drive to identify itself    
*/
+#define WIN_MEDIAEJECT                 0xED
+#define WIN_IDENTIFY_DMA               0xEE /* same as WIN_IDENTIFY, but DMA */
+#define WIN_SETFEATURES                        0xEF /* set special drive 
features */
+#define EXABYTE_ENABLE_NEST            0xF0
+#define IBM_SENSE_CONDITION            0xF0 /* measure disk temperature */
+#define WIN_SECURITY_SET_PASS          0xF1
+#define WIN_SECURITY_UNLOCK            0xF2
+#define WIN_SECURITY_ERASE_PREPARE     0xF3
+#define WIN_SECURITY_ERASE_UNIT                0xF4
+#define WIN_SECURITY_FREEZE_LOCK       0xF5
+#define CFA_WEAR_LEVEL                 0xF5 /* microdrives implement as NOP */
+#define WIN_SECURITY_DISABLE           0xF6
+#define WIN_READ_NATIVE_MAX            0xF8 /* return the native maximum 
address */
+#define WIN_SET_MAX                    0xF9
+#define DISABLE_SEAGATE                        0xFB
+
+/* set to 1 set disable mult support */
+#define MAX_MULT_SECTORS 16
+
+/* ATAPI defines */
+
+#define ATAPI_PACKET_SIZE 12
+
+/* The generic packet command opcodes for CD/DVD Logical Units,
+ * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
+#define GPCMD_BLANK                        0xa1
+#define GPCMD_CLOSE_TRACK                  0x5b
+#define GPCMD_FLUSH_CACHE                  0x35
+#define GPCMD_FORMAT_UNIT                  0x04
+#define GPCMD_GET_CONFIGURATION                    0x46
+#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a
+#define GPCMD_GET_PERFORMANCE              0xac
+#define GPCMD_INQUIRY                      0x12
+#define GPCMD_LOAD_UNLOAD                  0xa6
+#define GPCMD_MECHANISM_STATUS             0xbd
+#define GPCMD_MODE_SELECT_10               0x55
+#define GPCMD_MODE_SENSE_10                0x5a
+#define GPCMD_PAUSE_RESUME                 0x4b
+#define GPCMD_PLAY_AUDIO_10                0x45
+#define GPCMD_PLAY_AUDIO_MSF               0x47
+#define GPCMD_PLAY_AUDIO_TI                0x48
+#define GPCMD_PLAY_CD                      0xbc
+#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL  0x1e
+#define GPCMD_READ_10                      0x28
+#define GPCMD_READ_12                      0xa8
+#define GPCMD_READ_CDVD_CAPACITY           0x25
+#define GPCMD_READ_CD                      0xbe
+#define GPCMD_READ_CD_MSF                  0xb9
+#define GPCMD_READ_DISC_INFO               0x51
+#define GPCMD_READ_DVD_STRUCTURE           0xad
+#define GPCMD_READ_FORMAT_CAPACITIES       0x23
+#define GPCMD_READ_HEADER                  0x44
+#define GPCMD_READ_TRACK_RZONE_INFO        0x52
+#define GPCMD_READ_SUBCHANNEL              0x42
+#define GPCMD_READ_TOC_PMA_ATIP                    0x43
+#define GPCMD_REPAIR_RZONE_TRACK           0x58
+#define GPCMD_REPORT_KEY                   0xa4
+#define GPCMD_REQUEST_SENSE                0x03
+#define GPCMD_RESERVE_RZONE_TRACK          0x53
+#define GPCMD_SCAN                         0xba
+#define GPCMD_SEEK                         0x2b
+#define GPCMD_SEND_DVD_STRUCTURE           0xad
+#define GPCMD_SEND_EVENT                   0xa2
+#define GPCMD_SEND_KEY                     0xa3
+#define GPCMD_SEND_OPC                     0x54
+#define GPCMD_SET_READ_AHEAD               0xa7
+#define GPCMD_SET_STREAMING                0xb6
+#define GPCMD_START_STOP_UNIT              0x1b
+#define GPCMD_STOP_PLAY_SCAN               0x4e
+#define GPCMD_TEST_UNIT_READY              0x00
+#define GPCMD_VERIFY_10                            0x2f
+#define GPCMD_WRITE_10                     0x2a
+#define GPCMD_WRITE_AND_VERIFY_10          0x2e
+/* This is listed as optional in ATAPI 2.6, but is (curiously)
+ * missing from Mt. Fuji, Table 57.  It _is_ mentioned in Mt. Fuji
+ * Table 377 as an MMC command for SCSi devices though...  Most ATAPI
+ * drives support it. */
+#define GPCMD_SET_SPEED                            0xbb
+/* This seems to be a SCSI specific CD-ROM opcode
+ * to play data at track/index */
+#define GPCMD_PLAYAUDIO_TI                 0x48
+/*
+ * From MS Media Status Notification Support Specification. For
+ * older drives only.
+ */
+#define GPCMD_GET_MEDIA_STATUS             0xda
+#define GPCMD_MODE_SENSE_6                 0x1a
+
+/* Mode page codes for mode sense/set */
+#define GPMODE_R_W_ERROR_PAGE          0x01
+#define GPMODE_WRITE_PARMS_PAGE                0x05
+#define GPMODE_AUDIO_CTL_PAGE          0x0e
+#define GPMODE_POWER_PAGE              0x1a
+#define GPMODE_FAULT_FAIL_PAGE         0x1c
+#define GPMODE_TO_PROTECT_PAGE         0x1d
+#define GPMODE_CAPABILITIES_PAGE       0x2a
+#define GPMODE_ALL_PAGES               0x3f
+/* Not in Mt. Fuji, but in ATAPI 2.6 -- depricated now in favor
+ * of MODE_SENSE_POWER_PAGE */
+#define GPMODE_CDROM_PAGE              0x0d
+
+#define ATAPI_INT_REASON_CD             0x01 /* 0 = data transfer */
+#define ATAPI_INT_REASON_IO             0x02 /* 1 = transfer to the host */
+#define ATAPI_INT_REASON_REL            0x04
+#define ATAPI_INT_REASON_TAG            0xf8
+
+/* same constants as bochs */
+#define ASC_ILLEGAL_OPCODE                   0x20
+#define ASC_LOGICAL_BLOCK_OOR                0x21
+#define ASC_INV_FIELD_IN_CMD_PACKET          0x24
+#define ASC_MEDIUM_NOT_PRESENT               0x3a
+#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED  0x39
+
+#define CFA_NO_ERROR            0x00
+#define CFA_MISC_ERROR          0x09
+#define CFA_INVALID_COMMAND     0x20
+#define CFA_INVALID_ADDRESS     0x21
+#define CFA_ADDRESS_OVERFLOW    0x2f
+
+#define SENSE_NONE            0
+#define SENSE_NOT_READY       2
+#define SENSE_ILLEGAL_REQUEST 5
+#define SENSE_UNIT_ATTENTION  6
+
+struct IDEState;
+
+typedef void EndTransferFunc(struct IDEState *);
+
+/* NOTE: IDEState represents in fact one drive */
+typedef struct IDEState {
+    /* ide config */
+    int is_cdrom;
+    int is_cf;
+    unsigned int cylinders, heads, sectors;
+    int64_t nb_sectors;
+    int mult_sectors;
+    int identify_set;
+    uint16_t identify_data[256];
+    qemu_irq irq;
+    PCIDevice *pci_dev;
+    struct BMDMAState *bmdma;
+    int drive_serial;
+    /* ide regs */
+    uint8_t feature;
+    uint8_t error;
+    uint32_t nsector;
+    uint8_t sector;
+    uint8_t lcyl;
+    uint8_t hcyl;
+    /* other part of tf for lba48 support */
+    uint8_t hob_feature;
+    uint8_t hob_nsector;
+    uint8_t hob_sector;
+    uint8_t hob_lcyl;
+    uint8_t hob_hcyl;
+
+    uint8_t select;
+    uint8_t status;
+
+    /* 0x3f6 command, only meaningful for drive 0 */
+    uint8_t cmd;
+    /* set for lba48 access */
+    uint8_t lba48;
+    /* depends on bit 4 in select, only meaningful for drive 0 */
+    struct IDEState *cur_drive;
+    BlockDriverState *bs;
+    /* ATAPI specific */
+    uint8_t sense_key;
+    uint8_t asc;
+    int packet_transfer_size;
+    int elementary_transfer_size;
+    int io_buffer_index;
+    int lba;
+    int cd_sector_size;
+    int atapi_dma; /* true if dma is requested for the packet cmd */
+    /* ATA DMA state */
+    int io_buffer_size;
+    /* PIO transfer handling */
+    int req_nb_sectors; /* number of sectors per interrupt */
+    EndTransferFunc *end_transfer_func;
+    uint8_t *data_ptr;
+    uint8_t *data_end;
+#ifdef IOEMU
+    uint8_t *io_buffer;
+#else
+    uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4];
+#endif
+#ifdef TARGET_I386
+    QEMUTimer *sector_write_timer; /* only used for win2k install hack */
+#endif
+    uint32_t irq_count; /* counts IRQs when using win2k install hack */
+    /* CF-ATA extended error */
+    uint8_t ext_error;
+    /* CF-ATA metadata storage */
+    uint32_t mdata_size;
+    uint8_t *mdata_storage;
+    int media_changed;
+} IDEState;
+
+#define BM_STATUS_DMAING 0x01
+#define BM_STATUS_ERROR  0x02
+#define BM_STATUS_INT    0x04
+
+#define BM_CMD_START     0x01
+#define BM_CMD_READ      0x08
+
+#define IDE_TYPE_PIIX3   0
+#define IDE_TYPE_CMD646  1
+#define IDE_TYPE_PIIX4   2
+
+/* CMD646 specific */
+#define MRDMODE                0x71
+#define   MRDMODE_INTR_CH0     0x04
+#define   MRDMODE_INTR_CH1     0x08
+#define   MRDMODE_BLK_CH0      0x10
+#define   MRDMODE_BLK_CH1      0x20
+#define UDIDETCR0      0x73
+#define UDIDETCR1      0x7B
+
+typedef struct BMDMAState {
+    uint8_t cmd;
+    uint8_t status;
+    uint32_t addr;
+
+    struct PCIIDEState *pci_dev;
+    /* current transfer state */
+    uint32_t cur_addr;
+    uint32_t cur_prd_last;
+    uint32_t cur_prd_addr;
+    uint32_t cur_prd_len;
+    IDEState *ide_if;
+    BlockDriverCompletionFunc *dma_cb;
+    BlockDriverAIOCB *aiocb;
+} BMDMAState;
+
+typedef struct PCIIDEState {
+    PCIDevice dev;
+    IDEState ide_if[4];
+    BMDMAState bmdma[2];
+    int type; /* see IDE_TYPE_xxx */
+} PCIIDEState;
+
+static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb);
+static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret);
+
+static void padstr(char *str, const char *src, int len)
+{
+    int i, v;
+    for(i = 0; i < len; i++) {
+        if (*src)
+            v = *src++;
+        else
+            v = ' ';
+        *(char *)((long)str ^ 1) = v;
+        str++;
+    }
+}
+
+static void padstr8(uint8_t *buf, int buf_size, const char *src)
+{
+    int i;
+    for(i = 0; i < buf_size; i++) {
+        if (*src)
+            buf[i] = *src++;
+        else
+            buf[i] = ' ';
+    }
+}
+
+static void put_le16(uint16_t *p, unsigned int v)
+{
+    *p = cpu_to_le16(v);
+}
+
+static void ide_identify(IDEState *s)
+{
+    uint16_t *p;
+    unsigned int oldsize;
+    char buf[20];
+
+    if (s->identify_set) {
+       memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
+       return;
+    }
+
+    memset(s->io_buffer, 0, 512);
+    p = (uint16_t *)s->io_buffer;
+    put_le16(p + 0, 0x0040);
+    put_le16(p + 1, s->cylinders);
+    put_le16(p + 3, s->heads);
+    put_le16(p + 4, 512 * s->sectors); /* XXX: retired, remove ? */
+    put_le16(p + 5, 512); /* XXX: retired, remove ? */
+    put_le16(p + 6, s->sectors);
+    snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);
+    padstr((uint8_t *)(p + 10), buf, 20); /* serial number */
+    put_le16(p + 20, 3); /* XXX: retired, remove ? */
+    put_le16(p + 21, 512); /* cache size in sectors */
+    put_le16(p + 22, 4); /* ecc bytes */
+    padstr((uint8_t *)(p + 23), QEMU_VERSION, 8); /* firmware version */
+    padstr((uint8_t *)(p + 27), "QEMU HARDDISK", 40); /* model */
+#if MAX_MULT_SECTORS > 1
+    put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);
+#endif
+    put_le16(p + 48, 1); /* dword I/O */
+    put_le16(p + 49, (1 << 11) | (1 << 9) | (1 << 8)); /* DMA and LBA 
supported */
+    put_le16(p + 51, 0x200); /* PIO transfer cycle */
+    put_le16(p + 52, 0x200); /* DMA transfer cycle */
+    put_le16(p + 53, 1 | (1 << 1) | (1 << 2)); /* words 54-58,64-70,88 are 
valid */
+    put_le16(p + 54, s->cylinders);
+    put_le16(p + 55, s->heads);
+    put_le16(p + 56, s->sectors);
+    oldsize = s->cylinders * s->heads * s->sectors;
+    put_le16(p + 57, oldsize);
+    put_le16(p + 58, oldsize >> 16);
+    if (s->mult_sectors)
+        put_le16(p + 59, 0x100 | s->mult_sectors);
+    put_le16(p + 60, s->nb_sectors);
+    put_le16(p + 61, s->nb_sectors >> 16);
+    put_le16(p + 63, 0x07); /* mdma0-2 supported */
+    put_le16(p + 65, 120);
+    put_le16(p + 66, 120);
+    put_le16(p + 67, 120);
+    put_le16(p + 68, 120);
+    put_le16(p + 80, 0xf0); /* ata3 -> ata6 supported */
+    put_le16(p + 81, 0x16); /* conforms to ata5 */
+    put_le16(p + 82, (1 << 14));
+    /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
+    put_le16(p + 83, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
+    put_le16(p + 84, (1 << 14));
+    put_le16(p + 85, (1 << 14));
+    /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
+    put_le16(p + 86, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
+    put_le16(p + 87, (1 << 14));
+    put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */
+    put_le16(p + 93, 1 | (1 << 14) | 0x2000);
+    put_le16(p + 100, s->nb_sectors);
+    put_le16(p + 101, s->nb_sectors >> 16);
+    put_le16(p + 102, s->nb_sectors >> 32);
+    put_le16(p + 103, s->nb_sectors >> 48);
+
+    memcpy(s->identify_data, p, sizeof(s->identify_data));
+    s->identify_set = 1;
+}
+
+static void ide_atapi_identify(IDEState *s)
+{
+    uint16_t *p;
+    char buf[20];
+
+    if (s->identify_set) {
+       memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
+       return;
+    }
+
+    memset(s->io_buffer, 0, 512);
+    p = (uint16_t *)s->io_buffer;
+    /* Removable CDROM, 50us response, 12 byte packets */
+    put_le16(p + 0, (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0));
+    snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);
+    padstr((uint8_t *)(p + 10), buf, 20); /* serial number */
+    put_le16(p + 20, 3); /* buffer type */
+    put_le16(p + 21, 512); /* cache size in sectors */
+    put_le16(p + 22, 4); /* ecc bytes */
+    padstr((uint8_t *)(p + 23), QEMU_VERSION, 8); /* firmware version */
+    padstr((uint8_t *)(p + 27), "QEMU CD-ROM", 40); /* model */
+    put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */
+#ifdef USE_DMA_CDROM
+    put_le16(p + 49, 1 << 9 | 1 << 8); /* DMA and LBA supported */
+    put_le16(p + 53, 7); /* words 64-70, 54-58, 88 valid */
+    put_le16(p + 63, 7);  /* mdma0-2 supported */
+    put_le16(p + 64, 0x3f); /* PIO modes supported */
+#else
+    put_le16(p + 49, 1 << 9); /* LBA supported, no DMA */
+    put_le16(p + 53, 3); /* words 64-70, 54-58 valid */
+    put_le16(p + 63, 0x103); /* DMA modes XXX: may be incorrect */
+    put_le16(p + 64, 1); /* PIO modes */
+#endif
+    put_le16(p + 65, 0xb4); /* minimum DMA multiword tx cycle time */
+    put_le16(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */
+    put_le16(p + 67, 0x12c); /* minimum PIO cycle time without flow control */
+    put_le16(p + 68, 0xb4); /* minimum PIO cycle time with IORDY flow control 
*/
+
+    put_le16(p + 71, 30); /* in ns */
+    put_le16(p + 72, 30); /* in ns */
+
+    put_le16(p + 80, 0x1e); /* support up to ATA/ATAPI-4 */
+#ifdef USE_DMA_CDROM
+    put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */
+#endif
+    memcpy(s->identify_data, p, sizeof(s->identify_data));
+    s->identify_set = 1;
+}
+
+static void ide_cfata_identify(IDEState *s)
+{
+    uint16_t *p;
+    uint32_t cur_sec;
+    char buf[20];
+
+    p = (uint16_t *) s->identify_data;
+    if (s->identify_set)
+        goto fill_buffer;
+
+    memset(p, 0, sizeof(s->identify_data));
+
+    cur_sec = s->cylinders * s->heads * s->sectors;
+
+    put_le16(p + 0, 0x848a);                   /* CF Storage Card signature */
+    put_le16(p + 1, s->cylinders);             /* Default cylinders */
+    put_le16(p + 3, s->heads);                 /* Default heads */
+    put_le16(p + 6, s->sectors);               /* Default sectors per track */
+    put_le16(p + 7, s->nb_sectors >> 16);      /* Sectors per card */
+    put_le16(p + 8, s->nb_sectors);            /* Sectors per card */
+    snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);
+    padstr((uint8_t *)(p + 10), buf, 20);      /* Serial number in ASCII */
+    put_le16(p + 22, 0x0004);                  /* ECC bytes */
+    padstr((uint8_t *) (p + 23), QEMU_VERSION, 8);     /* Firmware Revision */
+    padstr((uint8_t *) (p + 27), "QEMU MICRODRIVE", 40);/* Model number */
+#if MAX_MULT_SECTORS > 1
+    put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);
+#else
+    put_le16(p + 47, 0x0000);
+#endif
+    put_le16(p + 49, 0x0f00);                  /* Capabilities */
+    put_le16(p + 51, 0x0002);                  /* PIO cycle timing mode */
+    put_le16(p + 52, 0x0001);                  /* DMA cycle timing mode */
+    put_le16(p + 53, 0x0003);                  /* Translation params valid */
+    put_le16(p + 54, s->cylinders);            /* Current cylinders */
+    put_le16(p + 55, s->heads);                        /* Current heads */
+    put_le16(p + 56, s->sectors);              /* Current sectors */
+    put_le16(p + 57, cur_sec);                 /* Current capacity */
+    put_le16(p + 58, cur_sec >> 16);           /* Current capacity */
+    if (s->mult_sectors)                       /* Multiple sector setting */
+        put_le16(p + 59, 0x100 | s->mult_sectors);
+    put_le16(p + 60, s->nb_sectors);           /* Total LBA sectors */
+    put_le16(p + 61, s->nb_sectors >> 16);     /* Total LBA sectors */
+    put_le16(p + 63, 0x0203);                  /* Multiword DMA capability */
+    put_le16(p + 64, 0x0001);                  /* Flow Control PIO support */
+    put_le16(p + 65, 0x0096);                  /* Min. Multiword DMA cycle */
+    put_le16(p + 66, 0x0096);                  /* Rec. Multiword DMA cycle */
+    put_le16(p + 68, 0x00b4);                  /* Min. PIO cycle time */
+    put_le16(p + 82, 0x400c);                  /* Command Set supported */
+    put_le16(p + 83, 0x7068);                  /* Command Set supported */
+    put_le16(p + 84, 0x4000);                  /* Features supported */
+    put_le16(p + 85, 0x000c);                  /* Command Set enabled */
+    put_le16(p + 86, 0x7044);                  /* Command Set enabled */
+    put_le16(p + 87, 0x4000);                  /* Features enabled */
+    put_le16(p + 91, 0x4060);                  /* Current APM level */
+    put_le16(p + 129, 0x0002);                 /* Current features option */
+    put_le16(p + 130, 0x0005);                 /* Reassigned sectors */
+    put_le16(p + 131, 0x0001);                 /* Initial power mode */
+    put_le16(p + 132, 0x0000);                 /* User signature */
+    put_le16(p + 160, 0x8100);                 /* Power requirement */
+    put_le16(p + 161, 0x8001);                 /* CF command set */
+
+    s->identify_set = 1;
+
+fill_buffer:
+    memcpy(s->io_buffer, p, sizeof(s->identify_data));
+}
+
+static void ide_set_signature(IDEState *s)
+{
+    s->select &= 0xf0; /* clear head */
+    /* put signature */
+    s->nsector = 1;
+    s->sector = 1;
+    if (s->is_cdrom) {
+        s->lcyl = 0x14;
+        s->hcyl = 0xeb;
+    } else if (s->bs) {
+        s->lcyl = 0;
+        s->hcyl = 0;
+    } else {
+        s->lcyl = 0xff;
+        s->hcyl = 0xff;
+    }
+}
+
+static inline void ide_abort_command(IDEState *s)
+{
+    s->status = READY_STAT | ERR_STAT;
+    s->error = ABRT_ERR;
+}
+
+static inline void ide_set_irq(IDEState *s)
+{
+    BMDMAState *bm = s->bmdma;
+    if (!(s->cmd & IDE_CMD_DISABLE_IRQ)) {
+        if (bm) {
+            bm->status |= BM_STATUS_INT;
+        }
+        qemu_irq_raise(s->irq);
+    }
+}
+
+/* prepare data transfer and tell what to do after */
+static void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
+                               EndTransferFunc *end_transfer_func)
+{
+    s->end_transfer_func = end_transfer_func;
+    s->data_ptr = buf;
+    s->data_end = buf + size;
+    if (!(s->status & ERR_STAT))
+        s->status |= DRQ_STAT;
+}
+
+static void ide_transfer_stop(IDEState *s)
+{
+    s->end_transfer_func = ide_transfer_stop;
+    s->data_ptr = s->io_buffer;
+    s->data_end = s->io_buffer;
+    s->status &= ~DRQ_STAT;
+}
+
+static int64_t ide_get_sector(IDEState *s)
+{
+    int64_t sector_num;
+    if (s->select & 0x40) {
+        /* lba */
+       if (!s->lba48) {
+           sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) |
+               (s->lcyl << 8) | s->sector;
+       } else {
+           sector_num = ((int64_t)s->hob_hcyl << 40) |
+               ((int64_t) s->hob_lcyl << 32) |
+               ((int64_t) s->hob_sector << 24) |
+               ((int64_t) s->hcyl << 16) |
+               ((int64_t) s->lcyl << 8) | s->sector;
+       }
+    } else {
+        sector_num = ((s->hcyl << 8) | s->lcyl) * s->heads * s->sectors +
+            (s->select & 0x0f) * s->sectors + (s->sector - 1);
+    }
+    return sector_num;
+}
+
+static void ide_set_sector(IDEState *s, uint64_t sector_num)
+{
+    unsigned int cyl, r;
+    if (s->select & 0x40) {
+       if (!s->lba48) {
+            s->select = (s->select & 0xf0) | (sector_num >> 24);
+            s->hcyl = (sector_num >> 16);
+            s->lcyl = (sector_num >> 8);
+            s->sector = (sector_num);
+       } else {
+           s->sector = sector_num;
+           s->lcyl = sector_num >> 8;
+           s->hcyl = sector_num >> 16;
+           s->hob_sector = sector_num >> 24;
+           s->hob_lcyl = sector_num >> 32;
+           s->hob_hcyl = sector_num >> 40;
+       }
+    } else {
+        cyl = sector_num / (s->heads * s->sectors);
+        r = sector_num % (s->heads * s->sectors);
+        s->hcyl = cyl >> 8;
+        s->lcyl = cyl;
+        s->select = (s->select & 0xf0) | ((r / s->sectors) & 0x0f);
+        s->sector = (r % s->sectors) + 1;
+    }
+}
+
+static void ide_sector_read(IDEState *s)
+{
+    int64_t sector_num;
+    int ret, n;
+
+    s->status = READY_STAT | SEEK_STAT;
+    s->error = 0; /* not needed by IDE spec, but needed by Windows */
+    sector_num = ide_get_sector(s);
+    n = s->nsector;
+    if (n == 0) {
+        /* no more sector to read from disk */
+        ide_transfer_stop(s);
+    } else {
+#if defined(DEBUG_IDE)
+        printf("read sector=%Ld\n", sector_num);
+#endif
+        if (n > s->req_nb_sectors)
+            n = s->req_nb_sectors;
+        ret = bdrv_read(s->bs, sector_num, s->io_buffer, n);
+        ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_read);
+        ide_set_irq(s);
+        ide_set_sector(s, sector_num + n);
+        s->nsector -= n;
+    }
+}
+
+/* return 0 if buffer completed */
+static int dma_buf_rw(BMDMAState *bm, int is_write)
+{
+    IDEState *s = bm->ide_if;
+    struct {
+        uint32_t addr;
+        uint32_t size;
+    } prd;
+    int l, len;
+
+    for(;;) {
+        l = s->io_buffer_size - s->io_buffer_index;
+        if (l <= 0)
+            break;
+        if (bm->cur_prd_len == 0) {
+            /* end of table (with a fail safe of one page) */
+            if (bm->cur_prd_last ||
+                (bm->cur_addr - bm->addr) >= 4096)
+                return 0;
+            cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8);
+            bm->cur_addr += 8;
+            prd.addr = le32_to_cpu(prd.addr);
+            prd.size = le32_to_cpu(prd.size);
+            len = prd.size & 0xfffe;
+            if (len == 0)
+                len = 0x10000;
+            bm->cur_prd_len = len;
+            bm->cur_prd_addr = prd.addr;
+            bm->cur_prd_last = (prd.size & 0x80000000);
+        }
+        if (l > bm->cur_prd_len)
+            l = bm->cur_prd_len;
+        if (l > 0) {
+            if (is_write) {
+                cpu_physical_memory_write(bm->cur_prd_addr,
+                                          s->io_buffer + s->io_buffer_index, 
l);
+            } else {
+                cpu_physical_memory_read(bm->cur_prd_addr,
+                                          s->io_buffer + s->io_buffer_index, 
l);
+            }
+            bm->cur_prd_addr += l;
+            bm->cur_prd_len -= l;
+            s->io_buffer_index += l;
+        }
+    }
+    return 1;
+}
+
+/* XXX: handle errors */
+static void ide_read_dma_cb(void *opaque, int ret)
+{
+    BMDMAState *bm = opaque;
+    IDEState *s = bm->ide_if;
+    int n;
+    int64_t sector_num;
+
+    n = s->io_buffer_size >> 9;
+    sector_num = ide_get_sector(s);
+    if (n > 0) {
+        sector_num += n;
+        ide_set_sector(s, sector_num);
+        s->nsector -= n;
+        if (dma_buf_rw(bm, 1) == 0)
+            goto eot;
+    }
+
+    /* end of transfer ? */
+    if (s->nsector == 0) {
+        s->status = READY_STAT | SEEK_STAT;
+        ide_set_irq(s);
+    eot:
+        bm->status &= ~BM_STATUS_DMAING;
+        bm->status |= BM_STATUS_INT;
+        bm->dma_cb = NULL;
+        bm->ide_if = NULL;
+        bm->aiocb = NULL;
+        return;
+    }
+
+    /* launch next transfer */
+    n = s->nsector;
+    if (n > MAX_MULT_SECTORS)
+        n = MAX_MULT_SECTORS;
+    s->io_buffer_index = 0;
+    s->io_buffer_size = n * 512;
+#ifdef DEBUG_AIO
+    printf("aio_read: sector_num=%lld n=%d\n", sector_num, n);
+#endif
+    bm->aiocb = bdrv_aio_read(s->bs, sector_num, s->io_buffer, n,
+                              ide_read_dma_cb, bm);
+}
+
+static void ide_sector_read_dma(IDEState *s)
+{
+    s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;
+    s->io_buffer_index = 0;
+    s->io_buffer_size = 0;
+    ide_dma_start(s, ide_read_dma_cb);
+}
+
+#ifdef TARGET_I386
+static void ide_sector_write_timer_cb(void *opaque)
+{
+    IDEState *s = opaque;
+    ide_set_irq(s);
+}
+#endif
+
+static void ide_sector_write(IDEState *s)
+{
+    int64_t sector_num;
+    int ret, n, n1;
+
+    s->status = READY_STAT | SEEK_STAT;
+    sector_num = ide_get_sector(s);
+#if defined(DEBUG_IDE)
+    printf("write sector=%Ld\n", sector_num);
+#endif
+    n = s->nsector;
+    if (n > s->req_nb_sectors)
+        n = s->req_nb_sectors;
+    ret = bdrv_write(s->bs, sector_num, s->io_buffer, n);
+    s->nsector -= n;
+    if (s->nsector == 0) {
+        /* no more sectors to write */
+        ide_transfer_stop(s);
+    } else {
+        n1 = s->nsector;
+        if (n1 > s->req_nb_sectors)
+            n1 = s->req_nb_sectors;
+        ide_transfer_start(s, s->io_buffer, 512 * n1, ide_sector_write);
+    }
+    ide_set_sector(s, sector_num + n);
+
+#ifdef TARGET_I386
+    if (win2k_install_hack && ((++s->irq_count % 16) == 0)) {
+        /* It seems there is a bug in the Windows 2000 installer HDD
+           IDE driver which fills the disk with empty logs when the
+           IDE write IRQ comes too early. This hack tries to correct
+           that at the expense of slower write performances. Use this
+           option _only_ to install Windows 2000. You must disable it
+           for normal use. */
+        qemu_mod_timer(s->sector_write_timer, 
+                       qemu_get_clock(vm_clock) + (ticks_per_sec / 1000));
+    } else 
+#endif
+    {
+        ide_set_irq(s);
+    }
+}
+
+/* XXX: handle errors */
+static void ide_write_dma_cb(void *opaque, int ret)
+{
+    BMDMAState *bm = opaque;
+    IDEState *s = bm->ide_if;
+    int n;
+    int64_t sector_num;
+
+    n = s->io_buffer_size >> 9;
+    sector_num = ide_get_sector(s);
+    if (n > 0) {
+        sector_num += n;
+        ide_set_sector(s, sector_num);
+        s->nsector -= n;
+    }
+
+    /* end of transfer ? */
+    if (s->nsector == 0) {
+        s->status = READY_STAT | SEEK_STAT;
+        ide_set_irq(s);
+    eot:
+        bm->status &= ~BM_STATUS_DMAING;
+        bm->status |= BM_STATUS_INT;
+        bm->dma_cb = NULL;
+        bm->ide_if = NULL;
+        bm->aiocb = NULL;
+        return;
+    }
+
+    /* launch next transfer */
+    n = s->nsector;
+    if (n > MAX_MULT_SECTORS)
+        n = MAX_MULT_SECTORS;
+    s->io_buffer_index = 0;
+    s->io_buffer_size = n * 512;
+
+    if (dma_buf_rw(bm, 0) == 0)
+        goto eot;
+#ifdef DEBUG_AIO
+    printf("aio_write: sector_num=%lld n=%d\n", sector_num, n);
+#endif
+    bm->aiocb = bdrv_aio_write(s->bs, sector_num, s->io_buffer, n,
+                               ide_write_dma_cb, bm);
+}
+
+static void ide_sector_write_dma(IDEState *s)
+{
+    s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;
+    s->io_buffer_index = 0;
+    s->io_buffer_size = 0;
+    ide_dma_start(s, ide_write_dma_cb);
+}
+
+static void ide_atapi_cmd_ok(IDEState *s)
+{
+    s->error = 0;
+    s->status = READY_STAT;
+    s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
+    ide_set_irq(s);
+}
+
+static void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc)
+{
+#ifdef DEBUG_IDE_ATAPI
+    printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc);
+#endif
+    s->error = sense_key << 4;
+    s->status = READY_STAT | ERR_STAT;
+    s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
+    s->sense_key = sense_key;
+    s->asc = asc;
+    ide_set_irq(s);
+}
+
+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;
+}
+
+static inline int ube16_to_cpu(const uint8_t *buf)
+{
+    return (buf[0] << 8) | buf[1];
+}
+
+static inline int ube32_to_cpu(const uint8_t *buf)
+{
+    return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+}
+
+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 void cd_data_to_raw(uint8_t *buf, int lba)
+{
+    /* sync bytes */
+    buf[0] = 0x00;
+    memset(buf + 1, 0xff, 10);
+    buf[11] = 0x00;
+    buf += 12;
+    /* MSF */
+    lba_to_msf(buf, lba);
+    buf[3] = 0x01; /* mode 1 data */
+    buf += 4;
+    /* data */
+    buf += 2048;
+    /* XXX: ECC not computed */
+    memset(buf, 0, 288);
+}
+
+static int cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf,
+                           int sector_size)
+{
+    int ret;
+
+    switch(sector_size) {
+    case 2048:
+        ret = bdrv_read(bs, (int64_t)lba << 2, buf, 4);
+        break;
+    case 2352:
+        ret = bdrv_read(bs, (int64_t)lba << 2, buf + 16, 4);
+        if (ret < 0)
+            return ret;
+        cd_data_to_raw(buf, lba);
+        break;
+    default:
+        ret = -EIO;
+        break;
+    }
+    return ret;
+}
+
+static void ide_atapi_io_error(IDEState *s, int ret)
+{
+    /* XXX: handle more errors */
+    if (ret == -ENOMEDIUM) {
+        ide_atapi_cmd_error(s, SENSE_NOT_READY,
+                            ASC_MEDIUM_NOT_PRESENT);
+    } else {
+        ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+                            ASC_LOGICAL_BLOCK_OOR);
+    }
+}
+
+/* The whole ATAPI transfer logic is handled in this function */
+static void ide_atapi_cmd_reply_end(IDEState *s)
+{
+    int byte_count_limit, size, ret;
+#ifdef DEBUG_IDE_ATAPI
+    printf("reply: tx_size=%d elem_tx_size=%d index=%d\n",
+           s->packet_transfer_size,
+           s->elementary_transfer_size,
+           s->io_buffer_index);
+#endif
+    if (s->packet_transfer_size <= 0) {
+        /* end of transfer */
+        ide_transfer_stop(s);
+        s->status = READY_STAT;
+        s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | 
ATAPI_INT_REASON_CD;
+        ide_set_irq(s);
+#ifdef DEBUG_IDE_ATAPI
+        printf("status=0x%x\n", s->status);
+#endif
+    } else {
+        /* see if a new sector must be read */
+        if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) {
+            ret = cd_read_sector(s->bs, s->lba, s->io_buffer, 
s->cd_sector_size);
+            if (ret < 0) {
+                ide_transfer_stop(s);
+                ide_atapi_io_error(s, ret);
+                return;
+            }
+            s->lba++;
+            s->io_buffer_index = 0;
+        }
+        if (s->elementary_transfer_size > 0) {
+            /* there are some data left to transmit in this elementary
+               transfer */
+            size = s->cd_sector_size - s->io_buffer_index;
+            if (size > s->elementary_transfer_size)
+                size = s->elementary_transfer_size;
+            ide_transfer_start(s, s->io_buffer + s->io_buffer_index,
+                               size, ide_atapi_cmd_reply_end);
+            s->packet_transfer_size -= size;
+            s->elementary_transfer_size -= size;
+            s->io_buffer_index += size;
+        } else {
+            /* a new transfer is needed */
+            s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO;
+            byte_count_limit = s->lcyl | (s->hcyl << 8);
+#ifdef DEBUG_IDE_ATAPI
+            printf("byte_count_limit=%d\n", byte_count_limit);
+#endif
+            if (byte_count_limit == 0xffff)
+                byte_count_limit--;
+            size = s->packet_transfer_size;
+            if (size > byte_count_limit) {
+                /* byte count limit must be even if this case */
+                if (byte_count_limit & 1)
+                    byte_count_limit--;
+                size = byte_count_limit;
+            }
+            s->lcyl = size;
+            s->hcyl = size >> 8;
+            s->elementary_transfer_size = size;
+            /* we cannot transmit more than one sector at a time */
+            if (s->lba != -1) {
+                if (size > (s->cd_sector_size - s->io_buffer_index))
+                    size = (s->cd_sector_size - s->io_buffer_index);
+            }
+            ide_transfer_start(s, s->io_buffer + s->io_buffer_index,
+                               size, ide_atapi_cmd_reply_end);
+            s->packet_transfer_size -= size;
+            s->elementary_transfer_size -= size;
+            s->io_buffer_index += size;
+            ide_set_irq(s);
+#ifdef DEBUG_IDE_ATAPI
+            printf("status=0x%x\n", s->status);
+#endif
+        }
+    }
+}
+
+/* send a reply of 'size' bytes in s->io_buffer to an ATAPI command */
+static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size)
+{
+    if (size > max_size)
+        size = max_size;
+    s->lba = -1; /* no sector read */
+    s->packet_transfer_size = size;
+    s->io_buffer_size = size;    /* dma: send the reply data as one chunk */
+    s->elementary_transfer_size = 0;
+    s->io_buffer_index = 0;
+
+    if (s->atapi_dma) {
+       s->status = READY_STAT | DRQ_STAT;
+       ide_dma_start(s, ide_atapi_cmd_read_dma_cb);
+    } else {
+       s->status = READY_STAT;
+       ide_atapi_cmd_reply_end(s);
+    }
+}
+
+/* start a CD-CDROM read command */
+static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors,
+                                   int sector_size)
+{
+    s->lba = lba;
+    s->packet_transfer_size = nb_sectors * sector_size;
+    s->elementary_transfer_size = 0;
+    s->io_buffer_index = sector_size;
+    s->cd_sector_size = sector_size;
+
+    s->status = READY_STAT;
+    ide_atapi_cmd_reply_end(s);
+}
+
+/* ATAPI DMA support */
+
+/* XXX: handle read errors */
+static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret)
+{
+    BMDMAState *bm = opaque;
+    IDEState *s = bm->ide_if;
+    int data_offset, n;
+
+    if (ret < 0) {
+        ide_atapi_io_error(s, ret);
+        goto eot;
+    }
+
+    if (s->io_buffer_size > 0) {
+       /*
+        * For a cdrom read sector command (s->lba != -1),
+        * adjust the lba for the next s->io_buffer_size chunk
+        * and dma the current chunk.
+        * For a command != read (s->lba == -1), just transfer
+        * the reply data.
+        */
+       if (s->lba != -1) {
+           if (s->cd_sector_size == 2352) {
+               n = 1;
+               cd_data_to_raw(s->io_buffer, s->lba);
+           } else {
+               n = s->io_buffer_size >> 11;
+           }
+           s->lba += n;
+       }
+        s->packet_transfer_size -= s->io_buffer_size;
+        if (dma_buf_rw(bm, 1) == 0)
+            goto eot;
+    }
+
+    if (s->packet_transfer_size <= 0) {
+        s->status = READY_STAT;
+        s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | 
ATAPI_INT_REASON_CD;
+        ide_set_irq(s);
+    eot:
+        bm->status &= ~BM_STATUS_DMAING;
+        bm->status |= BM_STATUS_INT;
+        bm->dma_cb = NULL;
+        bm->ide_if = NULL;
+        bm->aiocb = NULL;
+        return;
+    }
+
+    s->io_buffer_index = 0;
+    if (s->cd_sector_size == 2352) {
+        n = 1;
+        s->io_buffer_size = s->cd_sector_size;
+        data_offset = 16;
+    } else {
+        n = s->packet_transfer_size >> 11;
+        if (n > (MAX_MULT_SECTORS / 4))
+            n = (MAX_MULT_SECTORS / 4);
+        s->io_buffer_size = n * 2048;
+        data_offset = 0;
+    }
+#ifdef DEBUG_AIO
+    printf("aio_read_cd: lba=%u n=%d\n", s->lba, n);
+#endif
+    bm->aiocb = bdrv_aio_read(s->bs, (int64_t)s->lba << 2,
+                              s->io_buffer + data_offset, n * 4,
+                              ide_atapi_cmd_read_dma_cb, bm);
+    if (!bm->aiocb) {
+        /* Note: media not present is the most likely case */
+        ide_atapi_cmd_error(s, SENSE_NOT_READY,
+                            ASC_MEDIUM_NOT_PRESENT);
+        goto eot;
+    }
+}
+
+/* start a CD-CDROM read command with DMA */
+/* XXX: test if DMA is available */
+static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors,
+                                   int sector_size)
+{
+    s->lba = lba;
+    s->packet_transfer_size = nb_sectors * sector_size;
+    s->io_buffer_index = 0;
+    s->io_buffer_size = 0;
+    s->cd_sector_size = sector_size;
+
+    /* XXX: check if BUSY_STAT should be set */
+    s->status = READY_STAT | DRQ_STAT | BUSY_STAT;
+    ide_dma_start(s, ide_atapi_cmd_read_dma_cb);
+}
+
+static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors,
+                               int sector_size)
+{
+#ifdef DEBUG_IDE_ATAPI
+    printf("read %s: LBA=%d nb_sectors=%d\n", s->atapi_dma ? "dma" : "pio",
+       lba, nb_sectors);
+#endif
+    if (s->atapi_dma) {
+        ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size);
+    } else {
+        ide_atapi_cmd_read_pio(s, lba, nb_sectors, sector_size);
+    }
+}
+
+static void ide_atapi_cmd(IDEState *s)
+{
+    const uint8_t *packet;
+    uint8_t *buf;
+    int max_len;
+
+    packet = s->io_buffer;
+    buf = s->io_buffer;
+#ifdef DEBUG_IDE_ATAPI
+    {
+        int i;
+        printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8));
+        for(i = 0; i < ATAPI_PACKET_SIZE; i++) {
+            printf(" %02x", packet[i]);
+        }
+        printf("\n");
+    }
+#endif
+    switch(s->io_buffer[0]) {
+    case GPCMD_TEST_UNIT_READY:
+        if (bdrv_is_inserted(s->bs)) {
+            ide_atapi_cmd_ok(s);
+        } else {
+            ide_atapi_cmd_error(s, SENSE_NOT_READY,
+                                ASC_MEDIUM_NOT_PRESENT);
+        }
+        break;
+    case GPCMD_MODE_SENSE_6:
+    case GPCMD_MODE_SENSE_10:
+        {
+            int action, code;
+            if (packet[0] == GPCMD_MODE_SENSE_10)
+                max_len = ube16_to_cpu(packet + 7);
+            else
+                max_len = packet[4];
+            action = packet[2] >> 6;
+            code = packet[2] & 0x3f;
+            switch(action) {
+            case 0: /* current values */
+                switch(code) {
+                case 0x01: /* error recovery */
+                    cpu_to_ube16(&buf[0], 16 + 6);
+                    buf[2] = 0x70;
+                    buf[3] = 0;
+                    buf[4] = 0;
+                    buf[5] = 0;
+                    buf[6] = 0;
+                    buf[7] = 0;
+
+                    buf[8] = 0x01;
+                    buf[9] = 0x06;
+                    buf[10] = 0x00;
+                    buf[11] = 0x05;
+                    buf[12] = 0x00;
+                    buf[13] = 0x00;
+                    buf[14] = 0x00;
+                    buf[15] = 0x00;
+                    ide_atapi_cmd_reply(s, 16, max_len);
+                    break;
+                case 0x2a:
+                    cpu_to_ube16(&buf[0], 28 + 6);
+                    buf[2] = 0x70;
+                    buf[3] = 0;
+                    buf[4] = 0;
+                    buf[5] = 0;
+                    buf[6] = 0;
+                    buf[7] = 0;
+
+                    buf[8] = 0x2a;
+                    buf[9] = 0x12;
+                    buf[10] = 0x08;
+                    buf[11] = 0x00;
+
+                    buf[12] = 0x70;
+                    buf[13] = 3 << 5;
+                    buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
+                    if (bdrv_is_locked(s->bs))
+                        buf[6] |= 1 << 1;
+                    buf[15] = 0x00;
+                    cpu_to_ube16(&buf[16], 706);
+                    buf[18] = 0;
+                    buf[19] = 2;
+                    cpu_to_ube16(&buf[20], 512);
+                    cpu_to_ube16(&buf[22], 706);
+                    buf[24] = 0;
+                    buf[25] = 0;
+                    buf[26] = 0;
+                    buf[27] = 0;
+                    ide_atapi_cmd_reply(s, 28, max_len);
+                    break;
+                default:
+                    goto error_cmd;
+                }
+                break;
+            case 1: /* changeable values */
+                goto error_cmd;
+            case 2: /* default values */
+                goto error_cmd;
+            default:
+            case 3: /* saved values */
+                ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+                                    ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
+                break;
+            }
+        }
+        break;
+    case GPCMD_REQUEST_SENSE:
+        max_len = packet[4];
+        memset(buf, 0, 18);
+        buf[0] = 0x70 | (1 << 7);
+        buf[2] = s->sense_key;
+        buf[7] = 10;
+        buf[12] = s->asc;
+        ide_atapi_cmd_reply(s, 18, max_len);
+        break;
+    case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
+        if (bdrv_is_inserted(s->bs)) {
+            bdrv_set_locked(s->bs, packet[4] & 1);
+            ide_atapi_cmd_ok(s);
+        } else {
+            ide_atapi_cmd_error(s, SENSE_NOT_READY,
+                                ASC_MEDIUM_NOT_PRESENT);
+        }
+        break;
+    case GPCMD_READ_10:
+    case GPCMD_READ_12:
+        {
+            int nb_sectors, lba;
+
+            if (packet[0] == GPCMD_READ_10)
+                nb_sectors = ube16_to_cpu(packet + 7);
+            else
+                nb_sectors = ube32_to_cpu(packet + 6);
+            lba = ube32_to_cpu(packet + 2);
+            if (nb_sectors == 0) {
+                ide_atapi_cmd_ok(s);
+                break;
+            }
+            ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
+        }
+        break;
+    case GPCMD_READ_CD:
+        {
+            int nb_sectors, lba, transfer_request;
+
+            nb_sectors = (packet[6] << 16) | (packet[7] << 8) | packet[8];
+            lba = ube32_to_cpu(packet + 2);
+            if (nb_sectors == 0) {
+                ide_atapi_cmd_ok(s);
+                break;
+            }
+            transfer_request = packet[9];
+            switch(transfer_request & 0xf8) {
+            case 0x00:
+                /* nothing */
+                ide_atapi_cmd_ok(s);
+                break;
+            case 0x10:
+                /* normal read */
+                ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
+                break;
+            case 0xf8:
+                /* read all data */
+                ide_atapi_cmd_read(s, lba, nb_sectors, 2352);
+                break;
+            default:
+                ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+                                    ASC_INV_FIELD_IN_CMD_PACKET);
+                break;
+            }
+        }
+        break;
+    case GPCMD_SEEK:
+        {
+            int lba;
+            int64_t total_sectors;
+
+            bdrv_get_geometry(s->bs, &total_sectors);
+            total_sectors >>= 2;
+            if (total_sectors <= 0) {
+                ide_atapi_cmd_error(s, SENSE_NOT_READY,
+                                    ASC_MEDIUM_NOT_PRESENT);
+                break;
+            }
+            lba = ube32_to_cpu(packet + 2);
+            if (lba >= total_sectors) {
+                ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+                                    ASC_LOGICAL_BLOCK_OOR);
+                break;
+            }
+            ide_atapi_cmd_ok(s);
+        }
+        break;
+    case GPCMD_START_STOP_UNIT:
+        {
+            int start, eject;
+            start = packet[4] & 1;
+            eject = (packet[4] >> 1) & 1;
+
+            if (eject && !start) {
+                /* eject the disk */
+                bdrv_eject(s->bs, 1);
+            } else if (eject && start) {
+                /* close the tray */
+                bdrv_eject(s->bs, 0);
+            }
+            ide_atapi_cmd_ok(s);
+        }
+        break;
+    case GPCMD_MECHANISM_STATUS:
+        {
+            max_len = ube16_to_cpu(packet + 8);
+            cpu_to_ube16(buf, 0);
+            /* no current LBA */
+            buf[2] = 0;
+            buf[3] = 0;
+            buf[4] = 0;
+            buf[5] = 1;
+            cpu_to_ube16(buf + 6, 0);
+            ide_atapi_cmd_reply(s, 8, max_len);
+        }
+        break;
+    case GPCMD_READ_TOC_PMA_ATIP:
+        {
+            int format, msf, start_track, len;
+            int64_t total_sectors;
+
+            bdrv_get_geometry(s->bs, &total_sectors);
+            total_sectors >>= 2;
+            if (total_sectors <= 0) {
+                ide_atapi_cmd_error(s, SENSE_NOT_READY,
+                                    ASC_MEDIUM_NOT_PRESENT);
+                break;
+            }
+            max_len = ube16_to_cpu(packet + 7);
+            format = packet[9] >> 6;
+            msf = (packet[1] >> 1) & 1;
+            start_track = packet[6];
+            switch(format) {
+            case 0:
+                len = cdrom_read_toc(total_sectors, buf, msf, start_track);
+                if (len < 0)
+                    goto error_cmd;
+                ide_atapi_cmd_reply(s, len, max_len);
+                break;
+            case 1:
+                /* multi session : only a single session defined */
+                memset(buf, 0, 12);
+                buf[1] = 0x0a;
+                buf[2] = 0x01;
+                buf[3] = 0x01;
+                ide_atapi_cmd_reply(s, 12, max_len);
+                break;
+            case 2:
+                len = cdrom_read_toc_raw(total_sectors, buf, msf, start_track);
+                if (len < 0)
+                    goto error_cmd;
+                ide_atapi_cmd_reply(s, len, max_len);
+                break;
+            default:
+            error_cmd:
+                ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+                                    ASC_INV_FIELD_IN_CMD_PACKET);
+                break;
+            }
+        }
+        break;
+    case GPCMD_READ_CDVD_CAPACITY:
+        {
+            int64_t total_sectors;
+
+            bdrv_get_geometry(s->bs, &total_sectors);
+            total_sectors >>= 2;
+            if (total_sectors <= 0) {
+                ide_atapi_cmd_error(s, SENSE_NOT_READY,
+                                    ASC_MEDIUM_NOT_PRESENT);
+                break;
+            }
+            /* NOTE: it is really the number of sectors minus 1 */
+            cpu_to_ube32(buf, total_sectors - 1);
+            cpu_to_ube32(buf + 4, 2048);
+            ide_atapi_cmd_reply(s, 8, 8);
+        }
+        break;
+    case GPCMD_READ_DVD_STRUCTURE:
+        {
+            int media = packet[1];
+            int layer = packet[6];
+            int format = packet[2];
+            int64_t total_sectors;
+
+            if (media != 0 || layer != 0)
+            {
+                ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+                                    ASC_INV_FIELD_IN_CMD_PACKET);
+            }
+
+            switch (format) {
+                case 0:
+                    bdrv_get_geometry(s->bs, &total_sectors);
+                    total_sectors >>= 2;
+
+                    memset(buf, 0, 2052);
+
+                    buf[4] = 1;   // DVD-ROM, part version 1
+                    buf[5] = 0xf; // 120mm disc, maximum rate unspecified
+                    buf[6] = 0;   // one layer, embossed data
+                    buf[7] = 0;
+
+                    cpu_to_ube32(buf + 8, 0);
+                    cpu_to_ube32(buf + 12, total_sectors - 1);
+                    cpu_to_ube32(buf + 16, total_sectors - 1);
+
+                    cpu_to_be16wu((uint16_t *)buf, 2048 + 4);
+
+                    ide_atapi_cmd_reply(s, 2048 + 3, 2048 + 4);
+                    break;
+
+                default:
+                    ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+                                        ASC_INV_FIELD_IN_CMD_PACKET);
+                    break;
+            }
+        }
+        break;
+    case GPCMD_SET_SPEED:
+        ide_atapi_cmd_ok(s);
+        break;
+    case GPCMD_INQUIRY:
+        max_len = packet[4];
+        buf[0] = 0x05; /* CD-ROM */
+        buf[1] = 0x80; /* removable */
+        buf[2] = 0x00; /* ISO */
+        buf[3] = 0x21; /* ATAPI-2 (XXX: put ATAPI-4 ?) */
+        buf[4] = 31; /* additional length */
+        buf[5] = 0; /* reserved */
+        buf[6] = 0; /* reserved */
+        buf[7] = 0; /* reserved */
+        padstr8(buf + 8, 8, "QEMU");
+        padstr8(buf + 16, 16, "QEMU CD-ROM");
+        padstr8(buf + 32, 4, QEMU_VERSION);
+        ide_atapi_cmd_reply(s, 36, max_len);
+        break;
+    case GPCMD_GET_CONFIGURATION:
+        {
+            int64_t total_sectors;
+
+            /* only feature 0 is supported */
+            if (packet[2] != 0 || packet[3] != 0) {
+                ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+                                    ASC_INV_FIELD_IN_CMD_PACKET);
+                break;
+            }
+            memset(buf, 0, 32);
+            bdrv_get_geometry(s->bs, &total_sectors);
+            buf[3] = 16;
+            buf[7] = total_sectors <= 1433600 ? 0x08 : 0x10; /* current 
profile */
+            buf[10] = 0x10 | 0x1;
+            buf[11] = 0x08; /* size of profile list */
+            buf[13] = 0x10; /* DVD-ROM profile */
+            buf[14] = buf[7] == 0x10; /* (in)active */
+            buf[17] = 0x08; /* CD-ROM profile */
+            buf[18] = buf[7] == 0x08; /* (in)active */
+            ide_atapi_cmd_reply(s, 32, 32);
+            break;
+        }
+    default:
+        ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+                            ASC_ILLEGAL_OPCODE);
+        break;
+    }
+}
+
+static void ide_cfata_metadata_inquiry(IDEState *s)
+{
+    uint16_t *p;
+    uint32_t spd;
+
+    p = (uint16_t *) s->io_buffer;
+    memset(p, 0, 0x200);
+    spd = ((s->mdata_size - 1) >> 9) + 1;
+
+    put_le16(p + 0, 0x0001);                   /* Data format revision */
+    put_le16(p + 1, 0x0000);                   /* Media property: silicon */
+    put_le16(p + 2, s->media_changed);         /* Media status */
+    put_le16(p + 3, s->mdata_size & 0xffff);   /* Capacity in bytes (low) */
+    put_le16(p + 4, s->mdata_size >> 16);      /* Capacity in bytes (high) */
+    put_le16(p + 5, spd & 0xffff);             /* Sectors per device (low) */
+    put_le16(p + 6, spd >> 16);                        /* Sectors per device 
(high) */
+}
+
+static void ide_cfata_metadata_read(IDEState *s)
+{
+    uint16_t *p;
+
+    if (((s->hcyl << 16) | s->lcyl) << 9 > s->mdata_size + 2) {
+        s->status = ERR_STAT;
+        s->error = ABRT_ERR;
+        return;
+    }
+
+    p = (uint16_t *) s->io_buffer;
+    memset(p, 0, 0x200);
+
+    put_le16(p + 0, s->media_changed);         /* Media status */
+    memcpy(p + 1, s->mdata_storage + (((s->hcyl << 16) | s->lcyl) << 9),
+                    MIN(MIN(s->mdata_size - (((s->hcyl << 16) | s->lcyl) << 9),
+                                    s->nsector << 9), 0x200 - 2));
+}
+
+static void ide_cfata_metadata_write(IDEState *s)
+{
+    if (((s->hcyl << 16) | s->lcyl) << 9 > s->mdata_size + 2) {
+        s->status = ERR_STAT;
+        s->error = ABRT_ERR;
+        return;
+    }
+
+    s->media_changed = 0;
+
+    memcpy(s->mdata_storage + (((s->hcyl << 16) | s->lcyl) << 9),
+                    s->io_buffer + 2,
+                    MIN(MIN(s->mdata_size - (((s->hcyl << 16) | s->lcyl) << 9),
+                                    s->nsector << 9), 0x200 - 2));
+}
+
+/* called when the inserted state of the media has changed */
+static void cdrom_change_cb(void *opaque)
+{
+    IDEState *s = opaque;
+    int64_t nb_sectors;
+
+    /* XXX: send interrupt too */
+    bdrv_get_geometry(s->bs, &nb_sectors);
+    s->nb_sectors = nb_sectors;
+}
+
+static void ide_cmd_lba48_transform(IDEState *s, int lba48)
+{
+    s->lba48 = lba48;
+
+    /* handle the 'magic' 0 nsector count conversion here. to avoid
+     * fiddling with the rest of the read logic, we just store the
+     * full sector count in ->nsector and ignore ->hob_nsector from now
+     */
+    if (!s->lba48) {
+       if (!s->nsector)
+           s->nsector = 256;
+    } else {
+       if (!s->nsector && !s->hob_nsector)
+           s->nsector = 65536;
+       else {
+           int lo = s->nsector;
+           int hi = s->hob_nsector;
+
+           s->nsector = (hi << 8) | lo;
+       }
+    }
+}
+
+static void ide_clear_hob(IDEState *ide_if)
+{
+    /* any write clears HOB high bit of device control register */
+    ide_if[0].select &= ~(1 << 7);
+    ide_if[1].select &= ~(1 << 7);
+}
+
+static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    IDEState *ide_if = opaque;
+    IDEState *s;
+    int unit, n;
+    int lba48 = 0;
+
+#ifdef DEBUG_IDE
+    printf("IDE: write addr=0x%x val=0x%02x\n", addr, val);
+#endif
+
+    addr &= 7;
+    switch(addr) {
+    case 0:
+        break;
+    case 1:
+       ide_clear_hob(ide_if);
+        /* NOTE: data is written to the two drives */
+       ide_if[0].hob_feature = ide_if[0].feature;
+       ide_if[1].hob_feature = ide_if[1].feature;
+        ide_if[0].feature = val;
+        ide_if[1].feature = val;
+        break;
+    case 2:
+       ide_clear_hob(ide_if);
+       ide_if[0].hob_nsector = ide_if[0].nsector;
+       ide_if[1].hob_nsector = ide_if[1].nsector;
+        ide_if[0].nsector = val;
+        ide_if[1].nsector = val;
+        break;
+    case 3:
+       ide_clear_hob(ide_if);
+       ide_if[0].hob_sector = ide_if[0].sector;
+       ide_if[1].hob_sector = ide_if[1].sector;
+        ide_if[0].sector = val;
+        ide_if[1].sector = val;
+        break;
+    case 4:
+       ide_clear_hob(ide_if);
+       ide_if[0].hob_lcyl = ide_if[0].lcyl;
+       ide_if[1].hob_lcyl = ide_if[1].lcyl;
+        ide_if[0].lcyl = val;
+        ide_if[1].lcyl = val;
+        break;
+    case 5:
+       ide_clear_hob(ide_if);
+       ide_if[0].hob_hcyl = ide_if[0].hcyl;
+       ide_if[1].hob_hcyl = ide_if[1].hcyl;
+        ide_if[0].hcyl = val;
+        ide_if[1].hcyl = val;
+        break;
+    case 6:
+       /* FIXME: HOB readback uses bit 7 */
+        ide_if[0].select = (val & ~0x10) | 0xa0;
+        ide_if[1].select = (val | 0x10) | 0xa0;
+        /* select drive */
+        unit = (val >> 4) & 1;
+        s = ide_if + unit;
+        ide_if->cur_drive = s;
+        break;
+    default:
+    case 7:
+        /* command */
+#if defined(DEBUG_IDE)
+        printf("ide: CMD=%02x\n", val);
+#endif
+        s = ide_if->cur_drive;
+        /* ignore commands to non existant slave */
+        if (s != ide_if && !s->bs)
+            break;
+
+        switch(val) {
+        case WIN_IDENTIFY:
+            if (s->bs && !s->is_cdrom) {
+                if (!s->is_cf)
+                    ide_identify(s);
+                else
+                    ide_cfata_identify(s);
+                s->status = READY_STAT | SEEK_STAT;
+                ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);
+            } else {
+                if (s->is_cdrom) {
+                    ide_set_signature(s);
+                }
+                ide_abort_command(s);
+            }
+            ide_set_irq(s);
+            break;
+        case WIN_SPECIFY:
+        case WIN_RECAL:
+            s->error = 0;
+            s->status = READY_STAT | SEEK_STAT;
+            ide_set_irq(s);
+            break;
+        case WIN_SETMULT:
+            if (s->is_cf && s->nsector == 0) {
+                /* Disable Read and Write Multiple */
+                s->mult_sectors = 0;
+                s->status = READY_STAT;
+            } else if ((s->nsector & 0xff) != 0 &&
+                ((s->nsector & 0xff) > MAX_MULT_SECTORS ||
+                 (s->nsector & (s->nsector - 1)) != 0)) {
+                ide_abort_command(s);
+            } else {
+                s->mult_sectors = s->nsector & 0xff;
+                s->status = READY_STAT;
+            }
+            ide_set_irq(s);
+            break;
+        case WIN_VERIFY_EXT:
+           lba48 = 1;
+        case WIN_VERIFY:
+        case WIN_VERIFY_ONCE:
+            /* do sector number check ? */
+           ide_cmd_lba48_transform(s, lba48);
+            s->status = READY_STAT;
+            ide_set_irq(s);
+            break;
+       case WIN_READ_EXT:
+           lba48 = 1;
+        case WIN_READ:
+        case WIN_READ_ONCE:
+            if (!s->bs)
+                goto abort_cmd;
+           ide_cmd_lba48_transform(s, lba48);
+            s->req_nb_sectors = 1;
+            ide_sector_read(s);
+            break;
+       case WIN_WRITE_EXT:
+           lba48 = 1;
+        case WIN_WRITE:
+        case WIN_WRITE_ONCE:
+        case CFA_WRITE_SECT_WO_ERASE:
+        case WIN_WRITE_VERIFY:
+           ide_cmd_lba48_transform(s, lba48);
+            s->error = 0;
+            s->status = SEEK_STAT | READY_STAT;
+            s->req_nb_sectors = 1;
+            ide_transfer_start(s, s->io_buffer, 512, ide_sector_write);
+            s->media_changed = 1;
+            break;
+       case WIN_MULTREAD_EXT:
+           lba48 = 1;
+        case WIN_MULTREAD:
+            if (!s->mult_sectors)
+                goto abort_cmd;
+           ide_cmd_lba48_transform(s, lba48);
+            s->req_nb_sectors = s->mult_sectors;
+            ide_sector_read(s);
+            break;
+        case WIN_MULTWRITE_EXT:
+           lba48 = 1;
+        case WIN_MULTWRITE:
+        case CFA_WRITE_MULTI_WO_ERASE:
+            if (!s->mult_sectors)
+                goto abort_cmd;
+           ide_cmd_lba48_transform(s, lba48);
+            s->error = 0;
+            s->status = SEEK_STAT | READY_STAT;
+            s->req_nb_sectors = s->mult_sectors;
+            n = s->nsector;
+            if (n > s->req_nb_sectors)
+                n = s->req_nb_sectors;
+            ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write);
+            s->media_changed = 1;
+            break;
+       case WIN_READDMA_EXT:
+           lba48 = 1;
+        case WIN_READDMA:
+        case WIN_READDMA_ONCE:
+            if (!s->bs)
+                goto abort_cmd;
+           ide_cmd_lba48_transform(s, lba48);
+            ide_sector_read_dma(s);
+            break;
+       case WIN_WRITEDMA_EXT:
+           lba48 = 1;
+        case WIN_WRITEDMA:
+        case WIN_WRITEDMA_ONCE:
+            if (!s->bs)
+                goto abort_cmd;
+           ide_cmd_lba48_transform(s, lba48);
+            ide_sector_write_dma(s);
+            s->media_changed = 1;
+            break;
+        case WIN_READ_NATIVE_MAX_EXT:
+           lba48 = 1;
+        case WIN_READ_NATIVE_MAX:
+           ide_cmd_lba48_transform(s, lba48);
+            ide_set_sector(s, s->nb_sectors - 1);
+            s->status = READY_STAT;
+            ide_set_irq(s);
+            break;
+        case WIN_CHECKPOWERMODE1:
+        case WIN_CHECKPOWERMODE2:
+            s->nsector = 0xff; /* device active or idle */
+            s->status = READY_STAT;
+            ide_set_irq(s);
+            break;
+        case WIN_SETFEATURES:
+            if (!s->bs)
+                goto abort_cmd;
+            /* XXX: valid for CDROM ? */
+            switch(s->feature) {
+            case 0xcc: /* reverting to power-on defaults enable */
+            case 0x66: /* reverting to power-on defaults disable */
+            case 0x02: /* write cache enable */
+            case 0x82: /* write cache disable */
+            case 0xaa: /* read look-ahead enable */
+            case 0x55: /* read look-ahead disable */
+            case 0x05: /* set advanced power management mode */
+            case 0x85: /* disable advanced power management mode */
+            case 0x69: /* NOP */
+            case 0x67: /* NOP */
+            case 0x96: /* NOP */
+            case 0x9a: /* NOP */
+            case 0x42: /* enable Automatic Acoustic Mode */
+            case 0xc2: /* disable Automatic Acoustic Mode */
+                s->status = READY_STAT | SEEK_STAT;
+                ide_set_irq(s);
+                break;
+            case 0x03: { /* set transfer mode */
+               uint8_t val = s->nsector & 0x07;
+
+               switch (s->nsector >> 3) {
+                   case 0x00: /* pio default */
+                   case 0x01: /* pio mode */
+                       put_le16(s->identify_data + 63,0x07);
+                       put_le16(s->identify_data + 88,0x3f);
+                       break;
+                   case 0x04: /* mdma mode */
+                       put_le16(s->identify_data + 63,0x07 | (1 << (val + 8)));
+                       put_le16(s->identify_data + 88,0x3f);
+                       break;
+                   case 0x08: /* udma mode */
+                       put_le16(s->identify_data + 63,0x07);
+                       put_le16(s->identify_data + 88,0x3f | (1 << (val + 8)));
+                       break;
+                   default:
+                       goto abort_cmd;
+               }
+                s->status = READY_STAT | SEEK_STAT;
+                ide_set_irq(s);
+                break;
+           }
+            default:
+                goto abort_cmd;
+            }
+            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_STANDBY:
+        case WIN_STANDBY2:
+        case WIN_STANDBYNOW1:
+        case WIN_STANDBYNOW2:
+        case WIN_IDLEIMMEDIATE:
+        case CFA_IDLEIMMEDIATE:
+        case WIN_SETIDLE1:
+        case WIN_SETIDLE2:
+        case WIN_SLEEPNOW1:
+        case WIN_SLEEPNOW2:
+            s->status = READY_STAT;
+            ide_set_irq(s);
+            break;
+            /* ATAPI commands */
+        case WIN_PIDENTIFY:
+            if (s->is_cdrom) {
+                ide_atapi_identify(s);
+                s->status = READY_STAT | SEEK_STAT;
+                ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);
+            } else {
+                ide_abort_command(s);
+            }
+            ide_set_irq(s);
+            break;
+        case WIN_DIAGNOSE:
+            ide_set_signature(s);
+            s->status = 0x00; /* NOTE: READY is _not_ set */
+            s->error = 0x01;
+            break;
+        case WIN_SRST:
+            if (!s->is_cdrom)
+                goto abort_cmd;
+            ide_set_signature(s);
+            s->status = 0x00; /* NOTE: READY is _not_ set */
+            s->error = 0x01;
+            break;
+        case WIN_PACKETCMD:
+            if (!s->is_cdrom)
+                goto abort_cmd;
+            /* overlapping commands not supported */
+            if (s->feature & 0x02)
+                goto abort_cmd;
+            s->status = READY_STAT;
+            s->atapi_dma = s->feature & 1;
+            s->nsector = 1;
+            ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE,
+                               ide_atapi_cmd);
+            break;
+        /* CF-ATA commands */
+        case CFA_REQ_EXT_ERROR_CODE:
+            if (!s->is_cf)
+                goto abort_cmd;
+            s->error = 0x09;    /* miscellaneous error */
+            s->status = READY_STAT;
+            ide_set_irq(s);
+            break;
+        case CFA_ERASE_SECTORS:
+        case CFA_WEAR_LEVEL:
+            if (!s->is_cf)
+                goto abort_cmd;
+            if (val == CFA_WEAR_LEVEL)
+                s->nsector = 0;
+            if (val == CFA_ERASE_SECTORS)
+                s->media_changed = 1;
+            s->error = 0x00;
+            s->status = READY_STAT;
+            ide_set_irq(s);
+            break;
+        case CFA_TRANSLATE_SECTOR:
+            if (!s->is_cf)
+                goto abort_cmd;
+            s->error = 0x00;
+            s->status = READY_STAT;
+            memset(s->io_buffer, 0, 0x200);
+            s->io_buffer[0x00] = s->hcyl;                      /* Cyl MSB */
+            s->io_buffer[0x01] = s->lcyl;                      /* Cyl LSB */
+            s->io_buffer[0x02] = s->select;                    /* Head */
+            s->io_buffer[0x03] = s->sector;                    /* Sector */
+            s->io_buffer[0x04] = ide_get_sector(s) >> 16;      /* LBA MSB */
+            s->io_buffer[0x05] = ide_get_sector(s) >> 8;       /* LBA */
+            s->io_buffer[0x06] = ide_get_sector(s) >> 0;       /* LBA LSB */
+            s->io_buffer[0x13] = 0x00;                         /* Erase flag */
+            s->io_buffer[0x18] = 0x00;                         /* Hot count */
+            s->io_buffer[0x19] = 0x00;                         /* Hot count */
+            s->io_buffer[0x1a] = 0x01;                         /* Hot count */
+            ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
+            ide_set_irq(s);
+            break;
+        case CFA_ACCESS_METADATA_STORAGE:
+            if (!s->is_cf)
+                goto abort_cmd;
+            switch (s->feature) {
+            case 0x02: /* Inquiry Metadata Storage */
+                ide_cfata_metadata_inquiry(s);
+                break;
+            case 0x03: /* Read Metadata Storage */
+                ide_cfata_metadata_read(s);
+                break;
+            case 0x04: /* Write Metadata Storage */
+                ide_cfata_metadata_write(s);
+                break;
+            default:
+                goto abort_cmd;
+            }
+            ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
+            s->status = 0x00; /* NOTE: READY is _not_ set */
+            ide_set_irq(s);
+            break;
+        case IBM_SENSE_CONDITION:
+            if (!s->is_cf)
+                goto abort_cmd;
+            switch (s->feature) {
+            case 0x01:  /* sense temperature in device */
+                s->nsector = 0x50;      /* +20 C */
+                break;
+            default:
+                goto abort_cmd;
+            }
+            s->status = READY_STAT;
+            ide_set_irq(s);
+            break;
+        default:
+        abort_cmd:
+            ide_abort_command(s);
+            ide_set_irq(s);
+            break;
+        }
+    }
+}
+
+static uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
+{
+    IDEState *ide_if = opaque;
+    IDEState *s = ide_if->cur_drive;
+    uint32_t addr;
+    int ret, hob;
+
+    addr = addr1 & 7;
+    /* FIXME: HOB readback uses bit 7, but it's always set right now */
+    //hob = s->select & (1 << 7);
+    hob = 0;
+    switch(addr) {
+    case 0:
+        ret = 0xff;
+        break;
+    case 1:
+        if (!ide_if[0].bs && !ide_if[1].bs)
+            ret = 0;
+        else if (!hob)
+            ret = s->error;
+       else
+           ret = s->hob_feature;
+        break;
+    case 2:
+        if (!ide_if[0].bs && !ide_if[1].bs)
+            ret = 0;
+        else if (!hob)
+            ret = s->nsector & 0xff;
+       else
+           ret = s->hob_nsector;
+        break;
+    case 3:
+        if (!ide_if[0].bs && !ide_if[1].bs)
+            ret = 0;
+        else if (!hob)
+            ret = s->sector;
+       else
+           ret = s->hob_sector;
+        break;
+    case 4:
+        if (!ide_if[0].bs && !ide_if[1].bs)
+            ret = 0;
+        else if (!hob)
+            ret = s->lcyl;
+       else
+           ret = s->hob_lcyl;
+        break;
+    case 5:
+        if (!ide_if[0].bs && !ide_if[1].bs)
+            ret = 0;
+        else if (!hob)
+            ret = s->hcyl;
+       else
+           ret = s->hob_hcyl;
+        break;
+    case 6:
+        if (!ide_if[0].bs && !ide_if[1].bs)
+            ret = 0;
+        else
+            ret = s->select;
+        break;
+    default:
+    case 7:
+        if ((!ide_if[0].bs && !ide_if[1].bs) ||
+            (s != ide_if && !s->bs))
+            ret = 0;
+        else
+            ret = s->status;
+        qemu_irq_lower(s->irq);
+        break;
+    }
+#ifdef DEBUG_IDE
+    printf("ide: read addr=0x%x val=%02x\n", addr1, ret);
+#endif
+    return ret;
+}
+
+static uint32_t ide_status_read(void *opaque, uint32_t addr)
+{
+    IDEState *ide_if = opaque;
+    IDEState *s = ide_if->cur_drive;
+    int ret;
+
+    if ((!ide_if[0].bs && !ide_if[1].bs) ||
+        (s != ide_if && !s->bs))
+        ret = 0;
+    else
+        ret = s->status;
+#ifdef DEBUG_IDE
+    printf("ide: read status addr=0x%x val=%02x\n", addr, ret);
+#endif
+    return ret;
+}
+
+static void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    IDEState *ide_if = opaque;
+    IDEState *s;
+    int i;
+
+#ifdef DEBUG_IDE
+    printf("ide: write control addr=0x%x val=%02x\n", addr, val);
+#endif
+    /* common for both drives */
+    if (!(ide_if[0].cmd & IDE_CMD_RESET) &&
+        (val & IDE_CMD_RESET)) {
+        /* reset low to high */
+        for(i = 0;i < 2; i++) {
+            s = &ide_if[i];
+            s->status = BUSY_STAT | SEEK_STAT;
+            s->error = 0x01;
+        }
+    } else if ((ide_if[0].cmd & IDE_CMD_RESET) &&
+               !(val & IDE_CMD_RESET)) {
+        /* high to low */
+        for(i = 0;i < 2; i++) {
+            s = &ide_if[i];
+            if (s->is_cdrom)
+                s->status = 0x00; /* NOTE: READY is _not_ set */
+            else
+                s->status = READY_STAT | SEEK_STAT;
+            ide_set_signature(s);
+        }
+    }
+
+    ide_if[0].cmd = val;
+    ide_if[1].cmd = val;
+}
+
+static void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
+{
+    IDEState *s = ((IDEState *)opaque)->cur_drive;
+    uint8_t *p;
+
+    p = s->data_ptr;
+    *(uint16_t *)p = le16_to_cpu(val);
+    p += 2;
+    s->data_ptr = p;
+    if (p >= s->data_end)
+        s->end_transfer_func(s);
+}
+
+static uint32_t ide_data_readw(void *opaque, uint32_t addr)
+{
+    IDEState *s = ((IDEState *)opaque)->cur_drive;
+    uint8_t *p;
+    int ret;
+    p = s->data_ptr;
+    ret = cpu_to_le16(*(uint16_t *)p);
+    p += 2;
+    s->data_ptr = p;
+    if (p >= s->data_end)
+        s->end_transfer_func(s);
+    return ret;
+}
+
+static void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
+{
+    IDEState *s = ((IDEState *)opaque)->cur_drive;
+    uint8_t *p;
+
+    p = s->data_ptr;
+    *(uint32_t *)p = le32_to_cpu(val);
+    p += 4;
+    s->data_ptr = p;
+    if (p >= s->data_end)
+        s->end_transfer_func(s);
+}
+
+static uint32_t ide_data_readl(void *opaque, uint32_t addr)
+{
+    IDEState *s = ((IDEState *)opaque)->cur_drive;
+    uint8_t *p;
+    int ret;
+
+    p = s->data_ptr;
+    ret = cpu_to_le32(*(uint32_t *)p);
+    p += 4;
+    s->data_ptr = p;
+    if (p >= s->data_end)
+        s->end_transfer_func(s);
+    return ret;
+}
+
+static void ide_dummy_transfer_stop(IDEState *s)
+{
+    s->data_ptr = s->io_buffer;
+    s->data_end = s->io_buffer;
+    s->io_buffer[0] = 0xff;
+    s->io_buffer[1] = 0xff;
+    s->io_buffer[2] = 0xff;
+    s->io_buffer[3] = 0xff;
+}
+
+static void ide_reset(IDEState *s)
+{
+    if (s->is_cf)
+        s->mult_sectors = 0;
+    else
+        s->mult_sectors = MAX_MULT_SECTORS;
+    s->cur_drive = s;
+    s->select = 0xa0;
+    s->status = READY_STAT;
+    ide_set_signature(s);
+    /* init the transfer handler so that 0xffff is returned on data
+       accesses */
+    s->end_transfer_func = ide_dummy_transfer_stop;
+    ide_dummy_transfer_stop(s);
+    s->media_changed = 0;
+}
+
+struct partition {
+       uint8_t boot_ind;               /* 0x80 - active */
+       uint8_t head;           /* starting head */
+       uint8_t sector;         /* starting sector */
+       uint8_t cyl;            /* starting cylinder */
+       uint8_t sys_ind;                /* What partition type */
+       uint8_t end_head;               /* end head */
+       uint8_t end_sector;     /* end sector */
+       uint8_t end_cyl;                /* end cylinder */
+       uint32_t start_sect;    /* starting sector counting from 0 */
+       uint32_t nr_sects;              /* nr of sectors in partition */
+} __attribute__((packed));
+
+/* try to guess the disk logical geometry from the MSDOS partition table. 
Return 0 if OK, -1 if could not guess */
+static int guess_disk_lchs(IDEState *s,
+                           int *pcylinders, int *pheads, int *psectors)
+{
+#ifdef IOEMU
+    uint8_t *buf = s->io_buffer;
+#else
+    uint8_t buf[512];
+#endif
+    int ret, i, heads, sectors, cylinders;
+    struct partition *p;
+    uint32_t nr_sects;
+
+    ret = bdrv_read(s->bs, 0, buf, 1);
+    if (ret < 0)
+        return -1;
+    /* test msdos magic */
+    if (buf[510] != 0x55 || buf[511] != 0xaa)
+        return -1;
+    for(i = 0; i < 4; i++) {
+        p = ((struct partition *)(buf + 0x1be)) + i;
+        nr_sects = le32_to_cpu(p->nr_sects);
+        if (nr_sects && p->end_head) {
+            /* We make the assumption that the partition terminates on
+               a cylinder boundary */
+            heads = p->end_head + 1;
+            sectors = p->end_sector & 63;
+            if (sectors == 0)
+                continue;
+            cylinders = s->nb_sectors / (heads * sectors);
+            if (cylinders < 1 || cylinders > 16383)
+                continue;
+            *pheads = heads;
+            *psectors = sectors;
+            *pcylinders = cylinders;
+#if 0
+            printf("guessed geometry: LCHS=%d %d %d\n",
+                   cylinders, heads, sectors);
+#endif
+            return 0;
+        }
+    }
+    return -1;
+}
+
+static void ide_init2(IDEState *ide_state,
+                      BlockDriverState *hd0, BlockDriverState *hd1,
+                      qemu_irq irq)
+{
+    IDEState *s;
+    static int drive_serial = 1;
+    int i, cylinders, heads, secs, translation, lba_detected = 0;
+    int64_t nb_sectors;
+
+    for(i = 0; i < 2; i++) {
+        s = ide_state + i;
+        if (i == 0)
+            s->bs = hd0;
+        else
+            s->bs = hd1;
+        if (s->bs) {
+            bdrv_get_geometry(s->bs, &nb_sectors);
+            s->nb_sectors = nb_sectors;
+            /* if a geometry hint is available, use it */
+            bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs);
+            translation = bdrv_get_translation_hint(s->bs);
+            if (cylinders != 0) {
+                s->cylinders = cylinders;
+                s->heads = heads;
+                s->sectors = secs;
+            } else {
+                if (guess_disk_lchs(s, &cylinders, &heads, &secs) == 0) {
+                    if (heads > 16) {
+                        /* if heads > 16, it means that a BIOS LBA
+                           translation was active, so the default
+                           hardware geometry is OK */
+                        lba_detected = 1;
+                        goto default_geometry;
+                    } else {
+                        s->cylinders = cylinders;
+                        s->heads = heads;
+                        s->sectors = secs;
+                        /* disable any translation to be in sync with
+                           the logical geometry */
+                        if (translation == BIOS_ATA_TRANSLATION_AUTO) {
+                            bdrv_set_translation_hint(s->bs,
+                                                      
BIOS_ATA_TRANSLATION_NONE);
+                        }
+                    }
+                } else {
+                default_geometry:
+                    /* if no geometry, use a standard physical disk geometry */
+                    cylinders = nb_sectors / (16 * 63);
+                    if (cylinders > 16383)
+                        cylinders = 16383;
+                    else if (cylinders < 2)
+                        cylinders = 2;
+                    s->cylinders = cylinders;
+                    s->heads = 16;
+                    s->sectors = 63;
+                    if ((lba_detected == 1) && (translation == 
BIOS_ATA_TRANSLATION_AUTO)) {
+                      if ((s->cylinders * s->heads) <= 131072) {
+                        bdrv_set_translation_hint(s->bs,
+                                                  BIOS_ATA_TRANSLATION_LARGE);
+                      } else {
+                        bdrv_set_translation_hint(s->bs,
+                                                  BIOS_ATA_TRANSLATION_LBA);
+                      }
+                    }
+                }
+                bdrv_set_geometry_hint(s->bs, s->cylinders, s->heads, 
s->sectors);
+            }
+            if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
+                s->is_cdrom = 1;
+               bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
+            }
+        }
+        s->drive_serial = drive_serial++;
+        s->irq = irq;
+#ifdef TARGET_I386
+        s->sector_write_timer = qemu_new_timer(vm_clock,
+                                               ide_sector_write_timer_cb, s);
+#endif
+        ide_reset(s);
+    }
+}
+
+static void ide_init_ioport(IDEState *ide_state, int iobase, int iobase2)
+{
+    register_ioport_write(iobase, 8, 1, ide_ioport_write, ide_state);
+    register_ioport_read(iobase, 8, 1, ide_ioport_read, ide_state);
+    if (iobase2) {
+        register_ioport_read(iobase2, 1, 1, ide_status_read, ide_state);
+        register_ioport_write(iobase2, 1, 1, ide_cmd_write, ide_state);
+    }
+
+    /* data ports */
+    register_ioport_write(iobase, 2, 2, ide_data_writew, ide_state);
+    register_ioport_read(iobase, 2, 2, ide_data_readw, ide_state);
+    register_ioport_write(iobase, 4, 4, ide_data_writel, ide_state);
+    register_ioport_read(iobase, 4, 4, ide_data_readl, ide_state);
+}
+
+#ifndef IOEMU
+/* save per IDE drive data */
+static void ide_save(QEMUFile* f, IDEState *s)
+{
+    qemu_put_be32s(f, &s->mult_sectors);
+    qemu_put_be32s(f, &s->identify_set);
+    if (s->identify_set) {
+        qemu_put_buffer(f, (const uint8_t *)s->identify_data, 512);
+    }
+    qemu_put_8s(f, &s->feature);
+    qemu_put_8s(f, &s->error);
+    qemu_put_be32s(f, &s->nsector);
+    qemu_put_8s(f, &s->sector);
+    qemu_put_8s(f, &s->lcyl);
+    qemu_put_8s(f, &s->hcyl);
+    qemu_put_8s(f, &s->hob_feature);
+    qemu_put_8s(f, &s->hob_nsector);
+    qemu_put_8s(f, &s->hob_sector);
+    qemu_put_8s(f, &s->hob_lcyl);
+    qemu_put_8s(f, &s->hob_hcyl);
+    qemu_put_8s(f, &s->select);
+    qemu_put_8s(f, &s->status);
+    qemu_put_8s(f, &s->lba48);
+
+    qemu_put_8s(f, &s->sense_key);
+    qemu_put_8s(f, &s->asc);
+    /* XXX: if a transfer is pending, we do not save it yet */
+}
+
+/* load per IDE drive data */
+static void ide_load(QEMUFile* f, IDEState *s)
+{
+    qemu_get_be32s(f, &s->mult_sectors);
+    qemu_get_be32s(f, &s->identify_set);
+    if (s->identify_set) {
+        qemu_get_buffer(f, (uint8_t *)s->identify_data, 512);
+    }
+    qemu_get_8s(f, &s->feature);
+    qemu_get_8s(f, &s->error);
+    qemu_get_be32s(f, &s->nsector);
+    qemu_get_8s(f, &s->sector);
+    qemu_get_8s(f, &s->lcyl);
+    qemu_get_8s(f, &s->hcyl);
+    qemu_get_8s(f, &s->hob_feature);
+    qemu_get_8s(f, &s->hob_nsector);
+    qemu_get_8s(f, &s->hob_sector);
+    qemu_get_8s(f, &s->hob_lcyl);
+    qemu_get_8s(f, &s->hob_hcyl);
+    qemu_get_8s(f, &s->select);
+    qemu_get_8s(f, &s->status);
+    qemu_get_8s(f, &s->lba48);
+
+    qemu_get_8s(f, &s->sense_key);
+    qemu_get_8s(f, &s->asc);
+    /* XXX: if a transfer is pending, we do not save it yet */
+}
+#endif
+
+#ifndef IOEMU
+/***********************************************************/
+/* ISA IDE definitions */
+
+void isa_ide_init(int iobase, int iobase2, qemu_irq irq,
+                  BlockDriverState *hd0, BlockDriverState *hd1)
+{
+    IDEState *ide_state;
+
+    ide_state = qemu_mallocz(sizeof(IDEState) * 2);
+    if (!ide_state)
+        return;
+
+    ide_init2(ide_state, hd0, hd1, irq);
+    ide_init_ioport(ide_state, iobase, iobase2);
+}
+#endif
+
+/***********************************************************/
+/* PCI IDE definitions */
+
+static void cmd646_update_irq(PCIIDEState *d);
+
+static void ide_map(PCIDevice *pci_dev, int region_num,
+                    uint32_t addr, uint32_t size, int type)
+{
+    PCIIDEState *d = (PCIIDEState *)pci_dev;
+    IDEState *ide_state;
+
+    if (region_num <= 3) {
+        ide_state = &d->ide_if[(region_num >> 1) * 2];
+        if (region_num & 1) {
+            register_ioport_read(addr + 2, 1, 1, ide_status_read, ide_state);
+            register_ioport_write(addr + 2, 1, 1, ide_cmd_write, ide_state);
+        } else {
+            register_ioport_write(addr, 8, 1, ide_ioport_write, ide_state);
+            register_ioport_read(addr, 8, 1, ide_ioport_read, ide_state);
+
+            /* data ports */
+            register_ioport_write(addr, 2, 2, ide_data_writew, ide_state);
+            register_ioport_read(addr, 2, 2, ide_data_readw, ide_state);
+            register_ioport_write(addr, 4, 4, ide_data_writel, ide_state);
+            register_ioport_read(addr, 4, 4, ide_data_readl, ide_state);
+        }
+    }
+}
+
+static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb)
+{
+    BMDMAState *bm = s->bmdma;
+    if(!bm)
+        return;
+    bm->ide_if = s;
+    bm->dma_cb = dma_cb;
+    bm->cur_prd_last = 0;
+    bm->cur_prd_addr = 0;
+    bm->cur_prd_len = 0;
+    if (bm->status & BM_STATUS_DMAING) {
+        bm->dma_cb(bm, 0);
+    }
+}
+
+static void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    BMDMAState *bm = opaque;
+#ifdef DEBUG_IDE
+    printf("%s: 0x%08x\n", __func__, val);
+#endif
+    if (!(val & BM_CMD_START)) {
+        /* XXX: do it better */
+        if (bm->status & BM_STATUS_DMAING) {
+            bm->status &= ~BM_STATUS_DMAING;
+            /* cancel DMA request */
+            bm->ide_if = NULL;
+            bm->dma_cb = NULL;
+            if (bm->aiocb) {
+#ifdef DEBUG_AIO
+                printf("aio_cancel\n");
+#endif
+                bdrv_aio_cancel(bm->aiocb);
+                bm->aiocb = NULL;
+            }
+        }
+        bm->cmd = val & 0x09;
+    } else {
+        if (!(bm->status & BM_STATUS_DMAING)) {
+            bm->status |= BM_STATUS_DMAING;
+            /* start dma transfer if possible */
+            if (bm->dma_cb)
+                bm->dma_cb(bm, 0);
+        }
+        bm->cmd = val & 0x09;
+    }
+}
+
+static uint32_t bmdma_readb(void *opaque, uint32_t addr)
+{
+    BMDMAState *bm = opaque;
+    PCIIDEState *pci_dev;
+    uint32_t val;
+
+    switch(addr & 3) {
+    case 0:
+        val = bm->cmd;
+        break;
+    case 1:
+        pci_dev = bm->pci_dev;
+        if (pci_dev->type == IDE_TYPE_CMD646) {
+            val = pci_dev->dev.config[MRDMODE];
+        } else {
+            val = 0xff;
+        }
+        break;
+    case 2:
+        val = bm->status;
+        break;
+    case 3:
+        pci_dev = bm->pci_dev;
+        if (pci_dev->type == IDE_TYPE_CMD646) {
+            if (bm == &pci_dev->bmdma[0])
+                val = pci_dev->dev.config[UDIDETCR0];
+            else
+                val = pci_dev->dev.config[UDIDETCR1];
+        } else {
+            val = 0xff;
+        }
+        break;
+    default:
+        val = 0xff;
+        break;
+    }
+#ifdef DEBUG_IDE
+    printf("bmdma: readb 0x%02x : 0x%02x\n", addr, val);
+#endif
+    return val;
+}
+
+static void bmdma_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    BMDMAState *bm = opaque;
+    PCIIDEState *pci_dev;
+#ifdef DEBUG_IDE
+    printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val);
+#endif
+    switch(addr & 3) {
+    case 1:
+        pci_dev = bm->pci_dev;
+        if (pci_dev->type == IDE_TYPE_CMD646) {
+            pci_dev->dev.config[MRDMODE] =
+                (pci_dev->dev.config[MRDMODE] & ~0x30) | (val & 0x30);
+            cmd646_update_irq(pci_dev);
+        }
+        break;
+    case 2:
+        bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 
0x06);
+        break;
+    case 3:
+        pci_dev = bm->pci_dev;
+        if (pci_dev->type == IDE_TYPE_CMD646) {
+            if (bm == &pci_dev->bmdma[0])
+                pci_dev->dev.config[UDIDETCR0] = val;
+            else
+                pci_dev->dev.config[UDIDETCR1] = val;
+        }
+        break;
+    }
+}
+
+static uint32_t bmdma_addr_readl(void *opaque, uint32_t addr)
+{
+    BMDMAState *bm = opaque;
+    uint32_t val;
+    val = bm->addr;
+#ifdef DEBUG_IDE
+    printf("%s: 0x%08x\n", __func__, val);
+#endif
+    return val;
+}
+
+static void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val)
+{
+    BMDMAState *bm = opaque;
+#ifdef DEBUG_IDE
+    printf("%s: 0x%08x\n", __func__, val);
+#endif
+    bm->addr = val & ~3;
+    bm->cur_addr = bm->addr;
+}
+
+static void bmdma_map(PCIDevice *pci_dev, int region_num,
+                    uint32_t addr, uint32_t size, int type)
+{
+    PCIIDEState *d = (PCIIDEState *)pci_dev;
+    int i;
+
+    for(i = 0;i < 2; i++) {
+        BMDMAState *bm = &d->bmdma[i];
+        d->ide_if[2 * i].bmdma = bm;
+        d->ide_if[2 * i + 1].bmdma = bm;
+        bm->pci_dev = (PCIIDEState *)pci_dev;
+
+        register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm);
+
+        register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm);
+        register_ioport_read(addr, 4, 1, bmdma_readb, bm);
+
+        register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm);
+        register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm);
+        addr += 8;
+    }
+}
+
+/* XXX: call it also when the MRDMODE is changed from the PCI config
+   registers */
+static void cmd646_update_irq(PCIIDEState *d)
+{
+    int pci_level;
+    pci_level = ((d->dev.config[MRDMODE] & MRDMODE_INTR_CH0) &&
+                 !(d->dev.config[MRDMODE] & MRDMODE_BLK_CH0)) ||
+        ((d->dev.config[MRDMODE] & MRDMODE_INTR_CH1) &&
+         !(d->dev.config[MRDMODE] & MRDMODE_BLK_CH1));
+    qemu_set_irq(d->dev.irq[0], pci_level);
+}
+
+/* the PCI irq level is the logical OR of the two channels */
+static void cmd646_set_irq(void *opaque, int channel, int level)
+{
+    PCIIDEState *d = opaque;
+    int irq_mask;
+
+    irq_mask = MRDMODE_INTR_CH0 << channel;
+    if (level)
+        d->dev.config[MRDMODE] |= irq_mask;
+    else
+        d->dev.config[MRDMODE] &= ~irq_mask;
+    cmd646_update_irq(d);
+}
+
+/* CMD646 PCI IDE controller */
+void pci_cmd646_ide_init(PCIBus *bus, BlockDriverState **hd_table,
+                         int secondary_ide_enabled)
+{
+    PCIIDEState *d;
+    uint8_t *pci_conf;
+    int i;
+    qemu_irq *irq;
+
+    d = (PCIIDEState *)pci_register_device(bus, "CMD646 IDE",
+                                           sizeof(PCIIDEState),
+                                           -1,
+                                           NULL, NULL);
+#ifdef IOEMU
+    for (i = 0; i < 4; i++)
+      d->ide_if[i].io_buffer = alloc_pages
+       (((MAX_MULT_SECTORS * 512 + 4) + PAGE_SIZE - 1) >> PAGE_SHIFT);
+#endif
+    d->type = IDE_TYPE_CMD646;
+    pci_conf = d->dev.config;
+    pci_conf[0x00] = 0x95; // CMD646
+    pci_conf[0x01] = 0x10;
+    pci_conf[0x02] = 0x46;
+    pci_conf[0x03] = 0x06;
+
+    pci_conf[0x08] = 0x07; // IDE controller revision
+    pci_conf[0x09] = 0x8f;
+
+    pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
+    pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
+    pci_conf[0x0e] = 0x00; // header_type
+
+    if (secondary_ide_enabled) {
+        /* XXX: if not enabled, really disable the seconday IDE controller */
+        pci_conf[0x51] = 0x80; /* enable IDE1 */
+    }
+
+    pci_register_io_region((PCIDevice *)d, 0, 0x8,
+                           PCI_ADDRESS_SPACE_IO, ide_map);
+    pci_register_io_region((PCIDevice *)d, 1, 0x4,
+                           PCI_ADDRESS_SPACE_IO, ide_map);
+    pci_register_io_region((PCIDevice *)d, 2, 0x8,
+                           PCI_ADDRESS_SPACE_IO, ide_map);
+    pci_register_io_region((PCIDevice *)d, 3, 0x4,
+                           PCI_ADDRESS_SPACE_IO, ide_map);
+    pci_register_io_region((PCIDevice *)d, 4, 0x10,
+                           PCI_ADDRESS_SPACE_IO, bmdma_map);
+
+    pci_conf[0x3d] = 0x01; // interrupt on pin 1
+
+    for(i = 0; i < 4; i++)
+        d->ide_if[i].pci_dev = (PCIDevice *)d;
+
+    irq = qemu_allocate_irqs(cmd646_set_irq, d, 2);
+    ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], irq[0]);
+    ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], irq[1]);
+}
+
+#ifndef IOEMU
+static void pci_ide_save(QEMUFile* f, void *opaque)
+{
+    PCIIDEState *d = opaque;
+    int i;
+
+    pci_device_save(&d->dev, f);
+
+    for(i = 0; i < 2; i++) {
+        BMDMAState *bm = &d->bmdma[i];
+        qemu_put_8s(f, &bm->cmd);
+        qemu_put_8s(f, &bm->status);
+        qemu_put_be32s(f, &bm->addr);
+        /* XXX: if a transfer is pending, we do not save it yet */
+    }
+
+    /* per IDE interface data */
+    for(i = 0; i < 2; i++) {
+        IDEState *s = &d->ide_if[i * 2];
+        uint8_t drive1_selected;
+        qemu_put_8s(f, &s->cmd);
+        drive1_selected = (s->cur_drive != s);
+        qemu_put_8s(f, &drive1_selected);
+    }
+
+    /* per IDE drive data */
+    for(i = 0; i < 4; i++) {
+        ide_save(f, &d->ide_if[i]);
+    }
+}
+
+static int pci_ide_load(QEMUFile* f, void *opaque, int version_id)
+{
+    PCIIDEState *d = opaque;
+    int ret, i;
+
+    if (version_id != 1)
+        return -EINVAL;
+    ret = pci_device_load(&d->dev, f);
+    if (ret < 0)
+        return ret;
+
+    for(i = 0; i < 2; i++) {
+        BMDMAState *bm = &d->bmdma[i];
+        qemu_get_8s(f, &bm->cmd);
+        qemu_get_8s(f, &bm->status);
+        qemu_get_be32s(f, &bm->addr);
+        /* XXX: if a transfer is pending, we do not save it yet */
+    }
+
+    /* per IDE interface data */
+    for(i = 0; i < 2; i++) {
+        IDEState *s = &d->ide_if[i * 2];
+        uint8_t drive1_selected;
+        qemu_get_8s(f, &s->cmd);
+        qemu_get_8s(f, &drive1_selected);
+        s->cur_drive = &d->ide_if[i * 2 + (drive1_selected != 0)];
+    }
+
+    /* per IDE drive data */
+    for(i = 0; i < 4; i++) {
+        ide_load(f, &d->ide_if[i]);
+    }
+    return 0;
+}
+#endif
+
+static void piix3_reset(PCIIDEState *d)
+{
+    uint8_t *pci_conf = d->dev.config;
+
+    pci_conf[0x04] = 0x00;
+    pci_conf[0x05] = 0x00;
+    pci_conf[0x06] = 0x80; /* FBC */
+    pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
+    pci_conf[0x20] = 0x01; /* BMIBA: 20-23h */
+}
+
+/* hd_table must contain 4 block drivers */
+/* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
+void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
+                        qemu_irq *pic)
+{
+    PCIIDEState *d;
+    uint8_t *pci_conf;
+
+    /* register a function 1 of PIIX3 */
+    d = (PCIIDEState *)pci_register_device(bus, "PIIX3 IDE",
+                                           sizeof(PCIIDEState),
+                                           devfn,
+                                           NULL, NULL);
+    d->type = IDE_TYPE_PIIX3;
+#ifdef IOEMU
+    int i;
+    for (i = 0; i < 4; i++)
+      d->ide_if[i].io_buffer = alloc_pages
+       (((MAX_MULT_SECTORS * 512 + 4) + PAGE_SIZE - 1) >> PAGE_SHIFT);
+#endif
+
+    pci_conf = d->dev.config;
+    pci_conf[0x00] = 0x86; // Intel
+    pci_conf[0x01] = 0x80;
+    pci_conf[0x02] = 0x10;
+    pci_conf[0x03] = 0x70;
+    pci_conf[0x09] = 0x80; // legacy ATA mode
+    pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
+    pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
+    pci_conf[0x0e] = 0x00; // header_type
+
+    piix3_reset(d);
+
+    pci_register_io_region((PCIDevice *)d, 4, 0x10,
+                           PCI_ADDRESS_SPACE_IO, bmdma_map);
+
+    ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], pic[14]);
+    ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], pic[15]);
+    ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
+    ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
+
+    register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
+}
+
+/* hd_table must contain 4 block drivers */
+/* NOTE: for the PIIX4, the IRQs and IOports are hardcoded */
+void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
+                        qemu_irq *pic)
+{
+    PCIIDEState *d;
+    uint8_t *pci_conf;
+
+    /* register a function 1 of PIIX4 */
+    d = (PCIIDEState *)pci_register_device(bus, "PIIX4 IDE",
+                                           sizeof(PCIIDEState),
+                                           devfn,
+                                           NULL, NULL);
+    d->type = IDE_TYPE_PIIX4;
+#ifdef IOEMU
+    int i;
+    for (i = 0; i < 4; i++)
+      d->ide_if[i].io_buffer = alloc_pages
+       (((MAX_MULT_SECTORS * 512 + 4) + PAGE_SIZE - 1) >> PAGE_SHIFT);
+#endif
+
+    pci_conf = d->dev.config;
+    pci_conf[0x00] = 0x86; // Intel
+    pci_conf[0x01] = 0x80;
+    pci_conf[0x02] = 0x11;
+    pci_conf[0x03] = 0x71;
+    pci_conf[0x09] = 0x80; // legacy ATA mode
+    pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
+    pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
+    pci_conf[0x0e] = 0x00; // header_type
+
+    piix3_reset(d);
+
+    pci_register_io_region((PCIDevice *)d, 4, 0x10,
+                           PCI_ADDRESS_SPACE_IO, bmdma_map);
+
+    ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], pic[14]);
+    ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], pic[15]);
+    ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
+    ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
+
+    register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
+}
+
+#ifndef IOEMU
+/***********************************************************/
+/* MacIO based PowerPC IDE */
+
+/* PowerMac IDE memory IO */
+static void pmac_ide_writeb (void *opaque,
+                             target_phys_addr_t addr, uint32_t val)
+{
+    addr = (addr & 0xFFF) >> 4;
+    switch (addr) {
+    case 1 ... 7:
+        ide_ioport_write(opaque, addr, val);
+        break;
+    case 8:
+    case 22:
+        ide_cmd_write(opaque, 0, val);
+        break;
+    default:
+        break;
+    }
+}
+
+static uint32_t pmac_ide_readb (void *opaque,target_phys_addr_t addr)
+{
+    uint8_t retval;
+
+    addr = (addr & 0xFFF) >> 4;
+    switch (addr) {
+    case 1 ... 7:
+        retval = ide_ioport_read(opaque, addr);
+        break;
+    case 8:
+    case 22:
+        retval = ide_status_read(opaque, 0);
+        break;
+    default:
+        retval = 0xFF;
+        break;
+    }
+    return retval;
+}
+
+static void pmac_ide_writew (void *opaque,
+                             target_phys_addr_t addr, uint32_t val)
+{
+    addr = (addr & 0xFFF) >> 4;
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap16(val);
+#endif
+    if (addr == 0) {
+        ide_data_writew(opaque, 0, val);
+    }
+}
+
+static uint32_t pmac_ide_readw (void *opaque,target_phys_addr_t addr)
+{
+    uint16_t retval;
+
+    addr = (addr & 0xFFF) >> 4;
+    if (addr == 0) {
+        retval = ide_data_readw(opaque, 0);
+    } else {
+        retval = 0xFFFF;
+    }
+#ifdef TARGET_WORDS_BIGENDIAN
+    retval = bswap16(retval);
+#endif
+    return retval;
+}
+
+static void pmac_ide_writel (void *opaque,
+                             target_phys_addr_t addr, uint32_t val)
+{
+    addr = (addr & 0xFFF) >> 4;
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    if (addr == 0) {
+        ide_data_writel(opaque, 0, val);
+    }
+}
+
+static uint32_t pmac_ide_readl (void *opaque,target_phys_addr_t addr)
+{
+    uint32_t retval;
+
+    addr = (addr & 0xFFF) >> 4;
+    if (addr == 0) {
+        retval = ide_data_readl(opaque, 0);
+    } else {
+        retval = 0xFFFFFFFF;
+    }
+#ifdef TARGET_WORDS_BIGENDIAN
+    retval = bswap32(retval);
+#endif
+    return retval;
+}
+
+static CPUWriteMemoryFunc *pmac_ide_write[] = {
+    pmac_ide_writeb,
+    pmac_ide_writew,
+    pmac_ide_writel,
+};
+
+static CPUReadMemoryFunc *pmac_ide_read[] = {
+    pmac_ide_readb,
+    pmac_ide_readw,
+    pmac_ide_readl,
+};
+
+/* hd_table must contain 4 block drivers */
+/* PowerMac uses memory mapped registers, not I/O. Return the memory
+   I/O index to access the ide. */
+int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq)
+{
+    IDEState *ide_if;
+    int pmac_ide_memory;
+
+    ide_if = qemu_mallocz(sizeof(IDEState) * 2);
+    ide_init2(&ide_if[0], hd_table[0], hd_table[1], irq);
+
+    pmac_ide_memory = cpu_register_io_memory(0, pmac_ide_read,
+                                             pmac_ide_write, &ide_if[0]);
+    return pmac_ide_memory;
+}
+
+/***********************************************************/
+/* CF-ATA Microdrive */
+
+#define METADATA_SIZE  0x20
+
+/* DSCM-1XXXX Microdrive hard disk with CF+ II / PCMCIA interface.  */
+struct md_s {
+    IDEState ide[2];
+    struct pcmcia_card_s card;
+    uint32_t attr_base;
+    uint32_t io_base;
+
+    /* Card state */
+    uint8_t opt;
+    uint8_t stat;
+    uint8_t pins;
+
+    uint8_t ctrl;
+    uint16_t io;
+    int cycle;
+};
+
+/* Register bitfields */
+enum md_opt {
+    OPT_MODE_MMAP      = 0,
+    OPT_MODE_IOMAP16   = 1,
+    OPT_MODE_IOMAP1    = 2,
+    OPT_MODE_IOMAP2    = 3,
+    OPT_MODE           = 0x3f,
+    OPT_LEVIREQ                = 0x40,
+    OPT_SRESET         = 0x80,
+};
+enum md_cstat {
+    STAT_INT           = 0x02,
+    STAT_PWRDWN                = 0x04,
+    STAT_XE            = 0x10,
+    STAT_IOIS8         = 0x20,
+    STAT_SIGCHG                = 0x40,
+    STAT_CHANGED       = 0x80,
+};
+enum md_pins {
+    PINS_MRDY          = 0x02,
+    PINS_CRDY          = 0x20,
+};
+enum md_ctrl {
+    CTRL_IEN           = 0x02,
+    CTRL_SRST          = 0x04,
+};
+
+static inline void md_interrupt_update(struct md_s *s)
+{
+    if (!s->card.slot)
+        return;
+
+    qemu_set_irq(s->card.slot->irq,
+                    !(s->stat & STAT_INT) &&   /* Inverted */
+                    !(s->ctrl & (CTRL_IEN | CTRL_SRST)) &&
+                    !(s->opt & OPT_SRESET));
+}
+
+static void md_set_irq(void *opaque, int irq, int level)
+{
+    struct md_s *s = (struct md_s *) opaque;
+    if (level)
+        s->stat |= STAT_INT;
+    else
+        s->stat &= ~STAT_INT;
+
+    md_interrupt_update(s);
+}
+
+static void md_reset(struct md_s *s)
+{
+    s->opt = OPT_MODE_MMAP;
+    s->stat = 0;
+    s->pins = 0;
+    s->cycle = 0;
+    s->ctrl = 0;
+    ide_reset(s->ide);
+}
+
+static uint8_t md_attr_read(void *opaque, uint32_t at)
+{
+    struct md_s *s = (struct md_s *) opaque;
+    if (at < s->attr_base) {
+        if (at < s->card.cis_len)
+            return s->card.cis[at];
+        else
+            return 0x00;
+    }
+
+    at -= s->attr_base;
+
+    switch (at) {
+    case 0x00: /* Configuration Option Register */
+        return s->opt;
+    case 0x02: /* Card Configuration Status Register */
+        if (s->ctrl & CTRL_IEN)
+            return s->stat & ~STAT_INT;
+        else
+            return s->stat;
+    case 0x04: /* Pin Replacement Register */
+        return (s->pins & PINS_CRDY) | 0x0c;
+    case 0x06: /* Socket and Copy Register */
+        return 0x00;
+#ifdef VERBOSE
+    default:
+        printf("%s: Bad attribute space register %02x\n", __FUNCTION__, at);
+#endif
+    }
+
+    return 0;
+}
+
+static void md_attr_write(void *opaque, uint32_t at, uint8_t value)
+{
+    struct md_s *s = (struct md_s *) opaque;
+    at -= s->attr_base;
+
+    switch (at) {
+    case 0x00: /* Configuration Option Register */
+        s->opt = value & 0xcf;
+        if (value & OPT_SRESET)
+            md_reset(s);
+        md_interrupt_update(s);
+        break;
+    case 0x02: /* Card Configuration Status Register */
+        if ((s->stat ^ value) & STAT_PWRDWN)
+            s->pins |= PINS_CRDY;
+        s->stat &= 0x82;
+        s->stat |= value & 0x74;
+        md_interrupt_update(s);
+        /* Word 170 in Identify Device must be equal to STAT_XE */
+        break;
+    case 0x04: /* Pin Replacement Register */
+        s->pins &= PINS_CRDY;
+        s->pins |= value & PINS_MRDY;
+        break;
+    case 0x06: /* Socket and Copy Register */
+        break;
+    default:
+        printf("%s: Bad attribute space register %02x\n", __FUNCTION__, at);
+    }
+}
+
+static uint16_t md_common_read(void *opaque, uint32_t at)
+{
+    struct md_s *s = (struct md_s *) opaque;
+    uint16_t ret;
+    at -= s->io_base;
+
+    switch (s->opt & OPT_MODE) {
+    case OPT_MODE_MMAP:
+        if ((at & ~0x3ff) == 0x400)
+            at = 0;
+        break;
+    case OPT_MODE_IOMAP16:
+        at &= 0xf;
+        break;
+    case OPT_MODE_IOMAP1:
+        if ((at & ~0xf) == 0x3f0)
+            at -= 0x3e8;
+        else if ((at & ~0xf) == 0x1f0)
+            at -= 0x1f0;
+        break;
+    case OPT_MODE_IOMAP2:
+        if ((at & ~0xf) == 0x370)
+            at -= 0x368;
+        else if ((at & ~0xf) == 0x170)
+            at -= 0x170;
+    }
+
+    switch (at) {
+    case 0x0:  /* Even RD Data */
+    case 0x8:
+        return ide_data_readw(s->ide, 0);
+
+        /* TODO: 8-bit accesses */
+        if (s->cycle)
+            ret = s->io >> 8;
+        else {
+            s->io = ide_data_readw(s->ide, 0);
+            ret = s->io & 0xff;
+        }
+        s->cycle = !s->cycle;
+        return ret;
+    case 0x9:  /* Odd RD Data */
+        return s->io >> 8;
+    case 0xd:  /* Error */
+        return ide_ioport_read(s->ide, 0x1);
+    case 0xe:  /* Alternate Status */
+        if (s->ide->cur_drive->bs)
+            return s->ide->cur_drive->status;
+        else
+            return 0;
+    case 0xf:  /* Device Address */
+        return 0xc2 | ((~s->ide->select << 2) & 0x3c);
+    default:
+        return ide_ioport_read(s->ide, at);
+    }
+
+    return 0;
+}
+
+static void md_common_write(void *opaque, uint32_t at, uint16_t value)
+{
+    struct md_s *s = (struct md_s *) opaque;
+    at -= s->io_base;
+
+    switch (s->opt & OPT_MODE) {
+    case OPT_MODE_MMAP:
+        if ((at & ~0x3ff) == 0x400)
+            at = 0;
+        break;
+    case OPT_MODE_IOMAP16:
+        at &= 0xf;
+        break;
+    case OPT_MODE_IOMAP1:
+        if ((at & ~0xf) == 0x3f0)
+            at -= 0x3e8;
+        else if ((at & ~0xf) == 0x1f0)
+            at -= 0x1f0;
+        break;
+    case OPT_MODE_IOMAP2:
+        if ((at & ~0xf) == 0x370)
+            at -= 0x368;
+        else if ((at & ~0xf) == 0x170)
+            at -= 0x170;
+    }
+
+    switch (at) {
+    case 0x0:  /* Even WR Data */
+    case 0x8:
+        ide_data_writew(s->ide, 0, value);
+        break;
+
+        /* TODO: 8-bit accesses */
+        if (s->cycle)
+            ide_data_writew(s->ide, 0, s->io | (value << 8));
+        else
+            s->io = value & 0xff;
+        s->cycle = !s->cycle;
+        break;
+    case 0x9:
+        s->io = value & 0xff;
+        s->cycle = !s->cycle;
+        break;
+    case 0xd:  /* Features */
+        ide_ioport_write(s->ide, 0x1, value);
+        break;
+    case 0xe:  /* Device Control */
+        s->ctrl = value;
+        if (value & CTRL_SRST)
+            md_reset(s);
+        md_interrupt_update(s);
+        break;
+    default:
+        if (s->stat & STAT_PWRDWN) {
+            s->pins |= PINS_CRDY;
+            s->stat &= ~STAT_PWRDWN;
+        }
+        ide_ioport_write(s->ide, at, value);
+    }
+}
+
+static void md_save(QEMUFile *f, void *opaque)
+{
+    struct md_s *s = (struct md_s *) opaque;
+    int i;
+    uint8_t drive1_selected;
+
+    qemu_put_8s(f, &s->opt);
+    qemu_put_8s(f, &s->stat);
+    qemu_put_8s(f, &s->pins);
+
+    qemu_put_8s(f, &s->ctrl);
+    qemu_put_be16s(f, &s->io);
+    qemu_put_byte(f, s->cycle);
+
+    drive1_selected = (s->ide->cur_drive != s->ide);
+    qemu_put_8s(f, &s->ide->cmd);
+    qemu_put_8s(f, &drive1_selected);
+
+    for (i = 0; i < 2; i ++)
+        ide_save(f, &s->ide[i]);
+}
+
+static int md_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct md_s *s = (struct md_s *) opaque;
+    int i;
+    uint8_t drive1_selected;
+
+    qemu_get_8s(f, &s->opt);
+    qemu_get_8s(f, &s->stat);
+    qemu_get_8s(f, &s->pins);
+
+    qemu_get_8s(f, &s->ctrl);
+    qemu_get_be16s(f, &s->io);
+    s->cycle = qemu_get_byte(f);
+
+    qemu_get_8s(f, &s->ide->cmd);
+    qemu_get_8s(f, &drive1_selected);
+    s->ide->cur_drive = &s->ide[(drive1_selected != 0)];
+
+    for (i = 0; i < 2; i ++)
+        ide_load(f, &s->ide[i]);
+
+    return 0;
+}
+
+static int md_iid = 0;
+
+static const uint8_t dscm1xxxx_cis[0x14a] = {
+    [0x000] = CISTPL_DEVICE,   /* 5V Device Information */
+    [0x002] = 0x03,            /* Tuple length = 4 bytes */
+    [0x004] = 0xdb,            /* ID: DTYPE_FUNCSPEC, non WP, DSPEED_150NS */
+    [0x006] = 0x01,            /* Size = 2K bytes */
+    [0x008] = CISTPL_ENDMARK,
+
+    [0x00a] = CISTPL_DEVICE_OC,        /* Additional Device Information */
+    [0x00c] = 0x04,            /* Tuple length = 4 byest */
+    [0x00e] = 0x03,            /* Conditions: Ext = 0, Vcc 3.3V, MWAIT = 1 */
+    [0x010] = 0xdb,            /* ID: DTYPE_FUNCSPEC, non WP, DSPEED_150NS */
+    [0x012] = 0x01,            /* Size = 2K bytes */
+    [0x014] = CISTPL_ENDMARK,
+
+    [0x016] = CISTPL_JEDEC_C,  /* JEDEC ID */
+    [0x018] = 0x02,            /* Tuple length = 2 bytes */
+    [0x01a] = 0xdf,            /* PC Card ATA with no Vpp required */
+    [0x01c] = 0x01,
+
+    [0x01e] = CISTPL_MANFID,   /* Manufacture ID */
+    [0x020] = 0x04,            /* Tuple length = 4 bytes */
+    [0x022] = 0xa4,            /* TPLMID_MANF = 00a4 (IBM) */
+    [0x024] = 0x00,
+    [0x026] = 0x00,            /* PLMID_CARD = 0000 */
+    [0x028] = 0x00,
+
+    [0x02a] = CISTPL_VERS_1,   /* Level 1 Version */
+    [0x02c] = 0x12,            /* Tuple length = 23 bytes */
+    [0x02e] = 0x04,            /* Major Version = JEIDA 4.2 / PCMCIA 2.1 */
+    [0x030] = 0x01,            /* Minor Version = 1 */
+    [0x032] = 'I',
+    [0x034] = 'B',
+    [0x036] = 'M',
+    [0x038] = 0x00,
+    [0x03a] = 'm',
+    [0x03c] = 'i',
+    [0x03e] = 'c',
+    [0x040] = 'r',
+    [0x042] = 'o',
+    [0x044] = 'd',
+    [0x046] = 'r',
+    [0x048] = 'i',
+    [0x04a] = 'v',
+    [0x04c] = 'e',
+    [0x04e] = 0x00,
+    [0x050] = CISTPL_ENDMARK,
+
+    [0x052] = CISTPL_FUNCID,   /* Function ID */
+    [0x054] = 0x02,            /* Tuple length = 2 bytes */
+    [0x056] = 0x04,            /* TPLFID_FUNCTION = Fixed Disk */
+    [0x058] = 0x01,            /* TPLFID_SYSINIT: POST = 1, ROM = 0 */
+
+    [0x05a] = CISTPL_FUNCE,    /* Function Extension */
+    [0x05c] = 0x02,            /* Tuple length = 2 bytes */
+    [0x05e] = 0x01,            /* TPLFE_TYPE = Disk Device Interface */
+    [0x060] = 0x01,            /* TPLFE_DATA = PC Card ATA Interface */
+
+    [0x062] = CISTPL_FUNCE,    /* Function Extension */
+    [0x064] = 0x03,            /* Tuple length = 3 bytes */
+    [0x066] = 0x02,            /* TPLFE_TYPE = Basic PC Card ATA Interface */
+    [0x068] = 0x08,            /* TPLFE_DATA: Rotating, Unique, Single */
+    [0x06a] = 0x0f,            /* TPLFE_DATA: Sleep, Standby, Idle, Auto */
+
+    [0x06c] = CISTPL_CONFIG,   /* Configuration */
+    [0x06e] = 0x05,            /* Tuple length = 5 bytes */
+    [0x070] = 0x01,            /* TPCC_RASZ = 2 bytes, TPCC_RMSZ = 1 byte */
+    [0x072] = 0x07,            /* TPCC_LAST = 7 */
+    [0x074] = 0x00,            /* TPCC_RADR = 0200 */
+    [0x076] = 0x02,
+    [0x078] = 0x0f,            /* TPCC_RMSK = 200, 202, 204, 206 */
+
+    [0x07a] = CISTPL_CFTABLE_ENTRY,    /* 16-bit PC Card Configuration */
+    [0x07c] = 0x0b,            /* Tuple length = 11 bytes */
+    [0x07e] = 0xc0,            /* TPCE_INDX = Memory Mode, Default, Iface */
+    [0x080] = 0xc0,            /* TPCE_IF = Memory, no BVDs, no WP, READY */
+    [0x082] = 0xa1,            /* TPCE_FS = Vcc only, no I/O, Memory, Misc */
+    [0x084] = 0x27,            /* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
+    [0x086] = 0x55,            /* NomV: 5.0 V */
+    [0x088] = 0x4d,            /* MinV: 4.5 V */
+    [0x08a] = 0x5d,            /* MaxV: 5.5 V */
+    [0x08c] = 0x4e,            /* Peakl: 450 mA */
+    [0x08e] = 0x08,            /* TPCE_MS = 1 window, 1 byte, Host address */
+    [0x090] = 0x00,            /* Window descriptor: Window length = 0 */
+    [0x092] = 0x20,            /* TPCE_MI: support power down mode, RW */
+
+    [0x094] = CISTPL_CFTABLE_ENTRY,    /* 16-bit PC Card Configuration */
+    [0x096] = 0x06,            /* Tuple length = 6 bytes */
+    [0x098] = 0x00,            /* TPCE_INDX = Memory Mode, no Default */
+    [0x09a] = 0x01,            /* TPCE_FS = Vcc only, no I/O, no Memory */
+    [0x09c] = 0x21,            /* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
+    [0x09e] = 0xb5,            /* NomV: 3.3 V */
+    [0x0a0] = 0x1e,
+    [0x0a2] = 0x3e,            /* Peakl: 350 mA */
+
+    [0x0a4] = CISTPL_CFTABLE_ENTRY,    /* 16-bit PC Card Configuration */
+    [0x0a6] = 0x0d,            /* Tuple length = 13 bytes */
+    [0x0a8] = 0xc1,            /* TPCE_INDX = I/O and Memory Mode, Default */
+    [0x0aa] = 0x41,            /* TPCE_IF = I/O and Memory, no BVD, no WP */
+    [0x0ac] = 0x99,            /* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
+    [0x0ae] = 0x27,            /* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
+    [0x0b0] = 0x55,            /* NomV: 5.0 V */
+    [0x0b2] = 0x4d,            /* MinV: 4.5 V */
+    [0x0b4] = 0x5d,            /* MaxV: 5.5 V */
+    [0x0b6] = 0x4e,            /* Peakl: 450 mA */
+    [0x0b8] = 0x64,            /* TPCE_IO = 16-byte boundary, 16/8 accesses */
+    [0x0ba] = 0xf0,            /* TPCE_IR =  MASK, Level, Pulse, Share */
+    [0x0bc] = 0xff,            /* IRQ0..IRQ7 supported */
+    [0x0be] = 0xff,            /* IRQ8..IRQ15 supported */
+    [0x0c0] = 0x20,            /* TPCE_MI = support power down mode */
+
+    [0x0c2] = CISTPL_CFTABLE_ENTRY,    /* 16-bit PC Card Configuration */
+    [0x0c4] = 0x06,            /* Tuple length = 6 bytes */
+    [0x0c6] = 0x01,            /* TPCE_INDX = I/O and Memory Mode */
+    [0x0c8] = 0x01,            /* TPCE_FS = Vcc only, no I/O, no Memory */
+    [0x0ca] = 0x21,            /* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
+    [0x0cc] = 0xb5,            /* NomV: 3.3 V */
+    [0x0ce] = 0x1e,
+    [0x0d0] = 0x3e,            /* Peakl: 350 mA */
+
+    [0x0d2] = CISTPL_CFTABLE_ENTRY,    /* 16-bit PC Card Configuration */
+    [0x0d4] = 0x12,            /* Tuple length = 18 bytes */
+    [0x0d6] = 0xc2,            /* TPCE_INDX = I/O Primary Mode */
+    [0x0d8] = 0x41,            /* TPCE_IF = I/O and Memory, no BVD, no WP */
+    [0x0da] = 0x99,            /* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
+    [0x0dc] = 0x27,            /* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
+    [0x0de] = 0x55,            /* NomV: 5.0 V */
+    [0x0e0] = 0x4d,            /* MinV: 4.5 V */
+    [0x0e2] = 0x5d,            /* MaxV: 5.5 V */
+    [0x0e4] = 0x4e,            /* Peakl: 450 mA */
+    [0x0e6] = 0xea,            /* TPCE_IO = 1K boundary, 16/8 access, Range */
+    [0x0e8] = 0x61,            /* Range: 2 fields, 2 bytes addr, 1 byte len */
+    [0x0ea] = 0xf0,            /* Field 1 address = 0x01f0 */
+    [0x0ec] = 0x01,
+    [0x0ee] = 0x07,            /* Address block length = 8 */
+    [0x0f0] = 0xf6,            /* Field 2 address = 0x03f6 */
+    [0x0f2] = 0x03,
+    [0x0f4] = 0x01,            /* Address block length = 2 */
+    [0x0f6] = 0xee,            /* TPCE_IR = IRQ E, Level, Pulse, Share */
+    [0x0f8] = 0x20,            /* TPCE_MI = support power down mode */
+
+    [0x0fa] = CISTPL_CFTABLE_ENTRY,    /* 16-bit PC Card Configuration */
+    [0x0fc] = 0x06,            /* Tuple length = 6 bytes */
+    [0x0fe] = 0x02,            /* TPCE_INDX = I/O Primary Mode, no Default */
+    [0x100] = 0x01,            /* TPCE_FS = Vcc only, no I/O, no Memory */
+    [0x102] = 0x21,            /* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
+    [0x104] = 0xb5,            /* NomV: 3.3 V */
+    [0x106] = 0x1e,
+    [0x108] = 0x3e,            /* Peakl: 350 mA */
+
+    [0x10a] = CISTPL_CFTABLE_ENTRY,    /* 16-bit PC Card Configuration */
+    [0x10c] = 0x12,            /* Tuple length = 18 bytes */
+    [0x10e] = 0xc3,            /* TPCE_INDX = I/O Secondary Mode, Default */
+    [0x110] = 0x41,            /* TPCE_IF = I/O and Memory, no BVD, no WP */
+    [0x112] = 0x99,            /* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
+    [0x114] = 0x27,            /* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
+    [0x116] = 0x55,            /* NomV: 5.0 V */
+    [0x118] = 0x4d,            /* MinV: 4.5 V */
+    [0x11a] = 0x5d,            /* MaxV: 5.5 V */
+    [0x11c] = 0x4e,            /* Peakl: 450 mA */
+    [0x11e] = 0xea,            /* TPCE_IO = 1K boundary, 16/8 access, Range */
+    [0x120] = 0x61,            /* Range: 2 fields, 2 byte addr, 1 byte len */
+    [0x122] = 0x70,            /* Field 1 address = 0x0170 */
+    [0x124] = 0x01,
+    [0x126] = 0x07,            /* Address block length = 8 */
+    [0x128] = 0x76,            /* Field 2 address = 0x0376 */
+    [0x12a] = 0x03,
+    [0x12c] = 0x01,            /* Address block length = 2 */
+    [0x12e] = 0xee,            /* TPCE_IR = IRQ E, Level, Pulse, Share */
+    [0x130] = 0x20,            /* TPCE_MI = support power down mode */
+
+    [0x132] = CISTPL_CFTABLE_ENTRY,    /* 16-bit PC Card Configuration */
+    [0x134] = 0x06,            /* Tuple length = 6 bytes */
+    [0x136] = 0x03,            /* TPCE_INDX = I/O Secondary Mode */
+    [0x138] = 0x01,            /* TPCE_FS = Vcc only, no I/O, no Memory */
+    [0x13a] = 0x21,            /* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
+    [0x13c] = 0xb5,            /* NomV: 3.3 V */
+    [0x13e] = 0x1e,
+    [0x140] = 0x3e,            /* Peakl: 350 mA */
+
+    [0x142] = CISTPL_NO_LINK,  /* No Link */
+    [0x144] = 0x00,            /* Tuple length = 0 bytes */
+
+    [0x146] = CISTPL_END,      /* Tuple End */
+};
+
+static int dscm1xxxx_attach(void *opaque)
+{
+    struct md_s *md = (struct md_s *) opaque;
+    md->card.attr_read = md_attr_read;
+    md->card.attr_write = md_attr_write;
+    md->card.common_read = md_common_read;
+    md->card.common_write = md_common_write;
+    md->card.io_read = md_common_read;
+    md->card.io_write = md_common_write;
+
+    md->attr_base = md->card.cis[0x74] | (md->card.cis[0x76] << 8);
+    md->io_base = 0x0;
+
+    md_reset(md);
+    md_interrupt_update(md);
+
+    md->card.slot->card_string = "DSCM-1xxxx Hitachi Microdrive";
+    return 0;
+}
+
+static int dscm1xxxx_detach(void *opaque)
+{
+    struct md_s *md = (struct md_s *) opaque;
+    md_reset(md);
+    return 0;
+}
+
+struct pcmcia_card_s *dscm1xxxx_init(BlockDriverState *bdrv)
+{
+    struct md_s *md = (struct md_s *) qemu_mallocz(sizeof(struct md_s));
+    md->card.state = md;
+    md->card.attach = dscm1xxxx_attach;
+    md->card.detach = dscm1xxxx_detach;
+    md->card.cis = dscm1xxxx_cis;
+    md->card.cis_len = sizeof(dscm1xxxx_cis);
+
+    ide_init2(md->ide, bdrv, 0, qemu_allocate_irqs(md_set_irq, md, 1)[0]);
+    md->ide->is_cf = 1;
+    md->ide->mdata_size = METADATA_SIZE;
+    md->ide->mdata_storage = (uint8_t *) qemu_mallocz(METADATA_SIZE);
+
+    register_savevm("microdrive", md_iid ++, 0, md_save, md_load, md);
+
+    return &md->card;
+}
+#endif
+
diff -r 092232fa1fbd extras/stubfw/ioemu/irq.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/ioemu/irq.c Fri Nov 16 03:43:56 2007 +0100
@@ -0,0 +1,72 @@
+/*
+ * QEMU IRQ/GPIO common code.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+struct IRQState {
+    qemu_irq_handler handler;
+    void *opaque;
+    int n;
+};
+
+void qemu_set_irq(qemu_irq irq, int level)
+{
+    if (!irq)
+        return;
+
+    if (irq->n == 0)
+      printk ("qemu_set_irq: irq=%d, caller=%lx\n", irq->n,
+             __builtin_return_address (0));
+    //printf("qemu_set_irq: irq=%d lvl=%d (not implemented)\n", irq->n, level);
+    irq->handler(irq->opaque, irq->n, level);
+}
+
+qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n)
+{
+    qemu_irq *s;
+    struct IRQState *p;
+    int i;
+
+    s = (qemu_irq *)qemu_mallocz(sizeof(qemu_irq) * n);
+    p = (struct IRQState *)qemu_mallocz(sizeof(struct IRQState) * n);
+    for (i = 0; i < n; i++) {
+        p->handler = handler;
+        p->opaque = opaque;
+        p->n = i;
+        s[i] = p;
+        p++;
+    }
+    return s;
+}
+
+static void qemu_notirq(void *opaque, int line, int level)
+{
+    struct IRQState *irq = opaque;
+
+    irq->handler(irq->opaque, irq->n, !level);
+}
+
+qemu_irq qemu_irq_invert(qemu_irq irq)
+{
+    return qemu_allocate_irqs(qemu_notirq, irq, 1)[0];
+}
diff -r 092232fa1fbd extras/stubfw/ioemu/mc146818rtc.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/ioemu/mc146818rtc.c Wed Nov 21 16:13:21 2007 +0100
@@ -0,0 +1,625 @@
+/*
+ * QEMU MC146818 RTC emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+//#define DEBUG_CMOS
+
+#define RTC_SECONDS             0
+#define RTC_SECONDS_ALARM       1
+#define RTC_MINUTES             2
+#define RTC_MINUTES_ALARM       3
+#define RTC_HOURS               4
+#define RTC_HOURS_ALARM         5
+#define RTC_ALARM_DONT_CARE    0xC0
+
+#define RTC_DAY_OF_WEEK         6
+#define RTC_DAY_OF_MONTH        7
+#define RTC_MONTH               8
+#define RTC_YEAR                9
+
+#define RTC_REG_A               10
+#define RTC_REG_B               11
+#define RTC_REG_C               12
+#define RTC_REG_D               13
+
+#define REG_A_UIP 0x80
+
+#define REG_B_SET 0x80
+#define REG_B_PIE 0x40
+#define REG_B_AIE 0x20
+#define REG_B_UIE 0x10
+
+struct RTCState {
+    uint8_t cmos_data[128];
+    uint8_t cmos_index;
+  //    struct tm current_tm;
+    qemu_irq irq;
+    target_phys_addr_t base;
+    int it_shift;
+#ifndef IOEMU
+    /* periodic timer */
+    QEMUTimer *periodic_timer;
+    int64_t next_periodic_time;
+    /* second update */
+    int64_t next_second_time;
+    QEMUTimer *second_timer;
+    QEMUTimer *second_timer2;
+#endif
+};
+
+#ifndef IOEMU
+static void rtc_set_time(RTCState *s);
+static void rtc_copy_date(RTCState *s);
+
+static void rtc_timer_update(RTCState *s, int64_t current_time)
+{
+    int period_code, period;
+    int64_t cur_clock, next_irq_clock;
+
+    period_code = s->cmos_data[RTC_REG_A] & 0x0f;
+    if (period_code != 0 &&
+        (s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
+        if (period_code <= 2)
+            period_code += 7;
+        /* period in 32 Khz cycles */
+        period = 1 << (period_code - 1);
+        /* compute 32 khz clock */
+        cur_clock = muldiv64(current_time, 32768, ticks_per_sec);
+        next_irq_clock = (cur_clock & ~(period - 1)) + period;
+        s->next_periodic_time = muldiv64(next_irq_clock, ticks_per_sec, 32768) 
+ 1;
+        qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
+    } else {
+        qemu_del_timer(s->periodic_timer);
+    }
+}
+
+static void rtc_periodic_timer(void *opaque)
+{
+    RTCState *s = opaque;
+
+    rtc_timer_update(s, s->next_periodic_time);
+    s->cmos_data[RTC_REG_C] |= 0xc0;
+    qemu_irq_raise(s->irq);
+}
+#endif
+
+void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
+{
+    RTCState *s = opaque;
+
+    if ((addr & 1) == 0) {
+        s->cmos_index = data & 0x7f;
+    } else {
+#ifdef DEBUG_CMOS
+        printf("cmos: write index=0x%02x val=0x%02x\n",
+               s->cmos_index, data);
+#endif
+        switch(s->cmos_index) {
+        case RTC_SECONDS_ALARM:
+        case RTC_MINUTES_ALARM:
+        case RTC_HOURS_ALARM:
+            /* XXX: not supported */
+            s->cmos_data[s->cmos_index] = data;
+            break;
+        case RTC_SECONDS:
+        case RTC_MINUTES:
+        case RTC_HOURS:
+        case RTC_DAY_OF_WEEK:
+        case RTC_DAY_OF_MONTH:
+        case RTC_MONTH:
+        case RTC_YEAR:
+            s->cmos_data[s->cmos_index] = data;
+            /* if in set mode, do not update the time */
+            if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
+#ifndef IOEMU
+                rtc_set_time(s);
+#endif
+            }
+            break;
+        case RTC_REG_A:
+            /* UIP bit is read only */
+            s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
+                (s->cmos_data[RTC_REG_A] & REG_A_UIP);
+#ifndef IOEMU
+            rtc_timer_update(s, qemu_get_clock(vm_clock));
+#endif
+            break;
+        case RTC_REG_B:
+            if (data & REG_B_SET) {
+                /* set mode: reset UIP mode */
+                s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
+                data &= ~REG_B_UIE;
+            } else {
+                /* if disabling set mode, update the time */
+                if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
+#ifndef IOEMU
+                    rtc_set_time(s);
+#endif
+                }
+            }
+            s->cmos_data[RTC_REG_B] = data;
+#ifndef IOEMU
+            rtc_timer_update(s, qemu_get_clock(vm_clock));
+#endif
+            break;
+        case RTC_REG_C:
+        case RTC_REG_D:
+            /* cannot write to them */
+            break;
+        default:
+            s->cmos_data[s->cmos_index] = data;
+            break;
+        }
+    }
+}
+
+static inline int to_bcd(RTCState *s, int a)
+{
+    if (s->cmos_data[RTC_REG_B] & 0x04) {
+        return a;
+    } else {
+        return ((a / 10) << 4) | (a % 10);
+    }
+}
+
+static inline int from_bcd(RTCState *s, int a)
+{
+    if (s->cmos_data[RTC_REG_B] & 0x04) {
+        return a;
+    } else {
+        return ((a >> 4) * 10) + (a & 0x0f);
+    }
+}
+
+#ifndef IOEMU
+static void rtc_set_time(RTCState *s)
+{
+    struct tm *tm = &s->current_tm;
+
+    tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]);
+    tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]);
+    tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
+    if (!(s->cmos_data[RTC_REG_B] & 0x02) &&
+        (s->cmos_data[RTC_HOURS] & 0x80)) {
+        tm->tm_hour += 12;
+    }
+    tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]);
+    tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
+    tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
+    tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + 100;
+}
+
+static void rtc_copy_date(RTCState *s)
+{
+    const struct tm *tm = &s->current_tm;
+
+    s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
+    s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
+    if (s->cmos_data[RTC_REG_B] & 0x02) {
+        /* 24 hour format */
+        s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour);
+    } else {
+        /* 12 hour format */
+        s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12);
+        if (tm->tm_hour >= 12)
+            s->cmos_data[RTC_HOURS] |= 0x80;
+    }
+    s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday);
+    s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday);
+    s->cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1);
+    s->cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100);
+}
+
+/* month is between 0 and 11. */
+static int get_days_in_month(int month, int year)
+{
+    static const int days_tab[12] = {
+        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+    };
+    int d;
+    if ((unsigned )month >= 12)
+        return 31;
+    d = days_tab[month];
+    if (month == 1) {
+        if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
+            d++;
+    }
+    return d;
+}
+
+/* update 'tm' to the next second */
+static void rtc_next_second(struct tm *tm)
+{
+    int days_in_month;
+
+    tm->tm_sec++;
+    if ((unsigned)tm->tm_sec >= 60) {
+        tm->tm_sec = 0;
+        tm->tm_min++;
+        if ((unsigned)tm->tm_min >= 60) {
+            tm->tm_min = 0;
+            tm->tm_hour++;
+            if ((unsigned)tm->tm_hour >= 24) {
+                tm->tm_hour = 0;
+                /* next day */
+                tm->tm_wday++;
+                if ((unsigned)tm->tm_wday >= 7)
+                    tm->tm_wday = 0;
+                days_in_month = get_days_in_month(tm->tm_mon,
+                                                  tm->tm_year + 1900);
+                tm->tm_mday++;
+                if (tm->tm_mday < 1) {
+                    tm->tm_mday = 1;
+                } else if (tm->tm_mday > days_in_month) {
+                    tm->tm_mday = 1;
+                    tm->tm_mon++;
+                    if (tm->tm_mon >= 12) {
+                        tm->tm_mon = 0;
+                        tm->tm_year++;
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+static void rtc_update_second(void *opaque)
+{
+    RTCState *s = opaque;
+    int64_t delay;
+
+    /* if the oscillator is not in normal operation, we do not update */
+    if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) {
+        s->next_second_time += ticks_per_sec;
+        qemu_mod_timer(s->second_timer, s->next_second_time);
+    } else {
+        rtc_next_second(&s->current_tm);
+
+        if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
+            /* update in progress bit */
+            s->cmos_data[RTC_REG_A] |= REG_A_UIP;
+        }
+        /* should be 244 us = 8 / 32768 seconds, but currently the
+           timers do not have the necessary resolution. */
+        delay = (ticks_per_sec * 1) / 100;
+        if (delay < 1)
+            delay = 1;
+        qemu_mod_timer(s->second_timer2,
+                       s->next_second_time + delay);
+    }
+}
+
+static void rtc_update_second2(void *opaque)
+{
+    RTCState *s = opaque;
+
+    if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
+        rtc_copy_date(s);
+    }
+
+    /* check alarm */
+    if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
+        if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
+             s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) &&
+            ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
+             s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) &&
+            ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
+             s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
+
+            s->cmos_data[RTC_REG_C] |= 0xa0;
+            qemu_irq_raise(s->irq);
+        }
+    }
+
+    /* update ended interrupt */
+    if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
+        s->cmos_data[RTC_REG_C] |= 0x90;
+        qemu_irq_raise(s->irq);
+    }
+
+    /* clear update in progress bit */
+    s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
+
+    s->next_second_time += ticks_per_sec;
+    qemu_mod_timer(s->second_timer, s->next_second_time);
+}
+#endif
+
+uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
+{
+    RTCState *s = opaque;
+    int ret;
+    if ((addr & 1) == 0) {
+        return 0xff;
+    } else {
+        switch(s->cmos_index) {
+        case RTC_SECONDS:
+         ret = s->cmos_data[s->cmos_index]++;
+        case RTC_MINUTES:
+        case RTC_HOURS:
+        case RTC_DAY_OF_WEEK:
+        case RTC_DAY_OF_MONTH:
+        case RTC_MONTH:
+        case RTC_YEAR:
+            ret = s->cmos_data[s->cmos_index];
+            break;
+        case RTC_REG_A:
+            ret = s->cmos_data[s->cmos_index];
+            break;
+        case RTC_REG_C:
+            ret = s->cmos_data[s->cmos_index];
+            qemu_irq_lower(s->irq);
+            s->cmos_data[RTC_REG_C] = 0x00;
+            break;
+        default:
+            ret = s->cmos_data[s->cmos_index];
+            break;
+        }
+#ifdef DEBUG_CMOS
+        printf("cmos: read index=0x%02x val=0x%02x\n",
+               s->cmos_index, ret);
+#endif
+        return ret;
+    }
+}
+
+void rtc_set_memory(RTCState *s, int addr, int val)
+{
+    if (addr >= 0 && addr <= 127)
+        s->cmos_data[addr] = val;
+}
+
+#ifndef IOEMU
+void rtc_set_date(RTCState *s, const struct tm *tm)
+{
+    s->current_tm = *tm;
+    rtc_copy_date(s);
+}
+#endif
+
+/* PC cmos mappings */
+#define REG_IBM_CENTURY_BYTE        0x32
+#define REG_IBM_PS2_CENTURY_BYTE    0x37
+
+#ifndef IOEMU
+void rtc_set_date_from_host(RTCState *s)
+{
+    time_t ti;
+    struct tm *tm;
+    int val;
+
+    /* set the CMOS date */
+    if (rtc_start_date == -1) {
+        time(&ti);
+        if (rtc_utc)
+            tm = gmtime(&ti);
+        else
+            tm = localtime(&ti);
+    } else {
+        ti = rtc_start_date;
+        tm = gmtime(&ti);
+    }
+    rtc_set_date(s, tm);
+
+    val = to_bcd(s, (tm->tm_year / 100) + 19);
+    rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
+    rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
+}
+
+static void rtc_save(QEMUFile *f, void *opaque)
+{
+    RTCState *s = opaque;
+
+    qemu_put_buffer(f, s->cmos_data, 128);
+    qemu_put_8s(f, &s->cmos_index);
+
+    qemu_put_be32s(f, &s->current_tm.tm_sec);
+    qemu_put_be32s(f, &s->current_tm.tm_min);
+    qemu_put_be32s(f, &s->current_tm.tm_hour);
+    qemu_put_be32s(f, &s->current_tm.tm_wday);
+    qemu_put_be32s(f, &s->current_tm.tm_mday);
+    qemu_put_be32s(f, &s->current_tm.tm_mon);
+    qemu_put_be32s(f, &s->current_tm.tm_year);
+
+    qemu_put_timer(f, s->periodic_timer);
+    qemu_put_be64s(f, &s->next_periodic_time);
+
+    qemu_put_be64s(f, &s->next_second_time);
+    qemu_put_timer(f, s->second_timer);
+    qemu_put_timer(f, s->second_timer2);
+}
+
+static int rtc_load(QEMUFile *f, void *opaque, int version_id)
+{
+    RTCState *s = opaque;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    qemu_get_buffer(f, s->cmos_data, 128);
+    qemu_get_8s(f, &s->cmos_index);
+
+    qemu_get_be32s(f, &s->current_tm.tm_sec);
+    qemu_get_be32s(f, &s->current_tm.tm_min);
+    qemu_get_be32s(f, &s->current_tm.tm_hour);
+    qemu_get_be32s(f, &s->current_tm.tm_wday);
+    qemu_get_be32s(f, &s->current_tm.tm_mday);
+    qemu_get_be32s(f, &s->current_tm.tm_mon);
+    qemu_get_be32s(f, &s->current_tm.tm_year);
+
+    qemu_get_timer(f, s->periodic_timer);
+    qemu_get_be64s(f, &s->next_periodic_time);
+
+    qemu_get_be64s(f, &s->next_second_time);
+    qemu_get_timer(f, s->second_timer);
+    qemu_get_timer(f, s->second_timer2);
+    return 0;
+}
+#endif
+
+RTCState *rtc_init(int base, qemu_irq irq)
+{
+    RTCState *s;
+
+    s = qemu_mallocz(sizeof(RTCState));
+    if (!s)
+        return NULL;
+
+    s->irq = irq;
+    s->cmos_data[RTC_REG_A] = 0x26;
+    s->cmos_data[RTC_REG_B] = 0x02;
+    s->cmos_data[RTC_REG_C] = 0x00;
+    s->cmos_data[RTC_REG_D] = 0x80;
+
+#ifndef IOEMU
+    rtc_set_date_from_host(s);
+
+    s->periodic_timer = qemu_new_timer(vm_clock,
+                                       rtc_periodic_timer, s);
+    s->second_timer = qemu_new_timer(vm_clock,
+                                     rtc_update_second, s);
+    s->second_timer2 = qemu_new_timer(vm_clock,
+                                      rtc_update_second2, s);
+
+    s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 
100;
+    qemu_mod_timer(s->second_timer2, s->next_second_time);
+#endif
+
+    register_ioport_write(base, 2, 1, cmos_ioport_write, s);
+    register_ioport_read(base, 2, 1, cmos_ioport_read, s);
+
+    register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
+
+    return s;
+}
+
+#ifndef IOEMU
+/* Memory mapped interface */
+uint32_t cmos_mm_readb (void *opaque, target_phys_addr_t addr)
+{
+    RTCState *s = opaque;
+
+    return cmos_ioport_read(s, (addr - s->base) >> s->it_shift) & 0xFF;
+}
+
+void cmos_mm_writeb (void *opaque,
+                     target_phys_addr_t addr, uint32_t value)
+{
+    RTCState *s = opaque;
+
+    cmos_ioport_write(s, (addr - s->base) >> s->it_shift, value & 0xFF);
+}
+
+uint32_t cmos_mm_readw (void *opaque, target_phys_addr_t addr)
+{
+    RTCState *s = opaque;
+    uint32_t val;
+
+    val = cmos_ioport_read(s, (addr - s->base) >> s->it_shift) & 0xFFFF;
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap16(val);
+#endif
+    return val;
+}
+
+void cmos_mm_writew (void *opaque,
+                     target_phys_addr_t addr, uint32_t value)
+{
+    RTCState *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+    value = bswap16(value);
+#endif
+    cmos_ioport_write(s, (addr - s->base) >> s->it_shift, value & 0xFFFF);
+}
+
+uint32_t cmos_mm_readl (void *opaque, target_phys_addr_t addr)
+{
+    RTCState *s = opaque;
+    uint32_t val;
+
+    val = cmos_ioport_read(s, (addr - s->base) >> s->it_shift);
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    return val;
+}
+
+void cmos_mm_writel (void *opaque,
+                     target_phys_addr_t addr, uint32_t value)
+{
+    RTCState *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+    value = bswap32(value);
+#endif
+    cmos_ioport_write(s, (addr - s->base) >> s->it_shift, value);
+}
+
+static CPUReadMemoryFunc *rtc_mm_read[] = {
+    &cmos_mm_readb,
+    &cmos_mm_readw,
+    &cmos_mm_readl,
+};
+
+static CPUWriteMemoryFunc *rtc_mm_write[] = {
+    &cmos_mm_writeb,
+    &cmos_mm_writew,
+    &cmos_mm_writel,
+};
+
+RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq)
+{
+    RTCState *s;
+    int io_memory;
+
+    s = qemu_mallocz(sizeof(RTCState));
+    if (!s)
+        return NULL;
+
+    s->irq = irq;
+    s->cmos_data[RTC_REG_A] = 0x26;
+    s->cmos_data[RTC_REG_B] = 0x02;
+    s->cmos_data[RTC_REG_C] = 0x00;
+    s->cmos_data[RTC_REG_D] = 0x80;
+    s->base = base;
+
+    rtc_set_date_from_host(s);
+
+    s->periodic_timer = qemu_new_timer(vm_clock,
+                                       rtc_periodic_timer, s);
+    s->second_timer = qemu_new_timer(vm_clock,
+                                     rtc_update_second, s);
+    s->second_timer2 = qemu_new_timer(vm_clock,
+                                      rtc_update_second2, s);
+
+    s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 
100;
+    qemu_mod_timer(s->second_timer2, s->next_second_time);
+
+    io_memory = cpu_register_io_memory(0, rtc_mm_read, rtc_mm_write, s);
+    cpu_register_physical_memory(base, 2 << it_shift, io_memory);
+
+    register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
+    return s;
+}
+#endif
diff -r 092232fa1fbd extras/stubfw/ioemu/monitor.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/ioemu/monitor.c     Sun Nov 18 08:08:19 2007 +0100
@@ -0,0 +1,1956 @@
+/*
+ * QEMU monitor
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "ctype.h"
+//#include "disas.h"
+
+//#define DEBUG
+//#define DEBUG_COMPLETION
+
+#ifndef offsetof
+#define offsetof(type, field) ((size_t) &((type *)0)->field)
+#endif
+
+/*
+ * Supported types:
+ *
+ * 'F'          filename
+ * 'B'          block device name
+ * 's'          string (accept optional quote)
+ * 'i'          32 bit integer
+ * 'l'          target long (32 or 64 bit)
+ * '/'          optional gdb-like print format (like "/10x")
+ *
+ * '?'          optional type (for 'F', 's' and 'i')
+ *
+ */
+
+typedef void (*cmd_handler)(void);
+typedef struct term_cmd_t {
+    const char *name;
+    const char *args_type;
+    void (*handler)(void);
+    const char *params;
+    const char *help;
+} term_cmd_t;
+
+#define MAX_MON 4
+static CharDriverState *monitor_hd[MAX_MON];
+static int hide_banner;
+
+static term_cmd_t term_cmds[];
+static term_cmd_t info_cmds[];
+
+static char term_outbuf[1024];
+static int term_outbuf_index;
+
+static void monitor_start_input(void);
+
+void term_flush(void)
+{
+    int i;
+    if (term_outbuf_index > 0) {
+        for (i = 0; i < MAX_MON; i++)
+            if (monitor_hd[i] && monitor_hd[i]->focus == 0)
+                qemu_chr_write(monitor_hd[i], term_outbuf, term_outbuf_index);
+        term_outbuf_index = 0;
+    }
+}
+
+/* flush at every end of line or if the buffer is full */
+void term_puts(const char *str)
+{
+    int c;
+    for(;;) {
+        c = *str++;
+        if (c == '\0')
+            break;
+        if (c == '\n')
+            term_outbuf[term_outbuf_index++] = '\r';
+        term_outbuf[term_outbuf_index++] = c;
+        if (term_outbuf_index >= (sizeof(term_outbuf) - 1) ||
+            c == '\n')
+            term_flush();
+    }
+}
+
+void term_vprintf(const char *fmt, va_list ap)
+{
+    char buf[4096];
+    vsnprintf(buf, sizeof(buf), fmt, ap);
+    term_puts(buf);
+}
+
+void term_printf(const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    term_vprintf(fmt, ap);
+    va_end(ap);
+}
+
+void term_print_filename(const char *filename)
+{
+    int i;
+
+    for (i = 0; filename[i]; i++) {
+       switch (filename[i]) {
+       case ' ':
+       case '"':
+       case '\\':
+           term_printf("\\%c", filename[i]);
+           break;
+       case '\t':
+           term_printf("\\t");
+           break;
+       case '\r':
+           term_printf("\\r");
+           break;
+       case '\n':
+           term_printf("\\n");
+           break;
+       default:
+           term_printf("%c", filename[i]);
+           break;
+       }
+    }
+}
+
+static int compare_cmd(const char *name, const char *list)
+{
+    const char *p, *pstart;
+    int len;
+    len = strlen(name);
+    p = list;
+    for(;;) {
+        pstart = p;
+        p = strchr(p, '|');
+        if (!p)
+            p = pstart + strlen(pstart);
+        if ((p - pstart) == len && !memcmp(pstart, name, len))
+            return 1;
+        if (*p == '\0')
+            break;
+        p++;
+    }
+    return 0;
+}
+
+static void help_cmd1(term_cmd_t *cmds, const char *prefix, const char *name)
+{
+    term_cmd_t *cmd;
+
+    for(cmd = cmds; cmd->name != NULL; cmd++) {
+        if (!name || !strcmp(name, cmd->name))
+            term_printf("%s%s %s -- %s\n", prefix, cmd->name, cmd->params, 
cmd->help);
+    }
+}
+
+static void help_cmd(const char *name)
+{
+    if (name && !strcmp(name, "info")) {
+        help_cmd1(info_cmds, "info ", NULL);
+    } else {
+        help_cmd1(term_cmds, "", name);
+    }
+}
+
+static void do_help(const char *name)
+{
+    help_cmd(name);
+}
+
+static void do_commit(const char *device)
+{
+    int i, all_devices;
+
+    all_devices = !strcmp(device, "all");
+    for (i = 0; i < MAX_DISKS; i++) {
+        if (bs_table[i]) {
+            if (all_devices ||
+                !strcmp(bdrv_get_device_name(bs_table[i]), device))
+                bdrv_commit(bs_table[i]);
+        }
+    }
+    if (mtd_bdrv)
+        if (all_devices || !strcmp(bdrv_get_device_name(mtd_bdrv), device))
+            bdrv_commit(mtd_bdrv);
+}
+
+static void do_info(const char *item)
+{
+    term_cmd_t *cmd;
+
+    if (!item)
+        goto help;
+    for(cmd = info_cmds; cmd->name != NULL; cmd++) {
+        if (compare_cmd(item, cmd->name))
+            goto found;
+    }
+ help:
+    help_cmd("info");
+    return;
+ found:
+    cmd->handler();
+}
+
+static void do_info_version(void)
+{
+  term_printf("%s\n", QEMU_VERSION);
+}
+
+
+static void do_info_block(void)
+{
+    bdrv_info();
+}
+
+
+static void do_info_history (void)
+{
+    int i;
+    const char *str;
+
+    i = 0;
+    for(;;) {
+        str = readline_get_history(i);
+        if (!str)
+            break;
+       term_printf("%d: '%s'\n", i, str);
+        i++;
+    }
+}
+
+#if defined(TARGET_PPC)
+/* XXX: not implemented in other targets */
+static void do_info_cpu_stats (void)
+{
+    CPUState *env;
+
+    env = mon_get_cpu();
+    cpu_dump_statistics(env, NULL, &monitor_fprintf, 0);
+}
+#endif
+
+static void do_quit(void)
+{
+    exit();
+}
+
+static int eject_device(BlockDriverState *bs, int force)
+{
+    if (bdrv_is_inserted(bs)) {
+        if (!force) {
+            if (!bdrv_is_removable(bs)) {
+                term_printf("device is not removable\n");
+                return -1;
+            }
+            if (bdrv_is_locked(bs)) {
+                term_printf("device is locked\n");
+                return -1;
+            }
+        }
+        bdrv_close(bs);
+    }
+    return 0;
+}
+
+static void do_eject(int force, const char *filename)
+{
+    BlockDriverState *bs;
+
+    bs = bdrv_find(filename);
+    if (!bs) {
+        term_printf("device not found\n");
+        return;
+    }
+    eject_device(bs, force);
+}
+
+
+static void term_printc(int c)
+{
+    term_printf("'");
+    switch(c) {
+    case '\'':
+        term_printf("\\'");
+        break;
+    case '\\':
+        term_printf("\\\\");
+        break;
+    case '\n':
+        term_printf("\\n");
+        break;
+    case '\r':
+        term_printf("\\r");
+        break;
+    default:
+        if (c >= 32 && c <= 126) {
+            term_printf("%c", c);
+        } else {
+            term_printf("\\x%02x", c);
+        }
+        break;
+    }
+    term_printf("'");
+}
+
+static void memory_dump(int count, int format, int wsize,
+                        target_phys_addr_t addr, int is_physical)
+{
+    int nb_per_line, l, line_size, i, max_digits, len;
+    uint8_t buf[16];
+    uint64_t v;
+
+#if 0
+    if (format == 'i') {
+       CPUState *env;
+        int flags;
+        flags = 0;
+        env = mon_get_cpu();
+        if (!env && !is_physical)
+            return;
+#ifdef TARGET_I386
+        if (wsize == 2) {
+            flags = 1;
+        } else if (wsize == 4) {
+            flags = 0;
+        } else {
+            /* as default we use the current CS size */
+            flags = 0;
+            if (env) {
+#ifdef TARGET_X86_64
+                if ((env->efer & MSR_EFER_LMA) &&
+                    (env->segs[R_CS].flags & DESC_L_MASK))
+                    flags = 2;
+                else
+#endif
+                if (!(env->segs[R_CS].flags & DESC_B_MASK))
+                    flags = 1;
+            }
+        }
+#endif
+        monitor_disas(env, addr, count, is_physical, flags);
+        return;
+    }
+#endif
+
+    len = wsize * count;
+    if (wsize == 1)
+        line_size = 8;
+    else
+        line_size = 16;
+    nb_per_line = line_size / wsize;
+    max_digits = 0;
+
+    switch(format) {
+    case 'o':
+        max_digits = (wsize * 8 + 2) / 3;
+        break;
+    default:
+    case 'x':
+        max_digits = (wsize * 8) / 4;
+        break;
+    case 'u':
+    case 'd':
+        max_digits = (wsize * 8 * 10 + 32) / 33;
+        break;
+    case 'c':
+        wsize = 1;
+        break;
+    }
+
+    while (len > 0) {
+        if (is_physical)
+            term_printf(TARGET_FMT_plx ":", addr);
+        else
+            term_printf(TARGET_FMT_lx ":", (target_ulong)addr);
+        l = len;
+        if (l > line_size)
+            l = line_size;
+       cpu_physical_memory_rw(addr, buf, l, 0);
+        i = 0;
+        while (i < l) {
+            switch(wsize) {
+            default:
+            case 1:
+                v = ldub_raw(buf + i);
+                break;
+            case 2:
+                v = lduw_raw(buf + i);
+                break;
+            case 4:
+                v = (uint32_t)ldl_raw(buf + i);
+                break;
+            case 8:
+                v = ldq_raw(buf + i);
+                break;
+            }
+            term_printf(" ");
+            switch(format) {
+            case 'o':
+                term_printf("%#*" PRIo64, max_digits, v);
+                break;
+            case 'x':
+                term_printf("0x%0*" PRIx64, max_digits, v);
+                break;
+            case 'u':
+                term_printf("%*" PRIu64, max_digits, v);
+                break;
+            case 'd':
+                term_printf("%*" PRId64, max_digits, v);
+                break;
+            case 'c':
+                term_printc(v);
+                break;
+            }
+            i += wsize;
+        }
+        term_printf("\n");
+        addr += l;
+        len -= l;
+    }
+}
+
+#if TARGET_LONG_BITS == 64
+#define GET_TLONG(h, l) (((uint64_t)(h) << 32) | (l))
+#else
+#define GET_TLONG(h, l) (l)
+#endif
+
+static void do_memory_dump(int count, int format, int size,
+                           uint32_t addrh, uint32_t addrl)
+{
+    target_long addr = GET_TLONG(addrh, addrl);
+    memory_dump(count, format, size, addr, 0);
+}
+
+#if TARGET_PHYS_ADDR_BITS > 32
+#define GET_TPHYSADDR(h, l) (((uint64_t)(h) << 32) | (l))
+#else
+#define GET_TPHYSADDR(h, l) (l)
+#endif
+
+static void do_physical_memory_dump(int count, int format, int size,
+                                    uint32_t addrh, uint32_t addrl)
+
+{
+    target_phys_addr_t addr = GET_TPHYSADDR(addrh, addrl);
+    memory_dump(count, format, size, addr, 1);
+}
+
+static void do_print(int count, int format, int size, unsigned int valh, 
unsigned int vall)
+{
+    target_phys_addr_t val = GET_TPHYSADDR(valh, vall);
+#if TARGET_PHYS_ADDR_BITS == 32
+    switch(format) {
+    case 'o':
+        term_printf("%#o", val);
+        break;
+    case 'x':
+        term_printf("%#x", val);
+        break;
+    case 'u':
+        term_printf("%u", val);
+        break;
+    default:
+    case 'd':
+        term_printf("%d", val);
+        break;
+    case 'c':
+        term_printc(val);
+        break;
+    }
+#else
+    switch(format) {
+    case 'o':
+        term_printf("%#" PRIo64, val);
+        break;
+    case 'x':
+        term_printf("%#" PRIx64, val);
+        break;
+    case 'u':
+        term_printf("%" PRIu64, val);
+        break;
+    default:
+    case 'd':
+        term_printf("%" PRId64, val);
+        break;
+    case 'c':
+        term_printc(val);
+        break;
+    }
+#endif
+    term_printf("\n");
+}
+
+static void do_sum(uint32_t start, uint32_t size)
+{
+    uint32_t addr;
+    uint8_t buf[1];
+    uint16_t sum;
+
+    sum = 0;
+    for(addr = start; addr < (start + size); addr++) {
+        cpu_physical_memory_rw(addr, buf, 1, 0);
+        /* BSD sum algorithm ('sum' Unix command) */
+        sum = (sum >> 1) | (sum << 15);
+        sum += buf[0];
+    }
+    term_printf("%05d\n", sum);
+}
+
+static void do_ioport_read(int count, int format, int size, int addr, int 
has_index, int index)
+{
+    uint32_t val;
+    int suffix;
+
+    if (has_index) {
+        cpu_outb(addr & 0xffff, index & 0xff);
+        addr++;
+    }
+    addr &= 0xffff;
+
+    switch(size) {
+    default:
+    case 1:
+        val = cpu_inb(addr);
+        suffix = 'b';
+        break;
+    case 2:
+        val = cpu_inw(addr);
+        suffix = 'w';
+        break;
+    case 4:
+        val = cpu_inl(addr);
+        suffix = 'l';
+        break;
+    }
+    term_printf("port%c[0x%04x] = %#0*x\n",
+                suffix, addr, size * 2, val);
+}
+
+#if defined(TARGET_I386)
+static void print_pte(uint32_t addr, uint32_t pte, uint32_t mask)
+{
+    term_printf("%08x: %08x %c%c%c%c%c%c%c%c\n",
+                addr,
+                pte & mask,
+                pte & PG_GLOBAL_MASK ? 'G' : '-',
+                pte & PG_PSE_MASK ? 'P' : '-',
+                pte & PG_DIRTY_MASK ? 'D' : '-',
+                pte & PG_ACCESSED_MASK ? 'A' : '-',
+                pte & PG_PCD_MASK ? 'C' : '-',
+                pte & PG_PWT_MASK ? 'T' : '-',
+                pte & PG_USER_MASK ? 'U' : '-',
+                pte & PG_RW_MASK ? 'W' : '-');
+}
+
+static void tlb_info(void)
+{
+    CPUState *env;
+    int l1, l2;
+    uint32_t pgd, pde, pte;
+
+    env = mon_get_cpu();
+    if (!env)
+        return;
+
+    if (!(env->cr[0] & CR0_PG_MASK)) {
+        term_printf("PG disabled\n");
+        return;
+    }
+    pgd = env->cr[3] & ~0xfff;
+    for(l1 = 0; l1 < 1024; l1++) {
+        cpu_physical_memory_read(pgd + l1 * 4, (uint8_t *)&pde, 4);
+        pde = le32_to_cpu(pde);
+        if (pde & PG_PRESENT_MASK) {
+            if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
+                print_pte((l1 << 22), pde, ~((1 << 20) - 1));
+            } else {
+                for(l2 = 0; l2 < 1024; l2++) {
+                    cpu_physical_memory_read((pde & ~0xfff) + l2 * 4,
+                                             (uint8_t *)&pte, 4);
+                    pte = le32_to_cpu(pte);
+                    if (pte & PG_PRESENT_MASK) {
+                        print_pte((l1 << 22) + (l2 << 12),
+                                  pte & ~PG_PSE_MASK,
+                                  ~0xfff);
+                    }
+                }
+            }
+        }
+    }
+}
+
+static void mem_print(uint32_t *pstart, int *plast_prot,
+                      uint32_t end, int prot)
+{
+    int prot1;
+    prot1 = *plast_prot;
+    if (prot != prot1) {
+        if (*pstart != -1) {
+            term_printf("%08x-%08x %08x %c%c%c\n",
+                        *pstart, end, end - *pstart,
+                        prot1 & PG_USER_MASK ? 'u' : '-',
+                        'r',
+                        prot1 & PG_RW_MASK ? 'w' : '-');
+        }
+        if (prot != 0)
+            *pstart = end;
+        else
+            *pstart = -1;
+        *plast_prot = prot;
+    }
+}
+
+static void mem_info(void)
+{
+    CPUState *env;
+    int l1, l2, prot, last_prot;
+    uint32_t pgd, pde, pte, start, end;
+
+    env = mon_get_cpu();
+    if (!env)
+        return;
+
+    if (!(env->cr[0] & CR0_PG_MASK)) {
+        term_printf("PG disabled\n");
+        return;
+    }
+    pgd = env->cr[3] & ~0xfff;
+    last_prot = 0;
+    start = -1;
+    for(l1 = 0; l1 < 1024; l1++) {
+        cpu_physical_memory_read(pgd + l1 * 4, (uint8_t *)&pde, 4);
+        pde = le32_to_cpu(pde);
+        end = l1 << 22;
+        if (pde & PG_PRESENT_MASK) {
+            if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
+                prot = pde & (PG_USER_MASK | PG_RW_MASK | PG_PRESENT_MASK);
+                mem_print(&start, &last_prot, end, prot);
+            } else {
+                for(l2 = 0; l2 < 1024; l2++) {
+                    cpu_physical_memory_read((pde & ~0xfff) + l2 * 4,
+                                             (uint8_t *)&pte, 4);
+                    pte = le32_to_cpu(pte);
+                    end = (l1 << 22) + (l2 << 12);
+                    if (pte & PG_PRESENT_MASK) {
+                        prot = pte & (PG_USER_MASK | PG_RW_MASK | 
PG_PRESENT_MASK);
+                    } else {
+                        prot = 0;
+                    }
+                    mem_print(&start, &last_prot, end, prot);
+                }
+            }
+        } else {
+            prot = 0;
+            mem_print(&start, &last_prot, end, prot);
+        }
+    }
+}
+#endif
+
+static void do_info_kqemu(void)
+{
+#ifdef USE_KQEMU
+    CPUState *env;
+    int val;
+    val = 0;
+    env = mon_get_cpu();
+    if (!env) {
+        term_printf("No cpu initialized yet");
+        return;
+    }
+    val = env->kqemu_enabled;
+    term_printf("kqemu support: ");
+    switch(val) {
+    default:
+    case 0:
+        term_printf("disabled\n");
+        break;
+    case 1:
+        term_printf("enabled for user code\n");
+        break;
+    case 2:
+        term_printf("enabled for user and kernel code\n");
+        break;
+    }
+#else
+    term_printf("kqemu support: not compiled\n");
+#endif
+}
+
+
+static term_cmd_t term_cmds[] = {
+    { "help|?", "s?", (cmd_handler)do_help,
+      "[cmd]", "show the help" },
+    { "commit", "s", (cmd_handler)do_commit,
+      "device|all", "commit changes to the disk images (if -snapshot is used) 
or backing files" },
+    { "info", "s?", (cmd_handler)do_info,
+      "subcommand", "show various information about the system state" },
+    { "q|quit", "", do_quit,
+      "", "quit the emulator" },
+    { "eject", "-fB", (cmd_handler)do_eject,
+      "[-f] device", "eject a removable medium (use -f to force it)" },
+    { "x", "/l", (cmd_handler)do_memory_dump,
+      "/fmt addr", "virtual memory dump starting at 'addr'", },
+    { "xp", "/l", (cmd_handler)do_physical_memory_dump,
+      "/fmt addr", "physical memory dump starting at 'addr'", },
+    { "p|print", "/l", (cmd_handler)do_print,
+      "/fmt expr", "print expression value (use $reg for CPU register 
access)", },
+    { "i", "/ii.", (cmd_handler)do_ioport_read,
+      "/fmt addr", "I/O port read" },
+
+    { "sum", "ii", (cmd_handler)do_sum,
+      "addr size", "compute the checksum of a memory region" },
+    { NULL, NULL, },
+};
+
+static term_cmd_t info_cmds[] = {
+    { "version", "", do_info_version,
+      "", "show the version of qemu" },
+#if 0
+    { "network", "", (cmd_handler)do_info_network,
+      "", "show the network state" },
+    { "block", "", (cmd_handler)do_info_block,
+      "", "show the block devices" },
+    { "registers", "", (cmd_handler)do_info_registers,
+      "", "show the cpu registers" },
+    { "cpus", "", (cmd_handler)do_info_cpus,
+      "", "show infos for each CPU" },
+#endif
+    { "history", "", (cmd_handler)do_info_history,
+      "", "show the command line history", },
+#if 0
+    { "irq", "", irq_info,
+      "", "show the interrupts statistics (if available)", },
+    { "pic", "", pic_info,
+      "", "show i8259 (PIC) state", },
+#endif
+    { "pci", "", pci_info,
+      "", "show PCI info", },
+#if defined(TARGET_I386)
+    { "tlb", "", tlb_info,
+      "", "show virtual to physical memory mappings", },
+    { "mem", "", mem_info,
+      "", "show the active virtual memory mappings", },
+#endif
+#if defined(TARGET_PPC)
+    { "cpustats", "", do_info_cpu_stats,
+      "", "show CPU statistics", },
+#endif
+#if defined(CONFIG_SLIRP)
+    { "slirp", "", do_info_slirp,
+      "", "show SLIRP statistics", },
+#endif
+    { NULL, NULL, },
+};
+
+/*******************************************************************/
+
+static const char *pch;
+//static jmp_buf expr_env;
+
+#define MD_TLONG 0
+#define MD_I32   1
+
+typedef struct MonitorDef {
+    const char *name;
+    int offset;
+    target_long (*get_value)(struct MonitorDef *md, int val);
+    int type;
+} MonitorDef;
+
+#if defined(TARGET_I386)
+static target_long monitor_get_pc (struct MonitorDef *md, int val)
+{
+    CPUState *env = mon_get_cpu();
+    if (!env)
+        return 0;
+    return env->eip + env->segs[R_CS].base;
+}
+#endif
+
+#if defined(TARGET_PPC)
+static target_long monitor_get_ccr (struct MonitorDef *md, int val)
+{
+    CPUState *env = mon_get_cpu();
+    unsigned int u;
+    int i;
+
+    if (!env)
+        return 0;
+
+    u = 0;
+    for (i = 0; i < 8; i++)
+       u |= env->crf[i] << (32 - (4 * i));
+
+    return u;
+}
+
+static target_long monitor_get_msr (struct MonitorDef *md, int val)
+{
+    CPUState *env = mon_get_cpu();
+    if (!env)
+        return 0;
+    return env->msr;
+}
+
+static target_long monitor_get_xer (struct MonitorDef *md, int val)
+{
+    CPUState *env = mon_get_cpu();
+    if (!env)
+        return 0;
+    return ppc_load_xer(env);
+}
+
+static target_long monitor_get_decr (struct MonitorDef *md, int val)
+{
+    CPUState *env = mon_get_cpu();
+    if (!env)
+        return 0;
+    return cpu_ppc_load_decr(env);
+}
+
+static target_long monitor_get_tbu (struct MonitorDef *md, int val)
+{
+    CPUState *env = mon_get_cpu();
+    if (!env)
+        return 0;
+    return cpu_ppc_load_tbu(env);
+}
+
+static target_long monitor_get_tbl (struct MonitorDef *md, int val)
+{
+    CPUState *env = mon_get_cpu();
+    if (!env)
+        return 0;
+    return cpu_ppc_load_tbl(env);
+}
+#endif
+
+#if defined(TARGET_SPARC)
+#ifndef TARGET_SPARC64
+static target_long monitor_get_psr (struct MonitorDef *md, int val)
+{
+    CPUState *env = mon_get_cpu();
+    if (!env)
+        return 0;
+    return GET_PSR(env);
+}
+#endif
+
+static target_long monitor_get_reg(struct MonitorDef *md, int val)
+{
+    CPUState *env = mon_get_cpu();
+    if (!env)
+        return 0;
+    return env->regwptr[val];
+}
+#endif
+
+static MonitorDef monitor_defs[] = {
+#ifdef TARGET_I386
+
+#define SEG(name, seg) \
+    { name, offsetof(CPUState, segs[seg].selector), NULL, MD_I32 },\
+    { name ".base", offsetof(CPUState, segs[seg].base) },\
+    { name ".limit", offsetof(CPUState, segs[seg].limit), NULL, MD_I32 },
+
+    { "eax", offsetof(CPUState, regs[0]) },
+    { "ecx", offsetof(CPUState, regs[1]) },
+    { "edx", offsetof(CPUState, regs[2]) },
+    { "ebx", offsetof(CPUState, regs[3]) },
+    { "esp|sp", offsetof(CPUState, regs[4]) },
+    { "ebp|fp", offsetof(CPUState, regs[5]) },
+    { "esi", offsetof(CPUState, regs[6]) },
+    { "edi", offsetof(CPUState, regs[7]) },
+#ifdef TARGET_X86_64
+    { "r8", offsetof(CPUState, regs[8]) },
+    { "r9", offsetof(CPUState, regs[9]) },
+    { "r10", offsetof(CPUState, regs[10]) },
+    { "r11", offsetof(CPUState, regs[11]) },
+    { "r12", offsetof(CPUState, regs[12]) },
+    { "r13", offsetof(CPUState, regs[13]) },
+    { "r14", offsetof(CPUState, regs[14]) },
+    { "r15", offsetof(CPUState, regs[15]) },
+#endif
+    { "eflags", offsetof(CPUState, eflags) },
+    { "eip", offsetof(CPUState, eip) },
+    SEG("cs", R_CS)
+    SEG("ds", R_DS)
+    SEG("es", R_ES)
+    SEG("ss", R_SS)
+    SEG("fs", R_FS)
+    SEG("gs", R_GS)
+    { "pc", 0, monitor_get_pc, },
+#elif defined(TARGET_PPC)
+    /* General purpose registers */
+    { "r0", offsetof(CPUState, gpr[0]) },
+    { "r1", offsetof(CPUState, gpr[1]) },
+    { "r2", offsetof(CPUState, gpr[2]) },
+    { "r3", offsetof(CPUState, gpr[3]) },
+    { "r4", offsetof(CPUState, gpr[4]) },
+    { "r5", offsetof(CPUState, gpr[5]) },
+    { "r6", offsetof(CPUState, gpr[6]) },
+    { "r7", offsetof(CPUState, gpr[7]) },
+    { "r8", offsetof(CPUState, gpr[8]) },
+    { "r9", offsetof(CPUState, gpr[9]) },
+    { "r10", offsetof(CPUState, gpr[10]) },
+    { "r11", offsetof(CPUState, gpr[11]) },
+    { "r12", offsetof(CPUState, gpr[12]) },
+    { "r13", offsetof(CPUState, gpr[13]) },
+    { "r14", offsetof(CPUState, gpr[14]) },
+    { "r15", offsetof(CPUState, gpr[15]) },
+    { "r16", offsetof(CPUState, gpr[16]) },
+    { "r17", offsetof(CPUState, gpr[17]) },
+    { "r18", offsetof(CPUState, gpr[18]) },
+    { "r19", offsetof(CPUState, gpr[19]) },
+    { "r20", offsetof(CPUState, gpr[20]) },
+    { "r21", offsetof(CPUState, gpr[21]) },
+    { "r22", offsetof(CPUState, gpr[22]) },
+    { "r23", offsetof(CPUState, gpr[23]) },
+    { "r24", offsetof(CPUState, gpr[24]) },
+    { "r25", offsetof(CPUState, gpr[25]) },
+    { "r26", offsetof(CPUState, gpr[26]) },
+    { "r27", offsetof(CPUState, gpr[27]) },
+    { "r28", offsetof(CPUState, gpr[28]) },
+    { "r29", offsetof(CPUState, gpr[29]) },
+    { "r30", offsetof(CPUState, gpr[30]) },
+    { "r31", offsetof(CPUState, gpr[31]) },
+    /* Floating point registers */
+    { "f0", offsetof(CPUState, fpr[0]) },
+    { "f1", offsetof(CPUState, fpr[1]) },
+    { "f2", offsetof(CPUState, fpr[2]) },
+    { "f3", offsetof(CPUState, fpr[3]) },
+    { "f4", offsetof(CPUState, fpr[4]) },
+    { "f5", offsetof(CPUState, fpr[5]) },
+    { "f6", offsetof(CPUState, fpr[6]) },
+    { "f7", offsetof(CPUState, fpr[7]) },
+    { "f8", offsetof(CPUState, fpr[8]) },
+    { "f9", offsetof(CPUState, fpr[9]) },
+    { "f10", offsetof(CPUState, fpr[10]) },
+    { "f11", offsetof(CPUState, fpr[11]) },
+    { "f12", offsetof(CPUState, fpr[12]) },
+    { "f13", offsetof(CPUState, fpr[13]) },
+    { "f14", offsetof(CPUState, fpr[14]) },
+    { "f15", offsetof(CPUState, fpr[15]) },
+    { "f16", offsetof(CPUState, fpr[16]) },
+    { "f17", offsetof(CPUState, fpr[17]) },
+    { "f18", offsetof(CPUState, fpr[18]) },
+    { "f19", offsetof(CPUState, fpr[19]) },
+    { "f20", offsetof(CPUState, fpr[20]) },
+    { "f21", offsetof(CPUState, fpr[21]) },
+    { "f22", offsetof(CPUState, fpr[22]) },
+    { "f23", offsetof(CPUState, fpr[23]) },
+    { "f24", offsetof(CPUState, fpr[24]) },
+    { "f25", offsetof(CPUState, fpr[25]) },
+    { "f26", offsetof(CPUState, fpr[26]) },
+    { "f27", offsetof(CPUState, fpr[27]) },
+    { "f28", offsetof(CPUState, fpr[28]) },
+    { "f29", offsetof(CPUState, fpr[29]) },
+    { "f30", offsetof(CPUState, fpr[30]) },
+    { "f31", offsetof(CPUState, fpr[31]) },
+    { "fpscr", offsetof(CPUState, fpscr) },
+    /* Next instruction pointer */
+    { "nip|pc", offsetof(CPUState, nip) },
+    { "lr", offsetof(CPUState, lr) },
+    { "ctr", offsetof(CPUState, ctr) },
+    { "decr", 0, &monitor_get_decr, },
+    { "ccr", 0, &monitor_get_ccr, },
+    /* Machine state register */
+    { "msr", 0, &monitor_get_msr, },
+    { "xer", 0, &monitor_get_xer, },
+    { "tbu", 0, &monitor_get_tbu, },
+    { "tbl", 0, &monitor_get_tbl, },
+#if defined(TARGET_PPC64)
+    /* Address space register */
+    { "asr", offsetof(CPUState, asr) },
+#endif
+    /* Segment registers */
+    { "sdr1", offsetof(CPUState, sdr1) },
+    { "sr0", offsetof(CPUState, sr[0]) },
+    { "sr1", offsetof(CPUState, sr[1]) },
+    { "sr2", offsetof(CPUState, sr[2]) },
+    { "sr3", offsetof(CPUState, sr[3]) },
+    { "sr4", offsetof(CPUState, sr[4]) },
+    { "sr5", offsetof(CPUState, sr[5]) },
+    { "sr6", offsetof(CPUState, sr[6]) },
+    { "sr7", offsetof(CPUState, sr[7]) },
+    { "sr8", offsetof(CPUState, sr[8]) },
+    { "sr9", offsetof(CPUState, sr[9]) },
+    { "sr10", offsetof(CPUState, sr[10]) },
+    { "sr11", offsetof(CPUState, sr[11]) },
+    { "sr12", offsetof(CPUState, sr[12]) },
+    { "sr13", offsetof(CPUState, sr[13]) },
+    { "sr14", offsetof(CPUState, sr[14]) },
+    { "sr15", offsetof(CPUState, sr[15]) },
+    /* Too lazy to put BATs and SPRs ... */
+#elif defined(TARGET_SPARC)
+    { "g0", offsetof(CPUState, gregs[0]) },
+    { "g1", offsetof(CPUState, gregs[1]) },
+    { "g2", offsetof(CPUState, gregs[2]) },
+    { "g3", offsetof(CPUState, gregs[3]) },
+    { "g4", offsetof(CPUState, gregs[4]) },
+    { "g5", offsetof(CPUState, gregs[5]) },
+    { "g6", offsetof(CPUState, gregs[6]) },
+    { "g7", offsetof(CPUState, gregs[7]) },
+    { "o0", 0, monitor_get_reg },
+    { "o1", 1, monitor_get_reg },
+    { "o2", 2, monitor_get_reg },
+    { "o3", 3, monitor_get_reg },
+    { "o4", 4, monitor_get_reg },
+    { "o5", 5, monitor_get_reg },
+    { "o6", 6, monitor_get_reg },
+    { "o7", 7, monitor_get_reg },
+    { "l0", 8, monitor_get_reg },
+    { "l1", 9, monitor_get_reg },
+    { "l2", 10, monitor_get_reg },
+    { "l3", 11, monitor_get_reg },
+    { "l4", 12, monitor_get_reg },
+    { "l5", 13, monitor_get_reg },
+    { "l6", 14, monitor_get_reg },
+    { "l7", 15, monitor_get_reg },
+    { "i0", 16, monitor_get_reg },
+    { "i1", 17, monitor_get_reg },
+    { "i2", 18, monitor_get_reg },
+    { "i3", 19, monitor_get_reg },
+    { "i4", 20, monitor_get_reg },
+    { "i5", 21, monitor_get_reg },
+    { "i6", 22, monitor_get_reg },
+    { "i7", 23, monitor_get_reg },
+    { "pc", offsetof(CPUState, pc) },
+    { "npc", offsetof(CPUState, npc) },
+    { "y", offsetof(CPUState, y) },
+#ifndef TARGET_SPARC64
+    { "psr", 0, &monitor_get_psr, },
+    { "wim", offsetof(CPUState, wim) },
+#endif
+    { "tbr", offsetof(CPUState, tbr) },
+    { "fsr", offsetof(CPUState, fsr) },
+    { "f0", offsetof(CPUState, fpr[0]) },
+    { "f1", offsetof(CPUState, fpr[1]) },
+    { "f2", offsetof(CPUState, fpr[2]) },
+    { "f3", offsetof(CPUState, fpr[3]) },
+    { "f4", offsetof(CPUState, fpr[4]) },
+    { "f5", offsetof(CPUState, fpr[5]) },
+    { "f6", offsetof(CPUState, fpr[6]) },
+    { "f7", offsetof(CPUState, fpr[7]) },
+    { "f8", offsetof(CPUState, fpr[8]) },
+    { "f9", offsetof(CPUState, fpr[9]) },
+    { "f10", offsetof(CPUState, fpr[10]) },
+    { "f11", offsetof(CPUState, fpr[11]) },
+    { "f12", offsetof(CPUState, fpr[12]) },
+    { "f13", offsetof(CPUState, fpr[13]) },
+    { "f14", offsetof(CPUState, fpr[14]) },
+    { "f15", offsetof(CPUState, fpr[15]) },
+    { "f16", offsetof(CPUState, fpr[16]) },
+    { "f17", offsetof(CPUState, fpr[17]) },
+    { "f18", offsetof(CPUState, fpr[18]) },
+    { "f19", offsetof(CPUState, fpr[19]) },
+    { "f20", offsetof(CPUState, fpr[20]) },
+    { "f21", offsetof(CPUState, fpr[21]) },
+    { "f22", offsetof(CPUState, fpr[22]) },
+    { "f23", offsetof(CPUState, fpr[23]) },
+    { "f24", offsetof(CPUState, fpr[24]) },
+    { "f25", offsetof(CPUState, fpr[25]) },
+    { "f26", offsetof(CPUState, fpr[26]) },
+    { "f27", offsetof(CPUState, fpr[27]) },
+    { "f28", offsetof(CPUState, fpr[28]) },
+    { "f29", offsetof(CPUState, fpr[29]) },
+    { "f30", offsetof(CPUState, fpr[30]) },
+    { "f31", offsetof(CPUState, fpr[31]) },
+#ifdef TARGET_SPARC64
+    { "f32", offsetof(CPUState, fpr[32]) },
+    { "f34", offsetof(CPUState, fpr[34]) },
+    { "f36", offsetof(CPUState, fpr[36]) },
+    { "f38", offsetof(CPUState, fpr[38]) },
+    { "f40", offsetof(CPUState, fpr[40]) },
+    { "f42", offsetof(CPUState, fpr[42]) },
+    { "f44", offsetof(CPUState, fpr[44]) },
+    { "f46", offsetof(CPUState, fpr[46]) },
+    { "f48", offsetof(CPUState, fpr[48]) },
+    { "f50", offsetof(CPUState, fpr[50]) },
+    { "f52", offsetof(CPUState, fpr[52]) },
+    { "f54", offsetof(CPUState, fpr[54]) },
+    { "f56", offsetof(CPUState, fpr[56]) },
+    { "f58", offsetof(CPUState, fpr[58]) },
+    { "f60", offsetof(CPUState, fpr[60]) },
+    { "f62", offsetof(CPUState, fpr[62]) },
+    { "asi", offsetof(CPUState, asi) },
+    { "pstate", offsetof(CPUState, pstate) },
+    { "cansave", offsetof(CPUState, cansave) },
+    { "canrestore", offsetof(CPUState, canrestore) },
+    { "otherwin", offsetof(CPUState, otherwin) },
+    { "wstate", offsetof(CPUState, wstate) },
+    { "cleanwin", offsetof(CPUState, cleanwin) },
+    { "fprs", offsetof(CPUState, fprs) },
+#endif
+#endif
+    { NULL },
+};
+
+static void expr_error(const char *fmt)
+{
+    term_printf(fmt);
+    term_printf("\n");
+    //longjmp(expr_env, 1);
+}
+
+/* return 0 if OK, -1 if not found, -2 if no CPU defined */
+static int get_monitor_def(target_long *pval, const char *name)
+{
+    MonitorDef *md;
+
+    for(md = monitor_defs; md->name != NULL; md++) {
+        if (compare_cmd(name, md->name)) {
+            if (md->get_value) {
+                *pval = md->get_value(md, md->offset);
+            } else {
+#if 0
+               void *ptr;
+                CPUState *env = mon_get_cpu();
+                if (!env)
+                    return -2;
+                ptr = (uint8_t *)env + md->offset;
+                switch(md->type) {
+                case MD_I32:
+                    *pval = *(int32_t *)ptr;
+                    break;
+                case MD_TLONG:
+                    *pval = *(target_long *)ptr;
+                    break;
+                default:
+                    *pval = 0;
+                    break;
+                }
+#else
+               return -2;
+#endif
+            }
+            return 0;
+        }
+    }
+    return -1;
+}
+
+static void next(void)
+{
+    if (pch != '\0') {
+        pch++;
+        while (*pch == ' ')
+            pch++;
+    }
+}
+
+static int64_t expr_sum(void);
+
+static int64_t expr_unary(void)
+{
+    int64_t n;
+    char *p;
+    int ret;
+
+    switch(*pch) {
+    case '+':
+        next();
+        n = expr_unary();
+        break;
+    case '-':
+        next();
+        n = -expr_unary();
+        break;
+    case '~':
+        next();
+        n = ~expr_unary();
+        break;
+    case '(':
+        next();
+        n = expr_sum();
+        if (*pch != ')') {
+            expr_error("')' expected");
+        }
+        next();
+        break;
+    case '\'':
+        pch++;
+        if (*pch == '\0')
+            expr_error("character constant expected");
+        n = *pch;
+        pch++;
+        if (*pch != '\'')
+            expr_error("missing terminating \' character");
+        next();
+        break;
+    case '$':
+        {
+            char buf[128], *q;
+            target_long reg;
+
+            pch++;
+            q = buf;
+            while ((*pch >= 'a' && *pch <= 'z') ||
+                   (*pch >= 'A' && *pch <= 'Z') ||
+                   (*pch >= '0' && *pch <= '9') ||
+                   *pch == '_' || *pch == '.') {
+                if ((q - buf) < sizeof(buf) - 1)
+                    *q++ = *pch;
+                pch++;
+            }
+            while (isspace(*pch))
+                pch++;
+            *q = 0;
+            ret = get_monitor_def(&reg, buf);
+            if (ret == -1)
+                expr_error("unknown register");
+            else if (ret == -2)
+                expr_error("no cpu defined");
+            n = reg;
+        }
+        break;
+    case '\0':
+        expr_error("unexpected end of expression");
+        n = 0;
+        break;
+    default:
+#if TARGET_PHYS_ADDR_BITS > 32
+        n = simple_strtoull(pch, &p, 0);
+#else
+        n = strtoul(pch, &p, 0);
+#endif
+        if (pch == p) {
+            expr_error("invalid char in expression");
+        }
+        pch = p;
+        while (isspace(*pch))
+            pch++;
+        break;
+    }
+    return n;
+}
+
+
+static int64_t expr_prod(void)
+{
+    int64_t val, val2;
+    int op;
+
+    val = expr_unary();
+    for(;;) {
+        op = *pch;
+        if (op != '*' && op != '/' && op != '%')
+            break;
+        next();
+        val2 = expr_unary();
+        switch(op) {
+        default:
+        case '*':
+            val *= val2;
+            break;
+        case '/':
+        case '%':
+            if (val2 == 0)
+                expr_error("division by zero");
+            if (op == '/')
+                val /= val2;
+            else
+                val %= val2;
+            break;
+        }
+    }
+    return val;
+}
+
+static int64_t expr_logic(void)
+{
+    int64_t val, val2;
+    int op;
+
+    val = expr_prod();
+    for(;;) {
+        op = *pch;
+        if (op != '&' && op != '|' && op != '^')
+            break;
+        next();
+        val2 = expr_prod();
+        switch(op) {
+        default:
+        case '&':
+            val &= val2;
+            break;
+        case '|':
+            val |= val2;
+            break;
+        case '^':
+            val ^= val2;
+            break;
+        }
+    }
+    return val;
+}
+
+static int64_t expr_sum(void)
+{
+    int64_t val, val2;
+    int op;
+
+    val = expr_logic();
+    for(;;) {
+        op = *pch;
+        if (op != '+' && op != '-')
+            break;
+        next();
+        val2 = expr_logic();
+        if (op == '+')
+            val += val2;
+        else
+            val -= val2;
+    }
+    return val;
+}
+
+static int get_expr(int64_t *pval, const char **pp)
+{
+    pch = *pp;
+#if 0
+    if (setjmp(expr_env)) {
+        *pp = pch;
+        return -1;
+    }
+#endif
+    while (isspace(*pch))
+        pch++;
+    *pval = expr_sum();
+    *pp = pch;
+    return 0;
+}
+
+static int get_str(char *buf, int buf_size, const char **pp)
+{
+    const char *p;
+    char *q;
+    int c;
+
+    q = buf;
+    p = *pp;
+    while (isspace(*p))
+        p++;
+    if (*p == '\0') {
+    fail:
+        *q = '\0';
+        *pp = p;
+        return -1;
+    }
+    if (*p == '\"') {
+        p++;
+        while (*p != '\0' && *p != '\"') {
+            if (*p == '\\') {
+                p++;
+                c = *p++;
+                switch(c) {
+                case 'n':
+                    c = '\n';
+                    break;
+                case 'r':
+                    c = '\r';
+                    break;
+                case '\\':
+                case '\'':
+                case '\"':
+                    break;
+                default:
+                    qemu_printf("unsupported escape code: '\\%c'\n", c);
+                    goto fail;
+                }
+                if ((q - buf) < buf_size - 1) {
+                    *q++ = c;
+                }
+            } else {
+                if ((q - buf) < buf_size - 1) {
+                    *q++ = *p;
+                }
+                p++;
+            }
+        }
+        if (*p != '\"') {
+            qemu_printf("unterminated string\n");
+            goto fail;
+        }
+        p++;
+    } else {
+        while (*p != '\0' && !isspace(*p)) {
+            if ((q - buf) < buf_size - 1) {
+                *q++ = *p;
+            }
+            p++;
+        }
+    }
+    *q = '\0';
+    *pp = p;
+    return 0;
+}
+
+static int default_fmt_format = 'x';
+static int default_fmt_size = 4;
+
+#define MAX_ARGS 16
+
+static void monitor_handle_command(const char *cmdline)
+{
+    const char *p, *pstart, *typestr;
+    char *q;
+    int c, nb_args, len, i, has_arg;
+    term_cmd_t *cmd;
+    char cmdname[256];
+    char buf[1024];
+    void *str_allocated[MAX_ARGS];
+    void *args[MAX_ARGS];
+
+#ifdef DEBUG
+    term_printf("command='%s'\n", cmdline);
+#endif
+
+    /* extract the command name */
+    p = cmdline;
+    q = cmdname;
+    while (isspace(*p))
+        p++;
+    if (*p == '\0')
+        return;
+    pstart = p;
+    while (*p != '\0' && *p != '/' && !isspace(*p))
+        p++;
+    len = p - pstart;
+    if (len > sizeof(cmdname) - 1)
+        len = sizeof(cmdname) - 1;
+    memcpy(cmdname, pstart, len);
+    cmdname[len] = '\0';
+
+    /* find the command */
+    for(cmd = term_cmds; cmd->name != NULL; cmd++) {
+        if (compare_cmd(cmdname, cmd->name))
+            goto found;
+    }
+    term_printf("unknown command: '%s'\n", cmdname);
+    return;
+ found:
+
+    for(i = 0; i < MAX_ARGS; i++)
+        str_allocated[i] = NULL;
+
+    /* parse the parameters */
+    typestr = cmd->args_type;
+    nb_args = 0;
+    for(;;) {
+        c = *typestr;
+        if (c == '\0')
+            break;
+        typestr++;
+        switch(c) {
+        case 'F':
+        case 'B':
+        case 's':
+            {
+                int ret;
+                char *str;
+
+                while (isspace(*p))
+                    p++;
+                if (*typestr == '?') {
+                    typestr++;
+                    if (*p == '\0') {
+                        /* no optional string: NULL argument */
+                        str = NULL;
+                        goto add_str;
+                    }
+                }
+                ret = get_str(buf, sizeof(buf), &p);
+                if (ret < 0) {
+                    switch(c) {
+                    case 'F':
+                        term_printf("%s: filename expected\n", cmdname);
+                        break;
+                    case 'B':
+                        term_printf("%s: block device name expected\n", 
cmdname);
+                        break;
+                    default:
+                        term_printf("%s: string expected\n", cmdname);
+                        break;
+                    }
+                    goto fail;
+                }
+                str = qemu_malloc(strlen(buf) + 1);
+                strcpy(str, buf);
+                str_allocated[nb_args] = str;
+            add_str:
+                if (nb_args >= MAX_ARGS) {
+                error_args:
+                    term_printf("%s: too many arguments\n", cmdname);
+                    goto fail;
+                }
+                args[nb_args++] = str;
+            }
+            break;
+        case '/':
+            {
+                int count, format, size;
+
+                while (isspace(*p))
+                    p++;
+                if (*p == '/') {
+                    /* format found */
+                    p++;
+                    count = 1;
+                    if (isdigit(*p)) {
+                        count = 0;
+                        while (isdigit(*p)) {
+                            count = count * 10 + (*p - '0');
+                            p++;
+                        }
+                    }
+                    size = -1;
+                    format = -1;
+                    for(;;) {
+                        switch(*p) {
+                        case 'o':
+                        case 'd':
+                        case 'u':
+                        case 'x':
+                        case 'i':
+                        case 'c':
+                            format = *p++;
+                            break;
+                        case 'b':
+                            size = 1;
+                            p++;
+                            break;
+                        case 'h':
+                            size = 2;
+                            p++;
+                            break;
+                        case 'w':
+                            size = 4;
+                            p++;
+                            break;
+                        case 'g':
+                        case 'L':
+                            size = 8;
+                            p++;
+                            break;
+                        default:
+                            goto next;
+                        }
+                    }
+                next:
+                    if (*p != '\0' && !isspace(*p)) {
+                        term_printf("invalid char in format: '%c'\n", *p);
+                        goto fail;
+                    }
+                    if (format < 0)
+                        format = default_fmt_format;
+                    if (format != 'i') {
+                        /* for 'i', not specifying a size gives -1 as size */
+                        if (size < 0)
+                            size = default_fmt_size;
+                    }
+                    default_fmt_size = size;
+                    default_fmt_format = format;
+                } else {
+                    count = 1;
+                    format = default_fmt_format;
+                    if (format != 'i') {
+                        size = default_fmt_size;
+                    } else {
+                        size = -1;
+                    }
+                }
+                if (nb_args + 3 > MAX_ARGS)
+                    goto error_args;
+                args[nb_args++] = (void*)(long)count;
+                args[nb_args++] = (void*)(long)format;
+                args[nb_args++] = (void*)(long)size;
+            }
+            break;
+        case 'i':
+        case 'l':
+            {
+                int64_t val;
+
+                while (isspace(*p))
+                    p++;
+                if (*typestr == '?' || *typestr == '.') {
+                    if (*typestr == '?') {
+                        if (*p == '\0')
+                            has_arg = 0;
+                        else
+                            has_arg = 1;
+                    } else {
+                        if (*p == '.') {
+                            p++;
+                            while (isspace(*p))
+                                p++;
+                            has_arg = 1;
+                        } else {
+                            has_arg = 0;
+                        }
+                    }
+                    typestr++;
+                    if (nb_args >= MAX_ARGS)
+                        goto error_args;
+                    args[nb_args++] = (void *)(long)has_arg;
+                    if (!has_arg) {
+                        if (nb_args >= MAX_ARGS)
+                            goto error_args;
+                        val = -1;
+                        goto add_num;
+                    }
+                }
+                if (get_expr(&val, &p))
+                    goto fail;
+            add_num:
+                if (c == 'i') {
+                    if (nb_args >= MAX_ARGS)
+                        goto error_args;
+                    args[nb_args++] = (void *)(long)val;
+                } else {
+                    if ((nb_args + 1) >= MAX_ARGS)
+                        goto error_args;
+#if TARGET_PHYS_ADDR_BITS > 32
+                    args[nb_args++] = (void *)(long)((val >> 32) & 0xffffffff);
+#else
+                    args[nb_args++] = (void *)0;
+#endif
+                    args[nb_args++] = (void *)(long)(val & 0xffffffff);
+                }
+            }
+            break;
+        case '-':
+            {
+                int has_option;
+                /* option */
+
+                c = *typestr++;
+                if (c == '\0')
+                    goto bad_type;
+                while (isspace(*p))
+                    p++;
+                has_option = 0;
+                if (*p == '-') {
+                    p++;
+                    if (*p != c) {
+                        term_printf("%s: unsupported option -%c\n",
+                                    cmdname, *p);
+                        goto fail;
+                    }
+                    p++;
+                    has_option = 1;
+                }
+                if (nb_args >= MAX_ARGS)
+                    goto error_args;
+                args[nb_args++] = (void *)(long)has_option;
+            }
+            break;
+        default:
+        bad_type:
+            term_printf("%s: unknown type '%c'\n", cmdname, c);
+            goto fail;
+        }
+    }
+    /* check that all arguments were parsed */
+    while (isspace(*p))
+        p++;
+    if (*p != '\0') {
+        term_printf("%s: extraneous characters at the end of line\n",
+                    cmdname);
+        goto fail;
+    }
+
+    switch(nb_args) {
+    case 0:
+        cmd->handler();
+        break;
+    case 1:
+        cmd->handler(args[0]);
+        break;
+    case 2:
+        cmd->handler(args[0], args[1]);
+        break;
+    case 3:
+        cmd->handler(args[0], args[1], args[2]);
+        break;
+    case 4:
+        cmd->handler(args[0], args[1], args[2], args[3]);
+        break;
+    case 5:
+        cmd->handler(args[0], args[1], args[2], args[3], args[4]);
+        break;
+    case 6:
+        cmd->handler(args[0], args[1], args[2], args[3], args[4], args[5]);
+        break;
+    case 7:
+        cmd->handler(args[0], args[1], args[2], args[3], args[4], args[5], 
args[6]);
+        break;
+    default:
+        term_printf("unsupported number of arguments: %d\n", nb_args);
+        goto fail;
+    }
+ fail:
+    for(i = 0; i < MAX_ARGS; i++)
+        qemu_free(str_allocated[i]);
+    return;
+}
+
+static void cmd_completion(const char *name, const char *list)
+{
+    const char *p, *pstart;
+    char cmd[128];
+    int len;
+
+    p = list;
+    for(;;) {
+        pstart = p;
+        p = strchr(p, '|');
+        if (!p)
+            p = pstart + strlen(pstart);
+        len = p - pstart;
+        if (len > sizeof(cmd) - 2)
+            len = sizeof(cmd) - 2;
+        memcpy(cmd, pstart, len);
+        cmd[len] = '\0';
+        if (name[0] == '\0' || !strncmp(name, cmd, strlen(name))) {
+            add_completion(cmd);
+        }
+        if (*p == '\0')
+            break;
+        p++;
+    }
+}
+
+
+static void block_completion_it(void *opaque, const char *name)
+{
+    const char *input = opaque;
+
+    if (input[0] == '\0' ||
+        !strncmp(name, (char *)input, strlen(input))) {
+        add_completion(name);
+    }
+}
+
+/* NOTE: this parser is an approximate form of the real command parser */
+static void parse_cmdline(const char *cmdline,
+                         int *pnb_args, char **args)
+{
+    const char *p;
+    int nb_args, ret;
+    char buf[1024];
+
+    p = cmdline;
+    nb_args = 0;
+    for(;;) {
+        while (isspace(*p))
+            p++;
+        if (*p == '\0')
+            break;
+        if (nb_args >= MAX_ARGS)
+            break;
+        ret = get_str(buf, sizeof(buf), &p);
+        args[nb_args] = qemu_strdup(buf);
+        nb_args++;
+        if (ret < 0)
+            break;
+    }
+    *pnb_args = nb_args;
+}
+
+void readline_find_completion(const char *cmdline)
+{
+    const char *cmdname;
+    char *args[MAX_ARGS];
+    int nb_args, i, len;
+    const char *ptype, *str;
+    term_cmd_t *cmd;
+    const KeyDef *key;
+
+    parse_cmdline(cmdline, &nb_args, args);
+#ifdef DEBUG_COMPLETION
+    for(i = 0; i < nb_args; i++) {
+        term_printf("arg%d = '%s'\n", i, (char *)args[i]);
+    }
+#endif
+
+    /* if the line ends with a space, it means we want to complete the
+       next arg */
+    len = strlen(cmdline);
+    if (len > 0 && isspace(cmdline[len - 1])) {
+        if (nb_args >= MAX_ARGS)
+            return;
+        args[nb_args++] = qemu_strdup("");
+    }
+    if (nb_args <= 1) {
+        /* command completion */
+        if (nb_args == 0)
+            cmdname = "";
+        else
+            cmdname = args[0];
+        completion_index = strlen(cmdname);
+        for(cmd = term_cmds; cmd->name != NULL; cmd++) {
+            cmd_completion(cmdname, cmd->name);
+        }
+    } else {
+        /* find the command */
+        for(cmd = term_cmds; cmd->name != NULL; cmd++) {
+            if (compare_cmd(args[0], cmd->name))
+                goto found;
+        }
+        return;
+    found:
+        ptype = cmd->args_type;
+        for(i = 0; i < nb_args - 2; i++) {
+            if (*ptype != '\0') {
+                ptype++;
+                while (*ptype == '?')
+                    ptype++;
+            }
+        }
+        str = args[nb_args - 1];
+        switch(*ptype) {
+        case 'B':
+            /* block device name completion */
+            completion_index = strlen(str);
+            bdrv_iterate(block_completion_it, (void *)str);
+            break;
+        case 's':
+            /* XXX: more generic ? */
+            if (!strcmp(cmd->name, "info")) {
+                completion_index = strlen(str);
+                for(cmd = info_cmds; cmd->name != NULL; cmd++) {
+                    cmd_completion(str, cmd->name);
+                }
+            } else if (!strcmp(cmd->name, "sendkey")) {
+                completion_index = strlen(str);
+                for(key = key_defs; key->name != NULL; key++) {
+                    cmd_completion(str, key->name);
+                }
+            }
+            break;
+        default:
+            break;
+        }
+    }
+    for(i = 0; i < nb_args; i++)
+        qemu_free(args[i]);
+}
+
+static int term_can_read(void *opaque)
+{
+    return 128;
+}
+
+static void term_read(void *opaque, const uint8_t *buf, int size)
+{
+    int i;
+    for(i = 0; i < size; i++)
+        readline_handle_byte(buf[i]);
+}
+
+static void monitor_start_input(void);
+
+static void monitor_handle_command1(void *opaque, const char *cmdline)
+{
+    monitor_handle_command(cmdline);
+    monitor_start_input();
+}
+
+static void monitor_start_input(void)
+{
+    readline_start("(qemu) ", 0, monitor_handle_command1, NULL);
+}
+
+static void term_event(void *opaque, int event)
+{
+    if (event != CHR_EVENT_RESET)
+       return;
+
+    if (!hide_banner)
+           term_printf("QEMU %s monitor - type 'help' for more information\n",
+                       QEMU_VERSION);
+    monitor_start_input();
+}
+
+static int is_first_init = 1;
+
+void monitor_init(CharDriverState *hd, int show_banner)
+{
+    int i;
+
+    if (is_first_init) {
+        for (i = 0; i < MAX_MON; i++) {
+            monitor_hd[i] = NULL;
+        }
+        is_first_init = 0;
+    }
+    for (i = 0; i < MAX_MON; i++) {
+        if (monitor_hd[i] == NULL) {
+            monitor_hd[i] = hd;
+            break;
+        }
+    }
+
+    hide_banner = !show_banner;
+
+    qemu_chr_add_handlers(hd, term_can_read, term_read, term_event, NULL);
+}
+
+/* XXX: use threads ? */
+/* modal monitor readline */
+static int monitor_readline_started;
+static char *monitor_readline_buf;
+static int monitor_readline_buf_size;
+
+static void monitor_readline_cb(void *opaque, const char *input)
+{
+    pstrcpy(monitor_readline_buf, monitor_readline_buf_size, input);
+    monitor_readline_started = 0;
+}
+
+void monitor_readline(const char *prompt, int is_password,
+                      char *buf, int buf_size)
+{
+    int i;
+
+    if (is_password) {
+        for (i = 0; i < MAX_MON; i++)
+            if (monitor_hd[i] && monitor_hd[i]->focus == 0)
+                qemu_chr_send_event(monitor_hd[i], CHR_EVENT_FOCUS);
+    }
+    readline_start(prompt, is_password, monitor_readline_cb, NULL);
+    monitor_readline_buf = buf;
+    monitor_readline_buf_size = buf_size;
+    monitor_readline_started = 1;
+    while (monitor_readline_started) {
+        main_loop_wait(10);
+    }
+}
diff -r 092232fa1fbd extras/stubfw/ioemu/pci.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/ioemu/pci.c Mon Nov 12 04:04:17 2007 +0100
@@ -0,0 +1,654 @@
+/*
+ * QEMU PCI bus manager
+ *
+ * Copyright (c) 2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+//#define DEBUG_PCI
+
+struct PCIBus {
+    int bus_num;
+    int devfn_min;
+    pci_set_irq_fn set_irq;
+    pci_map_irq_fn map_irq;
+    uint32_t config_reg; /* XXX: suppress */
+    /* low level pic */
+    SetIRQFunc *low_set_irq;
+    qemu_irq *irq_opaque;
+    PCIDevice *devices[256];
+    PCIDevice *parent_dev;
+    PCIBus *next;
+    /* The bus IRQ state is the logical OR of the connected devices.
+       Keep a count of the number of devices with raised IRQs.  */
+    int irq_count[];
+};
+
+static void pci_update_mappings(PCIDevice *d);
+static void pci_set_irq(void *opaque, int irq_num, int level);
+
+target_phys_addr_t pci_mem_base;
+static int pci_irq_index;
+static PCIBus *first_bus;
+
+PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+                         qemu_irq *pic, int devfn_min, int nirq)
+{
+    PCIBus *bus;
+    bus = qemu_mallocz(sizeof(PCIBus) + (nirq * sizeof(int)));
+    bus->set_irq = set_irq;
+    bus->map_irq = map_irq;
+    bus->irq_opaque = pic;
+    bus->devfn_min = devfn_min;
+    first_bus = bus;
+    return bus;
+}
+
+PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq)
+{
+    PCIBus *bus;
+    bus = qemu_mallocz(sizeof(PCIBus));
+    bus->map_irq = map_irq;
+    bus->parent_dev = dev;
+    bus->next = dev->bus->next;
+    dev->bus->next = bus;
+    return bus;
+}
+
+int pci_bus_num(PCIBus *s)
+{
+    return s->bus_num;
+}
+
+#ifndef IOEMU
+void pci_device_save(PCIDevice *s, QEMUFile *f)
+{
+    qemu_put_be32(f, 1); /* PCI device version */
+    qemu_put_buffer(f, s->config, 256);
+}
+
+int pci_device_load(PCIDevice *s, QEMUFile *f)
+{
+    uint32_t version_id;
+    version_id = qemu_get_be32(f);
+    if (version_id != 1)
+        return -EINVAL;
+    qemu_get_buffer(f, s->config, 256);
+    pci_update_mappings(s);
+    return 0;
+}
+#endif
+
+/* -1 for devfn means auto assign */
+PCIDevice *pci_register_device(PCIBus *bus, const char *name,
+                               int instance_size, int devfn,
+                               PCIConfigReadFunc *config_read,
+                               PCIConfigWriteFunc *config_write)
+{
+    PCIDevice *pci_dev;
+
+    if (pci_irq_index >= PCI_DEVICES_MAX)
+        return NULL;
+
+    if (devfn < 0) {
+        for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) {
+            if (!bus->devices[devfn])
+                goto found;
+        }
+        return NULL;
+    found: ;
+    }
+    pci_dev = qemu_mallocz(instance_size);
+    if (!pci_dev)
+        return NULL;
+    pci_dev->bus = bus;
+    pci_dev->devfn = devfn;
+    pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
+    memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
+
+    if (!config_read)
+        config_read = pci_default_read_config;
+    if (!config_write)
+        config_write = pci_default_write_config;
+    pci_dev->config_read = config_read;
+    pci_dev->config_write = config_write;
+    pci_dev->irq_index = pci_irq_index++;
+    bus->devices[devfn] = pci_dev;
+    pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, 4);
+    return pci_dev;
+}
+
+void pci_register_io_region(PCIDevice *pci_dev, int region_num,
+                            uint32_t size, int type,
+                            PCIMapIORegionFunc *map_func)
+{
+    PCIIORegion *r;
+    uint32_t addr;
+
+    if ((unsigned int)region_num >= PCI_NUM_REGIONS)
+        return;
+    r = &pci_dev->io_regions[region_num];
+    r->addr = -1;
+    r->size = size;
+    r->type = type;
+    r->map_func = map_func;
+    if (region_num == PCI_ROM_SLOT) {
+        addr = 0x30;
+    } else {
+        addr = 0x10 + region_num * 4;
+    }
+    *(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type);
+}
+
+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)
+{
+    PCIIORegion *r;
+    int cmd, i;
+    uint32_t last_addr, new_addr, config_ofs;
+
+    cmd = le16_to_cpu(*(uint16_t *)(d->config + PCI_COMMAND));
+    for(i = 0; i < PCI_NUM_REGIONS; i++) {
+        r = &d->io_regions[i];
+        if (i == PCI_ROM_SLOT) {
+            config_ofs = 0x30;
+        } else {
+            config_ofs = 0x10 + i * 4;
+        }
+        if (r->size != 0) {
+            if (r->type & PCI_ADDRESS_SPACE_IO) {
+                if (cmd & PCI_COMMAND_IO) {
+                    new_addr = le32_to_cpu(*(uint32_t *)(d->config +
+                                                         config_ofs));
+                    new_addr = new_addr & ~(r->size - 1);
+                    last_addr = new_addr + r->size - 1;
+                    /* NOTE: we have only 64K ioports on PC */
+                    if (last_addr <= new_addr || new_addr == 0 ||
+                        last_addr >= 0x10000) {
+                        new_addr = -1;
+                    }
+                } else {
+                    new_addr = -1;
+                }
+            } else {
+                if (cmd & PCI_COMMAND_MEMORY) {
+                    new_addr = le32_to_cpu(*(uint32_t *)(d->config +
+                                                         config_ofs));
+                    /* the ROM slot has a specific enable bit */
+                    if (i == PCI_ROM_SLOT && !(new_addr & 1))
+                        goto no_mem_map;
+                    new_addr = new_addr & ~(r->size - 1);
+                    last_addr = new_addr + r->size - 1;
+                    /* NOTE: we do not support wrapping */
+                    /* XXX: as we cannot support really dynamic
+                       mappings, we handle specific values as invalid
+                       mappings. */
+                    if (last_addr <= new_addr || new_addr == 0 ||
+                        last_addr == -1) {
+                        new_addr = -1;
+                    }
+                } else {
+                no_mem_map:
+                    new_addr = -1;
+                }
+            }
+            /* now do the real mapping */
+            if (new_addr != r->addr) {
+                if (r->addr != -1) {
+#ifndef IOEMU
+                    if (r->type & PCI_ADDRESS_SPACE_IO) {
+                        int class;
+                        /* NOTE: specific hack for IDE in PC case:
+                           only one byte must be mapped. */
+                        class = d->config[0x0a] | (d->config[0x0b] << 8);
+                        if (class == 0x0101 && r->size == 4) {
+                            isa_unassign_ioport(r->addr + 2, 1);
+                        } else {
+                            isa_unassign_ioport(r->addr, r->size);
+                        }
+                    } else {
+                        cpu_register_physical_memory(pci_to_cpu_addr(r->addr),
+                                                     r->size,
+                                                     IO_MEM_UNASSIGNED);
+                    }
+#endif
+                }
+                r->addr = new_addr;
+                if (r->addr != -1) {
+                    r->map_func(d, i, r->addr, r->size, r->type);
+                }
+            }
+        }
+    }
+}
+
+uint32_t pci_default_read_config(PCIDevice *d,
+                                 uint32_t address, int len)
+{
+    uint32_t val;
+
+    switch(len) {
+    default:
+    case 4:
+       if (address <= 0xfc) {
+           val = le32_to_cpu(*(uint32_t *)(d->config + address));
+           break;
+       }
+       /* fall through */
+    case 2:
+        if (address <= 0xfe) {
+           val = le16_to_cpu(*(uint16_t *)(d->config + address));
+           break;
+       }
+       /* fall through */
+    case 1:
+        val = d->config[address];
+        break;
+    }
+    return val;
+}
+
+void pci_default_write_config(PCIDevice *d,
+                              uint32_t address, uint32_t val, int len)
+{
+    int can_write, i;
+    uint32_t end, addr;
+
+    if (len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) ||
+                     (address >= 0x30 && address < 0x34))) {
+        PCIIORegion *r;
+        int reg;
+
+        if ( address >= 0x30 ) {
+            reg = PCI_ROM_SLOT;
+        }else{
+            reg = (address - 0x10) >> 2;
+        }
+        r = &d->io_regions[reg];
+        if (r->size == 0)
+            goto default_config;
+        /* compute the stored value */
+        if (reg == PCI_ROM_SLOT) {
+            /* keep ROM enable bit */
+            val &= (~(r->size - 1)) | 1;
+        } else {
+            val &= ~(r->size - 1);
+            val |= r->type;
+        }
+        *(uint32_t *)(d->config + address) = cpu_to_le32(val);
+        pci_update_mappings(d);
+        return;
+    }
+ default_config:
+    /* not efficient, but simple */
+    addr = address;
+    for(i = 0; i < len; i++) {
+        /* default read/write accesses */
+        switch(d->config[0x0e]) {
+        case 0x00:
+        case 0x80:
+            switch(addr) {
+            case 0x00:
+            case 0x01:
+            case 0x02:
+            case 0x03:
+            case 0x08:
+            case 0x09:
+            case 0x0a:
+            case 0x0b:
+            case 0x0e:
+            case 0x10 ... 0x27: /* base */
+            case 0x30 ... 0x33: /* rom */
+            case 0x3d:
+                can_write = 0;
+                break;
+            default:
+                can_write = 1;
+                break;
+            }
+            break;
+        default:
+        case 0x01:
+            switch(addr) {
+            case 0x00:
+            case 0x01:
+            case 0x02:
+            case 0x03:
+            case 0x08:
+            case 0x09:
+            case 0x0a:
+            case 0x0b:
+            case 0x0e:
+            case 0x38 ... 0x3b: /* rom */
+            case 0x3d:
+                can_write = 0;
+                break;
+            default:
+                can_write = 1;
+                break;
+            }
+            break;
+        }
+        if (can_write) {
+            d->config[addr] = val;
+        }
+        if (++addr > 0xff)
+               break;
+        val >>= 8;
+    }
+
+    end = address + len;
+    if (end > PCI_COMMAND && address < (PCI_COMMAND + 2)) {
+      pci_info ();
+        /* if the command register is modified, we must modify the mappings */
+        pci_update_mappings(d);
+    }
+}
+
+void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
+{
+    PCIBus *s = opaque;
+    PCIDevice *pci_dev;
+    int config_addr, bus_num;
+
+#if defined(DEBUG_PCI) && 0
+    printf("pci_data_write: addr=%08x val=%08x len=%d\n",
+           addr, val, len);
+#endif
+    bus_num = (addr >> 16) & 0xff;
+    while (s && s->bus_num != bus_num)
+        s = s->next;
+    if (!s)
+        return;
+    pci_dev = s->devices[(addr >> 8) & 0xff];
+    if (!pci_dev)
+        return;
+    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);
+#endif
+    pci_dev->config_write(pci_dev, config_addr, val, 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;
+
+    bus_num = (addr >> 16) & 0xff;
+    while (s && s->bus_num != bus_num)
+        s= s->next;
+    if (!s)
+        goto fail;
+    pci_dev = s->devices[(addr >> 8) & 0xff];
+    if (!pci_dev) {
+    fail:
+        switch(len) {
+        case 1:
+            val = 0xff;
+            break;
+        case 2:
+            val = 0xffff;
+            break;
+        default:
+        case 4:
+            val = 0xffffffff;
+            break;
+        }
+        goto the_end;
+    }
+    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",
+           pci_dev->name, config_addr, val, len);
+#endif
+ the_end:
+#if defined(DEBUG_PCI) && 0
+    printf("pci_data_read: addr=%08x val=%08x len=%d\n",
+           addr, val, len);
+#endif
+    return val;
+}
+
+/***********************************************************/
+/* generic PCI irq support */
+
+/* 0 <= irq_num <= 3. level must be 0 or 1 */
+static void pci_set_irq(void *opaque, int irq_num, int level)
+{
+    PCIDevice *pci_dev = (PCIDevice *)opaque;
+    PCIBus *bus;
+    int change;
+
+    change = level - pci_dev->irq_state[irq_num];
+    if (!change)
+        return;
+
+    pci_dev->irq_state[irq_num] = level;
+    for (;;) {
+        bus = pci_dev->bus;
+        irq_num = bus->map_irq(pci_dev, irq_num);
+        if (bus->set_irq)
+            break;
+        pci_dev = bus->parent_dev;
+    }
+    bus->irq_count[irq_num] += change;
+    bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
+}
+
+/***********************************************************/
+/* monitor info on PCI */
+
+typedef struct {
+    uint16_t class;
+    const char *desc;
+} pci_class_desc;
+
+static pci_class_desc pci_class_descriptions[] =
+{
+    { 0x0100, "SCSI controller"},
+    { 0x0101, "IDE controller"},
+    { 0x0102, "Floppy controller"},
+    { 0x0103, "IPI controller"},
+    { 0x0104, "RAID controller"},
+    { 0x0106, "SATA controller"},
+    { 0x0107, "SAS controller"},
+    { 0x0180, "Storage controller"},
+    { 0x0200, "Ethernet controller"},
+    { 0x0201, "Token Ring controller"},
+    { 0x0202, "FDDI controller"},
+    { 0x0203, "ATM controller"},
+    { 0x0280, "Network controller"},
+    { 0x0300, "VGA controller"},
+    { 0x0301, "XGA controller"},
+    { 0x0302, "3D controller"},
+    { 0x0380, "Display controller"},
+    { 0x0400, "Video controller"},
+    { 0x0401, "Audio controller"},
+    { 0x0402, "Phone"},
+    { 0x0480, "Multimedia controller"},
+    { 0x0500, "RAM controller"},
+    { 0x0501, "Flash controller"},
+    { 0x0580, "Memory controller"},
+    { 0x0600, "Host bridge"},
+    { 0x0601, "ISA bridge"},
+    { 0x0602, "EISA bridge"},
+    { 0x0603, "MC bridge"},
+    { 0x0604, "PCI bridge"},
+    { 0x0605, "PCMCIA bridge"},
+    { 0x0606, "NUBUS bridge"},
+    { 0x0607, "CARDBUS bridge"},
+    { 0x0608, "RACEWAY bridge"},
+    { 0x0680, "Bridge"},
+    { 0x0c03, "USB controller"},
+    { 0, NULL}
+};
+
+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("    ");
+    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);
+    }
+    term_printf(": PCI device %04x:%04x\n",
+           le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))),
+           le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID))));
+
+    if (d->config[PCI_INTERRUPT_PIN] != 0) {
+        term_printf("      IRQ %d.\n", d->config[PCI_INTERRUPT_LINE]);
+    }
+    if (class == 0x0604) {
+        term_printf("      BUS %d.\n", d->config[0x19]);
+    }
+    for(i = 0;i < PCI_NUM_REGIONS; i++) {
+        r = &d->io_regions[i];
+        if (r->size != 0) {
+            term_printf("      BAR%d: ", i);
+            if (r->type & PCI_ADDRESS_SPACE_IO) {
+                term_printf("I/O at 0x%04x [0x%04x].\n",
+                       r->addr, r->addr + r->size - 1);
+            } else {
+                term_printf("32 bit memory at 0x%08x [0x%08x].\n",
+                       r->addr, r->addr + r->size - 1);
+            }
+        }
+    }
+    if (class == 0x0604 && d->config[0x19] != 0) {
+        pci_for_each_device(d->config[0x19], pci_info_device);
+    }
+}
+
+void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
+{
+    PCIBus *bus = first_bus;
+    PCIDevice *d;
+    int devfn;
+
+    while (bus && bus->bus_num != bus_num)
+        bus = bus->next;
+    if (bus) {
+        for(devfn = 0; devfn < 256; devfn++) {
+            d = bus->devices[devfn];
+            if (d)
+                fn(d);
+        }
+    }
+}
+
+void pci_info(void)
+{
+    pci_for_each_device(0, pci_info_device);
+}
+
+#ifndef IOEMU
+/* Initialize a PCI NIC.  */
+void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn)
+{
+    if (strcmp(nd->model, "ne2k_pci") == 0) {
+        pci_ne2000_init(bus, nd, devfn);
+    } else if (strcmp(nd->model, "i82551") == 0) {
+        pci_i82551_init(bus, nd, devfn);
+    } else if (strcmp(nd->model, "i82557b") == 0) {
+        pci_i82557b_init(bus, nd, devfn);
+    } else if (strcmp(nd->model, "i82559er") == 0) {
+        pci_i82559er_init(bus, nd, devfn);
+    } else if (strcmp(nd->model, "rtl8139") == 0) {
+        pci_rtl8139_init(bus, nd, devfn);
+    } else if (strcmp(nd->model, "pcnet") == 0) {
+        pci_pcnet_init(bus, nd, devfn);
+    } else if (strcmp(nd->model, "?") == 0) {
+        fprintf(stderr, "qemu: Supported PCI NICs: i82551 i82557b i82559er"
+                        " ne2k_pci pcnet rtl8139\n");
+        exit (1);
+    } else {
+        fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
+        exit (1);
+    }
+}
+
+typedef struct {
+    PCIDevice dev;
+    PCIBus *bus;
+} PCIBridge;
+
+void pci_bridge_write_config(PCIDevice *d,
+                             uint32_t address, uint32_t val, int len)
+{
+    PCIBridge *s = (PCIBridge *)d;
+
+    if (address == 0x19 || (address == 0x18 && len > 1)) {
+        if (address == 0x19)
+            s->bus->bus_num = val & 0xff;
+        else
+            s->bus->bus_num = (val >> 8) & 0xff;
+#if defined(DEBUG_PCI)
+        printf ("pci-bridge: %s: Assigned bus %d\n", d->name, s->bus->bus_num);
+#endif
+    }
+    pci_default_write_config(d, address, val, len);
+}
+
+PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
+                        pci_map_irq_fn map_irq, const char *name)
+{
+    PCIBridge *s;
+    s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge),
+                                         devfn, NULL, pci_bridge_write_config);
+    s->dev.config[0x00] = id >> 16;
+    s->dev.config[0x01] = id >> 24;
+    s->dev.config[0x02] = id; // device_id
+    s->dev.config[0x03] = id >> 8;
+    s->dev.config[0x04] = 0x06; // command = bus master, pci mem
+    s->dev.config[0x05] = 0x00;
+    s->dev.config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
+    s->dev.config[0x07] = 0x00; // status = fast devsel
+    s->dev.config[0x08] = 0x00; // revision
+    s->dev.config[0x09] = 0x00; // programming i/f
+    s->dev.config[0x0A] = 0x04; // class_sub = PCI to PCI bridge
+    s->dev.config[0x0B] = 0x06; // class_base = PCI_bridge
+    s->dev.config[0x0D] = 0x10; // latency_timer
+    s->dev.config[0x0E] = 0x81; // header_type
+    s->dev.config[0x1E] = 0xa0; // secondary status
+
+    s->bus = pci_register_secondary_bus(&s->dev, map_irq);
+    return s->bus;
+}
+#endif
diff -r 092232fa1fbd extras/stubfw/ioemu/pci_host.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/ioemu/pci_host.h    Mon Nov 12 02:26:13 2007 +0100
@@ -0,0 +1,93 @@
+/*
+ * QEMU Common PCI Host bridge configuration data space access routines.
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* Worker routines for a PCI host controller that uses an {address,data}
+   register pair to access PCI configuration space.  */
+
+typedef struct {
+    uint32_t config_reg;
+    PCIBus *bus;
+} PCIHostState;
+
+static void pci_host_data_writeb(void* opaque, pci_addr_t addr, uint32_t val)
+{
+    PCIHostState *s = opaque;
+    if (s->config_reg & (1u << 31))
+        pci_data_write(s->bus, s->config_reg | (addr & 3), val, 1);
+}
+
+static void pci_host_data_writew(void* opaque, pci_addr_t addr, uint32_t val)
+{
+    PCIHostState *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap16(val);
+#endif
+    if (s->config_reg & (1u << 31))
+        pci_data_write(s->bus, s->config_reg | (addr & 3), val, 2);
+}
+
+static void pci_host_data_writel(void* opaque, pci_addr_t addr, uint32_t val)
+{
+    PCIHostState *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    if (s->config_reg & (1u << 31))
+        pci_data_write(s->bus, s->config_reg, val, 4);
+}
+
+static uint32_t pci_host_data_readb(void* opaque, pci_addr_t addr)
+{
+    PCIHostState *s = opaque;
+    if (!(s->config_reg & (1 << 31)))
+        return 0xff;
+    return pci_data_read(s->bus, s->config_reg | (addr & 3), 1);
+}
+
+static uint32_t pci_host_data_readw(void* opaque, pci_addr_t addr)
+{
+    PCIHostState *s = opaque;
+    uint32_t val;
+    if (!(s->config_reg & (1 << 31)))
+        return 0xffff;
+    val = pci_data_read(s->bus, s->config_reg | (addr & 3), 2);
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap16(val);
+#endif
+    return val;
+}
+
+static uint32_t pci_host_data_readl(void* opaque, pci_addr_t addr)
+{
+    PCIHostState *s = opaque;
+    uint32_t val;
+    if (!(s->config_reg & (1 << 31)))
+        return 0xffffffff;
+    val = pci_data_read(s->bus, s->config_reg | (addr & 3), 4);
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    return val;
+}
+
diff -r 092232fa1fbd extras/stubfw/ioemu/piix_pci.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/ioemu/piix_pci.c    Mon Nov 12 04:00:41 2007 +0100
@@ -0,0 +1,396 @@
+/*
+ * QEMU i440FX/PIIX3 PCI Bridge Emulation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vl.h"
+typedef uint32_t pci_addr_t;
+#include "pci_host.h"
+
+typedef PCIHostState I440FXState;
+
+static void i440fx_addr_writel(void* opaque, uint32_t addr, uint32_t val)
+{
+    I440FXState *s = opaque;
+    s->config_reg = val;
+}
+
+static uint32_t i440fx_addr_readl(void* opaque, uint32_t addr)
+{
+    I440FXState *s = opaque;
+    return s->config_reg;
+}
+
+static void piix3_set_irq(qemu_irq *pic, int irq_num, int level);
+
+/* return the global irq number corresponding to a given device irq
+   pin. We could also use the bus number to have a more precise
+   mapping. */
+static 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;
+}
+
+#ifndef IOEMU
+
+static uint32_t isa_page_descs[384 / 4];
+static uint8_t smm_enabled;
+
+static void update_pam(PCIDevice *d, uint32_t start, uint32_t end, int r)
+{
+    uint32_t addr;
+
+    //    printf("ISA mapping %08x-0x%08x: %d\n", start, end, r);
+    switch(r) {
+    case 3:
+        /* RAM */
+        cpu_register_physical_memory(start, end - start,
+                                     start);
+        break;
+    case 1:
+        /* ROM (XXX: not quite correct) */
+        cpu_register_physical_memory(start, end - start,
+                                     start | IO_MEM_ROM);
+        break;
+    case 2:
+    case 0:
+        /* XXX: should distinguish read/write cases */
+        for(addr = start; addr < end; addr += 4096) {
+            cpu_register_physical_memory(addr, 4096,
+                                         isa_page_descs[(addr - 0xa0000) >> 
12]);
+        }
+        break;
+    }
+}
+
+static void i440fx_update_memory_mappings(PCIDevice *d)
+{
+    int i, r;
+    uint32_t smram, addr;
+
+    update_pam(d, 0xf0000, 0x100000, (d->config[0x59] >> 4) & 3);
+    for(i = 0; i < 12; i++) {
+        r = (d->config[(i >> 1) + 0x5a] >> ((i & 1) * 4)) & 3;
+        update_pam(d, 0xc0000 + 0x4000 * i, 0xc0000 + 0x4000 * (i + 1), r);
+    }
+    smram = d->config[0x72];
+    if ((smm_enabled && (smram & 0x08)) || (smram & 0x40)) {
+        cpu_register_physical_memory(0xa0000, 0x20000, 0xa0000);
+    } else {
+        for(addr = 0xa0000; addr < 0xc0000; addr += 4096) {
+            cpu_register_physical_memory(addr, 4096,
+                                         isa_page_descs[(addr - 0xa0000) >> 
12]);
+        }
+    }
+}
+
+void i440fx_set_smm(PCIDevice *d, int val)
+{
+    val = (val != 0);
+    if (smm_enabled != val) {
+        smm_enabled = val;
+        i440fx_update_memory_mappings(d);
+    }
+}
+
+
+/* XXX: suppress when better memory API. We make the assumption that
+   no device (in particular the VGA) changes the memory mappings in
+   the 0xa0000-0x100000 range */
+void i440fx_init_memory_mappings(PCIDevice *d)
+{
+    int i;
+    for(i = 0; i < 96; i++) {
+        isa_page_descs[i] = cpu_get_physical_page_desc(0xa0000 + i * 0x1000);
+    }
+}
+#endif
+
+static void i440fx_write_config(PCIDevice *d,
+                                uint32_t address, uint32_t val, int len)
+{
+    /* XXX: implement SMRAM.D_LOCK */
+    pci_default_write_config(d, address, val, len);
+#ifndef IOEMU
+    if ((address >= 0x59 && address <= 0x5f) || address == 0x72)
+        i440fx_update_memory_mappings(d);
+#endif
+}
+
+#ifndef IOEMU
+static void i440fx_save(QEMUFile* f, void *opaque)
+{
+    PCIDevice *d = opaque;
+    pci_device_save(d, f);
+    qemu_put_8s(f, &smm_enabled);
+}
+
+static int i440fx_load(QEMUFile* f, void *opaque, int version_id)
+{
+    PCIDevice *d = opaque;
+    int ret;
+
+    if (version_id != 1)
+        return -EINVAL;
+    ret = pci_device_load(d, f);
+    if (ret < 0)
+        return ret;
+    i440fx_update_memory_mappings(d);
+    qemu_get_8s(f, &smm_enabled);
+    return 0;
+}
+#endif
+
+PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic)
+{
+    PCIBus *b;
+    PCIDevice *d;
+    I440FXState *s;
+
+    s = qemu_mallocz(sizeof(I440FXState));
+    b = pci_register_bus(piix3_set_irq, pci_slot_get_pirq, pic, 0, 4);
+    s->bus = b;
+
+    register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
+    register_ioport_read(0xcf8, 4, 4, i440fx_addr_readl, s);
+
+    register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb, s);
+    register_ioport_write(0xcfc, 4, 2, pci_host_data_writew, s);
+    register_ioport_write(0xcfc, 4, 4, pci_host_data_writel, s);
+    register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s);
+    register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
+    register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
+
+    pci_info ();
+    printf ("Register i440FX\n");
+    d = pci_register_device(b, "i440FX", sizeof(PCIDevice), 0,
+                            NULL, i440fx_write_config);
+
+    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
+
+    d->config[0x72] = 0x02; /* SMRAM */
+
+    register_savevm("I440FX", 0, 1, i440fx_save, i440fx_load, d);
+    *pi440fx_state = d;
+    return b;
+}
+
+/* PIIX3 PCI to ISA bridge */
+
+PCIDevice *piix3_dev;
+PCIDevice *piix4_dev;
+
+/* just used for simpler irq handling. */
+#define PCI_IRQ_WORDS   ((PCI_DEVICES_MAX + 31) / 32)
+
+static int pci_irq_levels[4];
+
+static void piix3_set_irq(qemu_irq *pic, int irq_num, int level)
+{
+    int i, pic_irq, pic_level;
+
+    piix3_dev->config[0x60 + irq_num] &= ~0x80;   // enable bit
+    pci_irq_levels[irq_num] = level;
+
+    /* now we change the pic irq level according to the piix irq mappings */
+    /* XXX: optimize */
+    pic_irq = piix3_dev->config[0x60 + irq_num];
+    if (pic_irq < 16) {
+        /* The pic level is the logical OR of all the PCI irqs mapped
+           to it */
+        pic_level = 0;
+        for (i = 0; i < 4; i++) {
+            if (pic_irq == piix3_dev->config[0x60 + i])
+                pic_level |= pci_irq_levels[i];
+        }
+        qemu_set_irq(pic[pic_irq], pic_level);
+    }
+}
+
+static void piix3_reset(PCIDevice *d)
+{
+    uint8_t *pci_conf = d->config;
+
+    pci_conf[0x04] = 0x07; // master, memory and I/O
+    pci_conf[0x05] = 0x00;
+    pci_conf[0x06] = 0x00;
+    pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
+    pci_conf[0x4c] = 0x4d;
+    pci_conf[0x4e] = 0x03;
+    pci_conf[0x4f] = 0x00;
+    pci_conf[0x60] = 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[0xa2] = 0x00;
+    pci_conf[0xa3] = 0x00;
+    pci_conf[0xa4] = 0x00;
+    pci_conf[0xa5] = 0x00;
+    pci_conf[0xa6] = 0x00;
+    pci_conf[0xa7] = 0x00;
+    pci_conf[0xa8] = 0x0f;
+    pci_conf[0xaa] = 0x00;
+    pci_conf[0xab] = 0x00;
+    pci_conf[0xac] = 0x00;
+    pci_conf[0xae] = 0x00;
+}
+
+static void piix4_reset(PCIDevice *d)
+{
+    uint8_t *pci_conf = d->config;
+
+    pci_conf[0x04] = 0x07; // master, memory and I/O
+    pci_conf[0x05] = 0x00;
+    pci_conf[0x06] = 0x00;
+    pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
+    pci_conf[0x4c] = 0x4d;
+    pci_conf[0x4e] = 0x03;
+    pci_conf[0x4f] = 0x00;
+    pci_conf[0x60] = 0x0a; // PCI A -> IRQ 10
+    pci_conf[0x61] = 0x0a; // PCI B -> IRQ 10
+    pci_conf[0x62] = 0x0b; // PCI C -> IRQ 11
+    pci_conf[0x63] = 0x0b; // PCI D -> IRQ 11
+    pci_conf[0x69] = 0x02;
+    pci_conf[0x70] = 0x80;
+    pci_conf[0x76] = 0x0c;
+    pci_conf[0x77] = 0x0c;
+    pci_conf[0x78] = 0x02;
+    pci_conf[0x79] = 0x00;
+    pci_conf[0x80] = 0x00;
+    pci_conf[0x82] = 0x00;
+    pci_conf[0xa0] = 0x08;
+    pci_conf[0xa2] = 0x00;
+    pci_conf[0xa3] = 0x00;
+    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;
+}
+
+#ifndef IOEMU
+static void piix_save(QEMUFile* f, void *opaque)
+{
+    PCIDevice *d = opaque;
+    pci_device_save(d, f);
+}
+
+static int piix_load(QEMUFile* f, void *opaque, int version_id)
+{
+    PCIDevice *d = opaque;
+    if (version_id != 2)
+        return -EINVAL;
+    return pci_device_load(d, f);
+}
+#endif
+
+int piix_init(PCIBus *bus, int devfn)
+{
+    PCIDevice *d;
+    uint8_t *pci_conf;
+
+    d = pci_register_device(bus, "PIIX", sizeof(PCIDevice),
+                                    devfn, NULL, NULL);
+    register_savevm("PIIX", 0, 2, piix_save, piix_load, d);
+
+    piix3_dev = d;
+    pci_conf = d->config;
+
+    pci_conf[0x00] = 0x86; // Intel
+    pci_conf[0x01] = 0x80;
+    pci_conf[0x02] = 0x2E; // 82371FB PIIX PCI-to-ISA bridge
+    pci_conf[0x03] = 0x12;
+    pci_conf[0x08] = 0x02; // Step A1
+    pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
+    pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
+    pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
+
+    piix3_reset(d);
+    return d->devfn;
+}
+
+int piix3_init(PCIBus *bus, int devfn)
+{
+    PCIDevice *d;
+    uint8_t *pci_conf;
+
+    d = pci_register_device(bus, "PIIX3", sizeof(PCIDevice),
+                                    devfn, NULL, NULL);
+    register_savevm("PIIX3", 0, 2, piix_save, piix_load, d);
+
+    piix3_dev = d;
+    pci_conf = d->config;
+
+    pci_conf[0x00] = 0x86; // Intel
+    pci_conf[0x01] = 0x80;
+    pci_conf[0x02] = 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);
+    return d->devfn;
+}
+
+int piix4_init(PCIBus *bus, int devfn)
+{
+    PCIDevice *d;
+    uint8_t *pci_conf;
+
+    d = pci_register_device(bus, "PIIX4", sizeof(PCIDevice),
+                                    devfn, NULL, NULL);
+    register_savevm("PIIX4", 0, 2, piix_save, piix_load, d);
+
+    piix4_dev = d;
+    pci_conf = d->config;
+
+    pci_conf[0x00] = 0x86; // Intel
+    pci_conf[0x01] = 0x80;
+    pci_conf[0x02] = 0x10; // 82371AB/EB/MB PIIX4 PCI-to-ISA bridge
+    pci_conf[0x03] = 0x71;
+    pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
+    pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
+    pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
+
+    piix4_reset(d);
+    return d->devfn;
+}
diff -r 092232fa1fbd extras/stubfw/ioemu/readline.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/ioemu/readline.c    Sun Nov 18 07:50:13 2007 +0100
@@ -0,0 +1,487 @@
+/*
+ * QEMU readline utility
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+#define TERM_CMD_BUF_SIZE 4095
+#define TERM_MAX_CMDS 64
+#define NB_COMPLETIONS_MAX 256
+
+#define IS_NORM 0
+#define IS_ESC  1
+#define IS_CSI  2
+
+#define printf do_not_use_printf
+
+static char term_cmd_buf[TERM_CMD_BUF_SIZE + 1];
+static int term_cmd_buf_index;
+static int term_cmd_buf_size;
+
+static char term_last_cmd_buf[TERM_CMD_BUF_SIZE + 1];
+static int term_last_cmd_buf_index;
+static int term_last_cmd_buf_size;
+
+static int term_esc_state;
+static int term_esc_param;
+
+static char *term_history[TERM_MAX_CMDS];
+static int term_hist_entry = -1;
+
+static int nb_completions;
+int completion_index;
+static char *completions[NB_COMPLETIONS_MAX];
+
+static ReadLineFunc *term_readline_func;
+static int term_is_password;
+static char term_prompt[256];
+static void *term_readline_opaque;
+
+static void term_show_prompt2(void)
+{
+    term_printf("%s", term_prompt);
+    term_flush();
+    term_last_cmd_buf_index = 0;
+    term_last_cmd_buf_size = 0;
+    term_esc_state = IS_NORM;
+}
+
+static void term_show_prompt(void)
+{
+    term_show_prompt2();
+    term_cmd_buf_index = 0;
+    term_cmd_buf_size = 0;
+}
+
+/* update the displayed command line */
+static void term_update(void)
+{
+    int i, delta, len;
+
+    if (term_cmd_buf_size != term_last_cmd_buf_size ||
+        memcmp(term_cmd_buf, term_last_cmd_buf, term_cmd_buf_size) != 0) {
+        for(i = 0; i < term_last_cmd_buf_index; i++) {
+            term_printf("\033[D");
+        }
+        term_cmd_buf[term_cmd_buf_size] = '\0';
+        if (term_is_password) {
+            len = strlen(term_cmd_buf);
+            for(i = 0; i < len; i++)
+                term_printf("*");
+        } else {
+            term_printf("%s", term_cmd_buf);
+        }
+        term_printf("\033[K");
+        memcpy(term_last_cmd_buf, term_cmd_buf, term_cmd_buf_size);
+        term_last_cmd_buf_size = term_cmd_buf_size;
+        term_last_cmd_buf_index = term_cmd_buf_size;
+    }
+    if (term_cmd_buf_index != term_last_cmd_buf_index) {
+        delta = term_cmd_buf_index - term_last_cmd_buf_index;
+        if (delta > 0) {
+            for(i = 0;i < delta; i++) {
+                term_printf("\033[C");
+            }
+        } else {
+            delta = -delta;
+            for(i = 0;i < delta; i++) {
+                term_printf("\033[D");
+            }
+        }
+        term_last_cmd_buf_index = term_cmd_buf_index;
+    }
+    term_flush();
+}
+
+static void term_insert_char(int ch)
+{
+    if (term_cmd_buf_index < TERM_CMD_BUF_SIZE) {
+        memmove(term_cmd_buf + term_cmd_buf_index + 1,
+                term_cmd_buf + term_cmd_buf_index,
+                term_cmd_buf_size - term_cmd_buf_index);
+        term_cmd_buf[term_cmd_buf_index] = ch;
+        term_cmd_buf_size++;
+        term_cmd_buf_index++;
+    }
+}
+
+static void term_backward_char(void)
+{
+    if (term_cmd_buf_index > 0) {
+        term_cmd_buf_index--;
+    }
+}
+
+static void term_forward_char(void)
+{
+    if (term_cmd_buf_index < term_cmd_buf_size) {
+        term_cmd_buf_index++;
+    }
+}
+
+static void term_delete_char(void)
+{
+    if (term_cmd_buf_index < term_cmd_buf_size) {
+        memmove(term_cmd_buf + term_cmd_buf_index,
+                term_cmd_buf + term_cmd_buf_index + 1,
+                term_cmd_buf_size - term_cmd_buf_index - 1);
+        term_cmd_buf_size--;
+    }
+}
+
+static void term_backspace(void)
+{
+    if (term_cmd_buf_index > 0) {
+        term_backward_char();
+        term_delete_char();
+    }
+}
+
+static void term_backword(void)
+{
+    int start;
+
+    if (term_cmd_buf_index == 0 || term_cmd_buf_index > term_cmd_buf_size) {
+        return;
+    }
+
+    start = term_cmd_buf_index - 1;
+
+    /* find first word (backwards) */
+    while (start > 0) {
+        if (!isspace(term_cmd_buf[start])) {
+            break;
+        }
+
+        --start;
+    }
+
+    /* find first space (backwards) */
+    while (start > 0) {
+        if (isspace(term_cmd_buf[start])) {
+            ++start;
+            break;
+        }
+
+        --start;
+    }
+
+    /* remove word */
+    if (start < term_cmd_buf_index) {
+        memmove(term_cmd_buf + start,
+                term_cmd_buf + term_cmd_buf_index,
+                term_cmd_buf_size - term_cmd_buf_index);
+        term_cmd_buf_size -= term_cmd_buf_index - start;
+        term_cmd_buf_index = start;
+    }
+}
+
+static void term_bol(void)
+{
+    term_cmd_buf_index = 0;
+}
+
+static void term_eol(void)
+{
+    term_cmd_buf_index = term_cmd_buf_size;
+}
+
+static void term_up_char(void)
+{
+    int idx;
+
+    if (term_hist_entry == 0)
+       return;
+    if (term_hist_entry == -1) {
+       /* Find latest entry */
+       for (idx = 0; idx < TERM_MAX_CMDS; idx++) {
+           if (term_history[idx] == NULL)
+               break;
+       }
+       term_hist_entry = idx;
+    }
+    term_hist_entry--;
+    if (term_hist_entry >= 0) {
+       pstrcpy(term_cmd_buf, sizeof(term_cmd_buf),
+                term_history[term_hist_entry]);
+       term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf);
+    }
+}
+
+static void term_down_char(void)
+{
+    if (term_hist_entry == TERM_MAX_CMDS - 1 || term_hist_entry == -1)
+       return;
+    if (term_history[++term_hist_entry] != NULL) {
+       pstrcpy(term_cmd_buf, sizeof(term_cmd_buf),
+                term_history[term_hist_entry]);
+    } else {
+       term_hist_entry = -1;
+    }
+    term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf);
+}
+
+static void term_hist_add(const char *cmdline)
+{
+    char *hist_entry, *new_entry;
+    int idx;
+
+    if (cmdline[0] == '\0')
+       return;
+    new_entry = NULL;
+    if (term_hist_entry != -1) {
+       /* We were editing an existing history entry: replace it */
+       hist_entry = term_history[term_hist_entry];
+       idx = term_hist_entry;
+       if (strcmp(hist_entry, cmdline) == 0) {
+           goto same_entry;
+       }
+    }
+    /* Search cmdline in history buffers */
+    for (idx = 0; idx < TERM_MAX_CMDS; idx++) {
+       hist_entry = term_history[idx];
+       if (hist_entry == NULL)
+           break;
+       if (strcmp(hist_entry, cmdline) == 0) {
+       same_entry:
+           new_entry = hist_entry;
+           /* Put this entry at the end of history */
+           memmove(&term_history[idx], &term_history[idx + 1],
+                   &term_history[TERM_MAX_CMDS] - &term_history[idx + 1]);
+           term_history[TERM_MAX_CMDS - 1] = NULL;
+           for (; idx < TERM_MAX_CMDS; idx++) {
+               if (term_history[idx] == NULL)
+                   break;
+           }
+           break;
+       }
+    }
+    if (idx == TERM_MAX_CMDS) {
+       /* Need to get one free slot */
+       free(term_history[0]);
+       memcpy(term_history, &term_history[1],
+              &term_history[TERM_MAX_CMDS] - &term_history[1]);
+       term_history[TERM_MAX_CMDS - 1] = NULL;
+       idx = TERM_MAX_CMDS - 1;
+    }
+    if (new_entry == NULL)
+       new_entry = strdup(cmdline);
+    term_history[idx] = new_entry;
+    term_hist_entry = -1;
+}
+
+/* completion support */
+
+void add_completion(const char *str)
+{
+    if (nb_completions < NB_COMPLETIONS_MAX) {
+        completions[nb_completions++] = qemu_strdup(str);
+    }
+}
+
+static void term_completion(void)
+{
+    int len, i, j, max_width, nb_cols, max_prefix;
+    char *cmdline;
+
+    nb_completions = 0;
+
+    cmdline = qemu_malloc(term_cmd_buf_index + 1);
+    if (!cmdline)
+        return;
+    memcpy(cmdline, term_cmd_buf, term_cmd_buf_index);
+    cmdline[term_cmd_buf_index] = '\0';
+    readline_find_completion(cmdline);
+    qemu_free(cmdline);
+
+    /* no completion found */
+    if (nb_completions <= 0)
+        return;
+    if (nb_completions == 1) {
+        len = strlen(completions[0]);
+        for(i = completion_index; i < len; i++) {
+            term_insert_char(completions[0][i]);
+        }
+        /* extra space for next argument. XXX: make it more generic */
+        if (len > 0 && completions[0][len - 1] != '/')
+            term_insert_char(' ');
+    } else {
+        term_printf("\n");
+        max_width = 0;
+        max_prefix = 0;        
+        for(i = 0; i < nb_completions; i++) {
+            len = strlen(completions[i]);
+            if (i==0) {
+                max_prefix = len;
+            } else {
+                if (len < max_prefix)
+                    max_prefix = len;
+                for(j=0; j<max_prefix; j++) {
+                    if (completions[i][j] != completions[0][j])
+                        max_prefix = j;
+                }
+            }
+            if (len > max_width)
+                max_width = len;
+        }
+        if (max_prefix > 0) 
+            for(i = completion_index; i < max_prefix; i++) {
+                term_insert_char(completions[0][i]);
+            }
+        max_width += 2;
+        if (max_width < 10)
+            max_width = 10;
+        else if (max_width > 80)
+            max_width = 80;
+        nb_cols = 80 / max_width;
+        j = 0;
+        for(i = 0; i < nb_completions; i++) {
+            term_printf("%-*s", max_width, completions[i]);
+            if (++j == nb_cols || i == (nb_completions - 1)) {
+                term_printf("\n");
+                j = 0;
+            }
+        }
+        term_show_prompt2();
+    }
+}
+
+/* return true if command handled */
+void readline_handle_byte(int ch)
+{
+    switch(term_esc_state) {
+    case IS_NORM:
+        switch(ch) {
+        case 1:
+            term_bol();
+            break;
+        case 4:
+            term_delete_char();
+            break;
+        case 5:
+            term_eol();
+            break;
+        case 9:
+            term_completion();
+            break;
+        case 10:
+        case 13:
+            term_cmd_buf[term_cmd_buf_size] = '\0';
+            if (!term_is_password)
+                term_hist_add(term_cmd_buf);
+            term_printf("\n");
+            term_cmd_buf_index = 0;
+            term_cmd_buf_size = 0;
+            term_last_cmd_buf_index = 0;
+            term_last_cmd_buf_size = 0;
+            /* NOTE: readline_start can be called here */
+            term_readline_func(term_readline_opaque, term_cmd_buf);
+            break;
+        case 23:
+            /* ^W */
+            term_backword();
+            break;
+        case 27:
+            term_esc_state = IS_ESC;
+            break;
+        case 127:
+        case 8:
+            term_backspace();
+            break;
+       case 155:
+            term_esc_state = IS_CSI;
+           break;
+        default:
+            if (ch >= 32) {
+                term_insert_char(ch);
+            }
+            break;
+        }
+        break;
+    case IS_ESC:
+        if (ch == '[') {
+            term_esc_state = IS_CSI;
+            term_esc_param = 0;
+        } else {
+            term_esc_state = IS_NORM;
+        }
+        break;
+    case IS_CSI:
+        switch(ch) {
+       case 'A':
+       case 'F':
+           term_up_char();
+           break;
+       case 'B':
+       case 'E':
+           term_down_char();
+           break;
+        case 'D':
+            term_backward_char();
+            break;
+        case 'C':
+            term_forward_char();
+            break;
+        case '0' ... '9':
+            term_esc_param = term_esc_param * 10 + (ch - '0');
+            goto the_end;
+        case '~':
+            switch(term_esc_param) {
+            case 1:
+                term_bol();
+                break;
+            case 3:
+                term_delete_char();
+                break;
+            case 4:
+                term_eol();
+                break;
+            }
+            break;
+        default:
+            break;
+        }
+        term_esc_state = IS_NORM;
+    the_end:
+        break;
+    }
+    term_update();
+}
+
+void readline_start(const char *prompt, int is_password,
+                    ReadLineFunc *readline_func, void *opaque)
+{
+    pstrcpy(term_prompt, sizeof(term_prompt), prompt);
+    term_readline_func = readline_func;
+    term_readline_opaque = opaque;
+    term_is_password = is_password;
+    term_show_prompt();
+}
+
+const char *readline_get_history(unsigned int index)
+{
+    if (index >= TERM_MAX_CMDS)
+        return NULL;
+    return term_history[index];
+}
+
+
diff -r 092232fa1fbd extras/stubfw/ioemu/serial.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/ioemu/serial.c      Sun Nov 18 06:42:11 2007 +0100
@@ -0,0 +1,478 @@
+/*
+ * QEMU 16450 UART emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+//#define DEBUG_SERIAL
+
+#define UART_LCR_DLAB  0x80    /* Divisor latch access bit */
+
+#define UART_IER_MSI   0x08    /* Enable Modem status interrupt */
+#define UART_IER_RLSI  0x04    /* Enable receiver line status interrupt */
+#define UART_IER_THRI  0x02    /* Enable Transmitter holding register int. */
+#define UART_IER_RDI   0x01    /* Enable receiver data interrupt */
+
+#define UART_IIR_NO_INT        0x01    /* No interrupts pending */
+#define UART_IIR_ID    0x06    /* Mask for the interrupt ID */
+
+#define UART_IIR_MSI   0x00    /* Modem status interrupt */
+#define UART_IIR_THRI  0x02    /* Transmitter holding register empty */
+#define UART_IIR_RDI   0x04    /* Receiver data interrupt */
+#define UART_IIR_RLSI  0x06    /* Receiver line status interrupt */
+
+/*
+ * These are the definitions for the Modem Control Register
+ */
+#define UART_MCR_LOOP  0x10    /* Enable loopback test mode */
+#define UART_MCR_OUT2  0x08    /* Out2 complement */
+#define UART_MCR_OUT1  0x04    /* Out1 complement */
+#define UART_MCR_RTS   0x02    /* RTS complement */
+#define UART_MCR_DTR   0x01    /* DTR complement */
+
+/*
+ * These are the definitions for the Modem Status Register
+ */
+#define UART_MSR_DCD   0x80    /* Data Carrier Detect */
+#define UART_MSR_RI    0x40    /* Ring Indicator */
+#define UART_MSR_DSR   0x20    /* Data Set Ready */
+#define UART_MSR_CTS   0x10    /* Clear to Send */
+#define UART_MSR_DDCD  0x08    /* Delta DCD */
+#define UART_MSR_TERI  0x04    /* Trailing edge ring indicator */
+#define UART_MSR_DDSR  0x02    /* Delta DSR */
+#define UART_MSR_DCTS  0x01    /* Delta CTS */
+#define UART_MSR_ANY_DELTA 0x0F        /* Any of the delta bits! */
+
+#define UART_LSR_TEMT  0x40    /* Transmitter empty */
+#define UART_LSR_THRE  0x20    /* Transmit-hold-register empty */
+#define UART_LSR_BI    0x10    /* Break interrupt indicator */
+#define UART_LSR_FE    0x08    /* Frame error indicator */
+#define UART_LSR_PE    0x04    /* Parity error indicator */
+#define UART_LSR_OE    0x02    /* Overrun error indicator */
+#define UART_LSR_DR    0x01    /* Receiver data ready */
+
+struct SerialState {
+    uint16_t divider;
+    uint8_t rbr; /* receive register */
+    uint8_t ier;
+    uint8_t iir; /* read only */
+    uint8_t lcr;
+    uint8_t mcr;
+    uint8_t lsr; /* read only */
+    uint8_t msr; /* read only */
+    uint8_t scr;
+    /* NOTE: this hidden state is necessary for tx irq generation as
+       it can be reset while reading iir */
+    int thr_ipending;
+    qemu_irq irq;
+    CharDriverState *chr;
+    int last_break_enable;
+    target_phys_addr_t base;
+    int it_shift;
+};
+
+static void serial_update_irq(SerialState *s)
+{
+    if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI)) {
+        s->iir = UART_IIR_RDI;
+    } else if (s->thr_ipending && (s->ier & UART_IER_THRI)) {
+        s->iir = UART_IIR_THRI;
+    } else {
+        s->iir = UART_IIR_NO_INT;
+    }
+    if (s->iir != UART_IIR_NO_INT) {
+        qemu_irq_raise(s->irq);
+    } else {
+        qemu_irq_lower(s->irq);
+    }
+}
+
+static void serial_update_parameters(SerialState *s)
+{
+#ifndef IOEMU
+    int speed, parity, data_bits, stop_bits;
+    QEMUSerialSetParams ssp;
+
+    if (s->lcr & 0x08) {
+        if (s->lcr & 0x10)
+            parity = 'E';
+        else
+            parity = 'O';
+    } else {
+            parity = 'N';
+    }
+    if (s->lcr & 0x04)
+        stop_bits = 2;
+    else
+        stop_bits = 1;
+    data_bits = (s->lcr & 0x03) + 5;
+    if (s->divider == 0)
+        return;
+    speed = 115200 / s->divider;
+    ssp.speed = speed;
+    ssp.parity = parity;
+    ssp.data_bits = data_bits;
+    ssp.stop_bits = stop_bits;
+    qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
+#if 0
+    printf("speed=%d parity=%c data=%d stop=%d\n",
+           speed, parity, data_bits, stop_bits);
+#endif
+#endif
+}
+
+
+static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    SerialState *s = opaque;
+    unsigned char ch;
+
+    addr &= 7;
+#ifdef DEBUG_SERIAL
+    printf("serial: write addr=0x%02x val=0x%02x\n", addr, val);
+#endif
+    switch(addr) {
+    default:
+    case 0:
+        if (s->lcr & UART_LCR_DLAB) {
+            s->divider = (s->divider & 0xff00) | val;
+            serial_update_parameters(s);
+        } else {
+            s->thr_ipending = 0;
+            s->lsr &= ~UART_LSR_THRE;
+            serial_update_irq(s);
+            ch = val;
+            qemu_chr_write(s->chr, &ch, 1);
+            s->thr_ipending = 1;
+            s->lsr |= UART_LSR_THRE;
+            s->lsr |= UART_LSR_TEMT;
+            serial_update_irq(s);
+        }
+        break;
+    case 1:
+        if (s->lcr & UART_LCR_DLAB) {
+            s->divider = (s->divider & 0x00ff) | (val << 8);
+            serial_update_parameters(s);
+        } else {
+            s->ier = val & 0x0f;
+            if (s->lsr & UART_LSR_THRE) {
+                s->thr_ipending = 1;
+            }
+            serial_update_irq(s);
+        }
+        break;
+    case 2:
+        break;
+    case 3:
+        {
+            int break_enable;
+            s->lcr = val;
+            serial_update_parameters(s);
+            break_enable = (val >> 6) & 1;
+            if (break_enable != s->last_break_enable) {
+                s->last_break_enable = break_enable;
+                qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
+                               &break_enable);
+            }
+        }
+        break;
+    case 4:
+        s->mcr = val & 0x1f;
+        break;
+    case 5:
+        break;
+    case 6:
+        break;
+    case 7:
+        s->scr = val;
+        break;
+    }
+}
+
+static uint32_t serial_ioport_read(void *opaque, uint32_t addr)
+{
+    SerialState *s = opaque;
+    uint32_t ret;
+
+    addr &= 7;
+    switch(addr) {
+    default:
+    case 0:
+        if (s->lcr & UART_LCR_DLAB) {
+            ret = s->divider & 0xff;
+        } else {
+            ret = s->rbr;
+            s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
+            serial_update_irq(s);
+        }
+        break;
+    case 1:
+        if (s->lcr & UART_LCR_DLAB) {
+            ret = (s->divider >> 8) & 0xff;
+        } else {
+            ret = s->ier;
+        }
+        break;
+    case 2:
+        ret = s->iir;
+        /* reset THR pending bit */
+        if ((ret & 0x7) == UART_IIR_THRI)
+            s->thr_ipending = 0;
+        serial_update_irq(s);
+        break;
+    case 3:
+        ret = s->lcr;
+        break;
+    case 4:
+        ret = s->mcr;
+        break;
+    case 5:
+        ret = s->lsr;
+        break;
+    case 6:
+        if (s->mcr & UART_MCR_LOOP) {
+            /* in loopback, the modem output pins are connected to the
+               inputs */
+            ret = (s->mcr & 0x0c) << 4;
+            ret |= (s->mcr & 0x02) << 3;
+            ret |= (s->mcr & 0x01) << 5;
+        } else {
+            ret = s->msr;
+        }
+        break;
+    case 7:
+        ret = s->scr;
+        break;
+    }
+#ifdef DEBUG_SERIAL
+    printf("serial: read addr=0x%02x val=0x%02x\n", addr, ret);
+#endif
+    return ret;
+}
+
+int serial_can_receive(SerialState *s)
+{
+    return !(s->lsr & UART_LSR_DR);
+}
+
+void serial_receive_byte(SerialState *s, int ch)
+{
+    s->rbr = ch;
+    s->lsr |= UART_LSR_DR;
+    serial_update_irq(s);
+}
+
+static void serial_receive_break(SerialState *s)
+{
+    s->rbr = 0;
+    s->lsr |= UART_LSR_BI | UART_LSR_DR;
+    serial_update_irq(s);
+}
+
+int serial_can_receive1(void *opaque)
+{
+    SerialState *s = opaque;
+    return serial_can_receive(s);
+}
+
+void serial_receive1(void *opaque, const uint8_t *buf, int size)
+{
+    SerialState *s = opaque;
+    serial_receive_byte(s, buf[0]);
+}
+
+void serial_event(void *opaque, int event)
+{
+    SerialState *s = opaque;
+    if (event == CHR_EVENT_BREAK)
+        serial_receive_break(s);
+}
+
+#if 0
+static void serial_save(QEMUFile *f, void *opaque)
+{
+    SerialState *s = opaque;
+
+    qemu_put_be16s(f,&s->divider);
+    qemu_put_8s(f,&s->rbr);
+    qemu_put_8s(f,&s->ier);
+    qemu_put_8s(f,&s->iir);
+    qemu_put_8s(f,&s->lcr);
+    qemu_put_8s(f,&s->mcr);
+    qemu_put_8s(f,&s->lsr);
+    qemu_put_8s(f,&s->msr);
+    qemu_put_8s(f,&s->scr);
+}
+
+static int serial_load(QEMUFile *f, void *opaque, int version_id)
+{
+    SerialState *s = opaque;
+
+    if(version_id > 2)
+        return -EINVAL;
+
+    if (version_id >= 2)
+        qemu_get_be16s(f, &s->divider);
+    else
+        s->divider = qemu_get_byte(f);
+    qemu_get_8s(f,&s->rbr);
+    qemu_get_8s(f,&s->ier);
+    qemu_get_8s(f,&s->iir);
+    qemu_get_8s(f,&s->lcr);
+    qemu_get_8s(f,&s->mcr);
+    qemu_get_8s(f,&s->lsr);
+    qemu_get_8s(f,&s->msr);
+    qemu_get_8s(f,&s->scr);
+
+    return 0;
+}
+#endif
+
+/* If fd is zero, it means that the serial device uses the console */
+SerialState *serial_init(int base, qemu_irq irq, CharDriverState *chr)
+{
+    SerialState *s;
+
+    s = qemu_mallocz(sizeof(SerialState));
+    if (!s)
+        return NULL;
+    s->irq = irq;
+    s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
+    s->iir = UART_IIR_NO_INT;
+    s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
+
+    s->chr = chr;
+
+    register_savevm("serial", base, 2, serial_save, serial_load, s);
+
+    register_ioport_write(base, 8, 1, serial_ioport_write, s);
+    register_ioport_read(base, 8, 1, serial_ioport_read, s);
+
+    qemu_chr_add_handlers(chr, serial_can_receive1, serial_receive1,
+                          serial_event, s);
+
+    return s;
+}
+
+#if 0
+/* Memory mapped interface */
+uint32_t serial_mm_readb (void *opaque, target_phys_addr_t addr)
+{
+    SerialState *s = opaque;
+
+    return serial_ioport_read(s, (addr - s->base) >> s->it_shift) & 0xFF;
+}
+
+void serial_mm_writeb (void *opaque,
+                       target_phys_addr_t addr, uint32_t value)
+{
+    SerialState *s = opaque;
+
+    serial_ioport_write(s, (addr - s->base) >> s->it_shift, value & 0xFF);
+}
+
+uint32_t serial_mm_readw (void *opaque, target_phys_addr_t addr)
+{
+    SerialState *s = opaque;
+    uint32_t val;
+
+    val = serial_ioport_read(s, (addr - s->base) >> s->it_shift) & 0xFFFF;
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap16(val);
+#endif
+    return val;
+}
+
+void serial_mm_writew (void *opaque,
+                       target_phys_addr_t addr, uint32_t value)
+{
+    SerialState *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+    value = bswap16(value);
+#endif
+    serial_ioport_write(s, (addr - s->base) >> s->it_shift, value & 0xFFFF);
+}
+
+uint32_t serial_mm_readl (void *opaque, target_phys_addr_t addr)
+{
+    SerialState *s = opaque;
+    uint32_t val;
+
+    val = serial_ioport_read(s, (addr - s->base) >> s->it_shift);
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    return val;
+}
+
+void serial_mm_writel (void *opaque,
+                       target_phys_addr_t addr, uint32_t value)
+{
+    SerialState *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+    value = bswap32(value);
+#endif
+    serial_ioport_write(s, (addr - s->base) >> s->it_shift, value);
+}
+
+static CPUReadMemoryFunc *serial_mm_read[] = {
+    &serial_mm_readb,
+    &serial_mm_readw,
+    &serial_mm_readl,
+};
+
+static CPUWriteMemoryFunc *serial_mm_write[] = {
+    &serial_mm_writeb,
+    &serial_mm_writew,
+    &serial_mm_writel,
+};
+
+SerialState *serial_mm_init (target_phys_addr_t base, int it_shift,
+                             qemu_irq irq, CharDriverState *chr,
+                             int ioregister)
+{
+    SerialState *s;
+    int s_io_memory;
+
+    s = qemu_mallocz(sizeof(SerialState));
+    if (!s)
+        return NULL;
+    s->irq = irq;
+    s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
+    s->iir = UART_IIR_NO_INT;
+    s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
+    s->base = base;
+    s->it_shift = it_shift;
+
+    register_savevm("serial", base, 2, serial_save, serial_load, s);
+
+    if (ioregister) {
+        s_io_memory = cpu_register_io_memory(0, serial_mm_read,
+                                             serial_mm_write, s);
+        cpu_register_physical_memory(base, 8 << it_shift, s_io_memory);
+    }
+    s->chr = chr;
+    qemu_chr_add_handlers(chr, serial_can_receive1, serial_receive1,
+                          serial_event, s);
+    return s;
+}
+#endif
diff -r 092232fa1fbd extras/stubfw/ioemu/vl.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/ioemu/vl.c  Sun Nov 18 07:14:31 2007 +0100
@@ -0,0 +1,87 @@
+#include "vl.h"
+
+/***********************************************************/
+/* character device */
+
+void qemu_chr_event(CharDriverState *s, int event)
+{
+    if (!s->chr_event)
+        return;
+    s->chr_event(s->handler_opaque, event);
+}
+
+#ifndef IOEMU
+
+static void qemu_chr_reset_bh(void *opaque)
+{
+    CharDriverState *s = opaque;
+    qemu_chr_event(s, CHR_EVENT_RESET);
+    qemu_bh_delete(s->bh);
+    s->bh = NULL;
+}
+#endif
+
+void qemu_chr_reset(CharDriverState *s)
+{
+#ifndef IOEMU
+    if (s->bh == NULL) {
+       s->bh = qemu_bh_new(qemu_chr_reset_bh, s);
+       qemu_bh_schedule(s->bh);
+    }
+#endif
+}
+
+int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len)
+{
+    return s->chr_write(s, buf, len);
+}
+
+int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg)
+{
+    if (!s->chr_ioctl)
+        return -ENOTSUP;
+    return s->chr_ioctl(s, cmd, arg);
+}
+
+int qemu_chr_can_read(CharDriverState *s)
+{
+    if (!s->chr_can_read)
+        return 0;
+    return s->chr_can_read(s->handler_opaque);
+}
+
+void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len)
+{
+    s->chr_read(s->handler_opaque, buf, len);
+}
+
+
+void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
+{
+    char buf[4096];
+    va_list ap;
+    va_start(ap, fmt);
+    vsnprintf(buf, sizeof(buf), fmt, ap);
+    qemu_chr_write(s, buf, strlen(buf));
+    va_end(ap);
+}
+
+void qemu_chr_send_event(CharDriverState *s, int event)
+{
+    if (s->chr_send_event)
+        s->chr_send_event(s, event);
+}
+
+void qemu_chr_add_handlers(CharDriverState *s,
+                           IOCanRWHandler *fd_can_read,
+                           IOReadHandler *fd_read,
+                           IOEventHandler *fd_event,
+                           void *opaque)
+{
+    s->chr_can_read = fd_can_read;
+    s->chr_read = fd_read;
+    s->chr_event = fd_event;
+    s->handler_opaque = opaque;
+    if (s->chr_update_read_handler)
+        s->chr_update_read_handler(s);
+}
diff -r 092232fa1fbd extras/stubfw/ioemu/vl.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/ioemu/vl.h  Sun Nov 18 08:05:22 2007 +0100
@@ -0,0 +1,515 @@
+#include "lib.h"
+#include "types.h"
+#include "errno.h"
+#include "../vbd.h"
+
+#define IOEMU
+#define TARGET_PHYS_ADDR_BITS 64
+#define QEMU_VERSION "IOemu"
+#define TARGET_FMT_plx "%p"
+#define TARGET_FMT_lx "%016lx"
+#define PRIo64 "lo"
+#define PRIx64 "lx"
+#define PRIu64 "lu"
+#define PRId64 "ld"
+
+typedef uint64_t target_phys_addr_t;
+typedef uint64_t target_ulong; 
+typedef int64_t target_long; 
+
+extern int printf (const char *str, ...);
+extern void term_printf (const char *str, ...);
+//void pstrcpy(char *buf, int buf_size, const char *str);
+
+static inline uint16_t cpu_to_le16(uint16_t v)
+{
+  return v;
+}
+
+static inline uint32_t cpu_to_le32(uint32_t v)
+{
+  return v;
+}
+
+static inline uint16_t le16_to_cpu(uint16_t v)
+{
+  return v;
+}
+
+static inline uint32_t le32_to_cpu(uint32_t v)
+{
+  return v;
+}
+
+static inline void cpu_to_be16wu(uint16_t *p, uint16_t v)
+{
+    uint8_t *p1 = (uint8_t *)p;
+
+    p1[0] = v >> 8;
+    p1[1] = v;
+}
+
+static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
+{
+    uint8_t *p1 = (uint8_t *)p;
+
+    p1[0] = v >> 24;
+    p1[1] = v >> 16;
+    p1[2] = v >> 8;
+    p1[3] = v;
+}
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
+                            int len, int is_write);
+static inline void cpu_physical_memory_read(target_phys_addr_t addr,
+                                            uint8_t *buf, int len)
+{
+    cpu_physical_memory_rw(addr, buf, len, 0);
+}
+static inline void cpu_physical_memory_write(target_phys_addr_t addr,
+                                             const uint8_t *buf, int len)
+{
+    cpu_physical_memory_rw(addr, (uint8_t *)buf, len, 1);
+}
+
+#define ldub_raw(ADDR) (*((unsigned char*)(ADDR)))
+#define lduw_raw(ADDR) (*((unsigned short*)(ADDR)))
+#define ldl_raw(ADDR) (*((unsigned int*)(ADDR)))
+#define ldq_raw(ADDR) (*((unsigned long*)(ADDR)))
+
+void cpu_outb(int addr, int val);
+void cpu_outw(int addr, int val);
+void cpu_outl(int addr, int val);
+int cpu_inb(int addr);
+int cpu_inw(int addr);
+int cpu_inl(int addr);
+
+void init_ioports(void);
+
+#define register_savevm(NAME,A,B,S,L,D)
+
+/* async I/O support */
+
+typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
+typedef int IOCanRWHandler(void *opaque);
+typedef void IOHandler(void *opaque);
+
+/* character device */
+
+#define CHR_EVENT_BREAK 0 /* serial break char */
+#define CHR_EVENT_FOCUS 1 /* focus to this terminal (modal input needed) */
+#define CHR_EVENT_RESET 2 /* new connection established */
+
+
+#define CHR_IOCTL_SERIAL_SET_PARAMS   1
+typedef struct {
+    int speed;
+    int parity;
+    int data_bits;
+    int stop_bits;
+} QEMUSerialSetParams;
+
+#define CHR_IOCTL_SERIAL_SET_BREAK    2
+
+#define CHR_IOCTL_PP_READ_DATA        3
+#define CHR_IOCTL_PP_WRITE_DATA       4
+#define CHR_IOCTL_PP_READ_CONTROL     5
+#define CHR_IOCTL_PP_WRITE_CONTROL    6
+#define CHR_IOCTL_PP_READ_STATUS      7
+#define CHR_IOCTL_PP_EPP_READ_ADDR    8
+#define CHR_IOCTL_PP_EPP_READ         9
+#define CHR_IOCTL_PP_EPP_WRITE_ADDR  10
+#define CHR_IOCTL_PP_EPP_WRITE       11
+
+typedef void IOEventHandler(void *opaque, int event);
+
+typedef struct CharDriverState {
+    int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len);
+    void (*chr_update_read_handler)(struct CharDriverState *s);
+    int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg);
+    IOEventHandler *chr_event;
+    IOCanRWHandler *chr_can_read;
+    IOReadHandler *chr_read;
+    void *handler_opaque;
+    void (*chr_send_event)(struct CharDriverState *chr, int event);
+    void (*chr_close)(struct CharDriverState *chr);
+    void *opaque;
+    int focus;
+  //    QEMUBH *bh;
+} CharDriverState;
+
+CharDriverState *qemu_chr_open(const char *filename);
+void qemu_chr_printf(CharDriverState *s, const char *fmt, ...);
+int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
+void qemu_chr_send_event(CharDriverState *s, int event);
+void qemu_chr_add_handlers(CharDriverState *s,
+                           IOCanRWHandler *fd_can_read,
+                           IOReadHandler *fd_read,
+                           IOEventHandler *fd_event,
+                           void *opaque);
+int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg);
+void qemu_chr_reset(CharDriverState *s);
+int qemu_chr_can_read(CharDriverState *s);
+void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len);
+
+void qemu_chr_event(CharDriverState *s, int event);
+
+/* IRQ.  */
+/* Generic IRQ/GPIO pin infrastructure.  */
+typedef void SetIRQFunc(void *opaque, int irq_num, int level);
+
+typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
+
+typedef struct IRQState *qemu_irq;
+
+void qemu_set_irq(qemu_irq irq, int level);
+
+static inline void qemu_irq_raise(qemu_irq irq)
+{
+    qemu_set_irq(irq, 1);
+}
+
+static inline void qemu_irq_lower(qemu_irq irq)
+{
+    qemu_set_irq(irq, 0);
+}
+
+/* Returns an array of N IRQs.  */
+qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n);
+
+/* Returns a new IRQ with opposite polarity.  */
+qemu_irq qemu_irq_invert(qemu_irq irq);
+
+/* Serial.  */
+
+typedef struct SerialState SerialState;
+SerialState *serial_init(int base, qemu_irq irq, CharDriverState *chr);
+
+/* mc146818rtc.c */
+
+typedef struct RTCState RTCState;
+
+RTCState *rtc_init(int base, qemu_irq irq);
+RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq);
+void rtc_set_memory(RTCState *s, int addr, int val);
+//void rtc_set_date(RTCState *s, const struct tm *tm);
+
+void *qemu_mallocz(size_t size);
+
+/* ISA bus */
+
+extern target_phys_addr_t isa_mem_base;
+
+typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data);
+typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address);
+
+int register_ioport_read(int start, int length, int size,
+                         IOPortReadFunc *func, void *opaque);
+int register_ioport_write(int start, int length, int size,
+                          IOPortWriteFunc *func, void *opaque);
+void isa_unassign_ioport(int start, int length);
+
+void isa_mmio_init(target_phys_addr_t base, target_phys_addr_t size);
+
+/* PCI bus */
+
+extern target_phys_addr_t pci_mem_base;
+
+typedef struct PCIBus PCIBus;
+typedef struct PCIDevice PCIDevice;
+
+typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
+                                uint32_t address, uint32_t data, int len);
+typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev,
+                                   uint32_t address, int len);
+typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num,
+                                uint32_t addr, uint32_t size, int type);
+
+#define PCI_ADDRESS_SPACE_MEM          0x00
+#define PCI_ADDRESS_SPACE_IO           0x01
+#define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08
+
+typedef struct PCIIORegion {
+    uint32_t addr; /* current PCI mapping address. -1 means not mapped */
+    uint32_t size;
+    uint8_t type;
+    PCIMapIORegionFunc *map_func;
+} PCIIORegion;
+
+#define PCI_ROM_SLOT 6
+#define PCI_NUM_REGIONS 7
+
+#define PCI_DEVICES_MAX 64
+
+#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 */
+
+struct PCIDevice {
+    /* PCI config space */
+    uint8_t config[256];
+
+    /* the following fields are read only */
+    PCIBus *bus;
+    int devfn;
+    char name[64];
+    PCIIORegion io_regions[PCI_NUM_REGIONS];
+
+    /* do not access the following fields */
+    PCIConfigReadFunc *config_read;
+    PCIConfigWriteFunc *config_write;
+    /* ??? This is a PC-specific hack, and should be removed.  */
+    int irq_index;
+
+    /* IRQ objects for the INTA-INTD pins.  */
+    qemu_irq *irq;
+
+    /* Current IRQ levels.  Used internally by the generic PCI code.  */
+    int irq_state[4];
+};
+
+PCIDevice *pci_register_device(PCIBus *bus, const char *name,
+                               int instance_size, int devfn,
+                               PCIConfigReadFunc *config_read,
+                               PCIConfigWriteFunc *config_write);
+
+void pci_register_io_region(PCIDevice *pci_dev, int region_num,
+                            uint32_t size, int type,
+                            PCIMapIORegionFunc *map_func);
+
+uint32_t pci_default_read_config(PCIDevice *d,
+                                 uint32_t address, int len);
+void pci_default_write_config(PCIDevice *d,
+                              uint32_t address, uint32_t val, int len);
+
+typedef void (*pci_set_irq_fn)(qemu_irq *pic, int irq_num, int level);
+typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
+PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+                         qemu_irq *pic, int devfn_min, int nirq);
+
+void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
+uint32_t pci_data_read(void *opaque, uint32_t addr, int len);
+int pci_bus_num(PCIBus *s);
+void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d));
+
+void pci_info(void);
+PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
+                        pci_map_irq_fn map_irq, const char *name);
+
+/* prep_pci.c */
+PCIBus *pci_prep_init(qemu_irq *pic);
+
+/* piix_pci.c */
+PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic);
+void i440fx_set_smm(PCIDevice *d, int val);
+int piix4_init(PCIBus *bus, int devfn);
+
+/* Block drivers.  */
+/* block.c */
+typedef struct BlockDriverState BlockDriverState;
+typedef struct BlockDriver BlockDriver;
+
+extern BlockDriver bdrv_raw;
+extern BlockDriver bdrv_host_device;
+extern BlockDriver bdrv_cow;
+extern BlockDriver bdrv_qcow;
+extern BlockDriver bdrv_vmdk;
+extern BlockDriver bdrv_cloop;
+extern BlockDriver bdrv_dmg;
+extern BlockDriver bdrv_bochs;
+extern BlockDriver bdrv_vpc;
+extern BlockDriver bdrv_vvfat;
+extern BlockDriver bdrv_qcow2;
+extern BlockDriver bdrv_parallels;
+
+typedef struct BlockDriverInfo {
+    /* in bytes, 0 if irrelevant */
+    int cluster_size;
+    /* offset at which the VM state can be saved (0 if not possible) */
+    int64_t vm_state_offset;
+} BlockDriverInfo;
+
+typedef struct QEMUSnapshotInfo {
+    char id_str[128]; /* unique snapshot id */
+    /* the following fields are informative. They are not needed for
+       the consistency of the snapshot */
+    char name[256]; /* user choosen name */
+    uint32_t vm_state_size; /* VM state info size */
+    uint32_t date_sec; /* UTC date of the snapshot */
+    uint32_t date_nsec;
+    uint64_t vm_clock_nsec; /* VM clock relative to boot */
+} QEMUSnapshotInfo;
+
+#define BDRV_O_RDONLY      0x0000
+#define BDRV_O_RDWR        0x0002
+#define BDRV_O_ACCESS      0x0003
+#define BDRV_O_CREAT       0x0004 /* create an empty file */
+#define BDRV_O_SNAPSHOT    0x0008 /* open the file read only and save writes 
in a snapshot */
+#define BDRV_O_FILE        0x0010 /* open as a raw file (do not try to
+                                     use a disk image format on top of
+                                     it (default for
+                                     bdrv_file_open()) */
+
+void bdrv_init(void);
+BlockDriver *bdrv_find_format(const char *format_name);
+int bdrv_create(BlockDriver *drv,
+                const char *filename, int64_t size_in_sectors,
+                const char *backing_file, int flags);
+BlockDriverState *bdrv_new(const char *device_name);
+void bdrv_delete(BlockDriverState *bs);
+int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
+int bdrv_open(BlockDriverState *bs, const char *filename, int flags);
+int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
+               BlockDriver *drv);
+int bdrv_open_vbd(BlockDriverState *bs, struct vbd_info *info, int flags);
+void bdrv_close(BlockDriverState *bs);
+int bdrv_read(BlockDriverState *bs, int64_t sector_num,
+              uint8_t *buf, int nb_sectors);
+int bdrv_write(BlockDriverState *bs, int64_t sector_num,
+               const uint8_t *buf, int nb_sectors);
+int bdrv_pread(BlockDriverState *bs, int64_t offset,
+               void *buf, int count);
+int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
+                const void *buf, int count);
+int bdrv_truncate(BlockDriverState *bs, int64_t offset);
+int64_t bdrv_getlength(BlockDriverState *bs);
+void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr);
+int bdrv_commit(BlockDriverState *bs);
+void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size);
+/* async block I/O */
+typedef struct BlockDriverAIOCB BlockDriverAIOCB;
+typedef void BlockDriverCompletionFunc(void *opaque, int ret);
+
+BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
+                                uint8_t *buf, int nb_sectors,
+                                BlockDriverCompletionFunc *cb, void *opaque);
+BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
+                                 const uint8_t *buf, int nb_sectors,
+                                 BlockDriverCompletionFunc *cb, void *opaque);
+void bdrv_aio_cancel(BlockDriverAIOCB *acb);
+
+void qemu_aio_init(void);
+void qemu_aio_poll(void);
+void qemu_aio_flush(void);
+void qemu_aio_wait_start(void);
+void qemu_aio_wait(void);
+void qemu_aio_wait_end(void);
+
+int qemu_key_check(BlockDriverState *bs, const char *name);
+
+/* Ensure contents are flushed to disk.  */
+void bdrv_flush(BlockDriverState *bs);
+
+#define BDRV_TYPE_HD     0
+#define BDRV_TYPE_CDROM  1
+#define BDRV_TYPE_FLOPPY 2
+#define BIOS_ATA_TRANSLATION_AUTO   0
+#define BIOS_ATA_TRANSLATION_NONE   1
+#define BIOS_ATA_TRANSLATION_LBA    2
+#define BIOS_ATA_TRANSLATION_LARGE  3
+#define BIOS_ATA_TRANSLATION_RECHS  4
+
+void bdrv_set_geometry_hint(BlockDriverState *bs,
+                            int cyls, int heads, int secs);
+void bdrv_set_type_hint(BlockDriverState *bs, int type);
+void bdrv_set_translation_hint(BlockDriverState *bs, int translation);
+void bdrv_get_geometry_hint(BlockDriverState *bs,
+                            int *pcyls, int *pheads, int *psecs);
+int bdrv_get_type_hint(BlockDriverState *bs);
+int bdrv_get_translation_hint(BlockDriverState *bs);
+int bdrv_is_removable(BlockDriverState *bs);
+int bdrv_is_read_only(BlockDriverState *bs);
+int bdrv_is_inserted(BlockDriverState *bs);
+int bdrv_media_changed(BlockDriverState *bs);
+int bdrv_is_locked(BlockDriverState *bs);
+void bdrv_set_locked(BlockDriverState *bs, int locked);
+void bdrv_eject(BlockDriverState *bs, int eject_flag);
+void bdrv_set_change_cb(BlockDriverState *bs,
+                        void (*change_cb)(void *opaque), void *opaque);
+void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size);
+void bdrv_info(void);
+BlockDriverState *bdrv_find(const char *name);
+void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque);
+int bdrv_is_encrypted(BlockDriverState *bs);
+int bdrv_set_key(BlockDriverState *bs, const char *key);
+void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
+                         void *opaque);
+const char *bdrv_get_device_name(BlockDriverState *bs);
+int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
+                          const uint8_t *buf, int nb_sectors);
+int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
+
+void bdrv_get_backing_filename(BlockDriverState *bs,
+                               char *filename, int filename_size);
+int bdrv_snapshot_create(BlockDriverState *bs,
+                         QEMUSnapshotInfo *sn_info);
+int bdrv_snapshot_goto(BlockDriverState *bs,
+                       const char *snapshot_id);
+int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id);
+int bdrv_snapshot_list(BlockDriverState *bs,
+                       QEMUSnapshotInfo **psn_info);
+char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn);
+
+char *get_human_readable_size(char *buf, int buf_size, int64_t size);
+int path_is_absolute(const char *path);
+void path_combine(char *dest, int dest_size,
+                  const char *base_path,
+                  const char *filename);
+
+/* ide.c */
+#define MAX_DISKS 4
+
+extern BlockDriverState *bs_table[MAX_DISKS + 1];
+extern BlockDriverState *sd_bdrv;
+extern BlockDriverState *mtd_bdrv;
+
+void isa_ide_init(int iobase, int iobase2, qemu_irq irq,
+                  BlockDriverState *hd0, BlockDriverState *hd1);
+void pci_cmd646_ide_init(PCIBus *bus, BlockDriverState **hd_table,
+                         int secondary_ide_enabled);
+void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
+                        qemu_irq *pic);
+void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
+                        qemu_irq *pic);
+
+/* cdrom.c */
+int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
+int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
+
+#define SECTOR_BITS 9
+#define SECTOR_SIZE (1 << SECTOR_BITS)
+#define SECTOR_MASK (SECTOR_SIZE - 1)
+
+/* readline.c */
+typedef void ReadLineFunc(void *opaque, const char *str);
+
+extern int completion_index;
+void add_completion(const char *str);
+void readline_handle_byte(int ch);
+void readline_find_completion(const char *cmdline);
+const char *readline_get_history(unsigned int index);
+void readline_start(const char *prompt, int is_password,
+                    ReadLineFunc *readline_func, void *opaque);
+
+void kqemu_record_dump(void);
+
+
+/* IOemu.  */
+CharDriverState *qemu_chr_open_xc(void);
+CharDriverState *qemu_chr_open_mux(CharDriverState *drv);
+void monitor_init(CharDriverState *hd, int show_banner);
+
diff -r 092232fa1fbd extras/stubfw/main.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/main.c      Tue Nov 20 02:28:22 2007 +0100
@@ -0,0 +1,228 @@
+#include "types.h"
+#include "lib.h"
+#include "os.h"
+#include "console.h"
+#include "events.h"
+#include "ioemu/vl.h"
+#include "callback.h"
+#include "xenbus.h"
+#include "gnttab.h"
+
+struct IRQState {
+    qemu_irq_handler handler;
+    void *opaque;
+    int n;
+};
+
+extern void test_xenbus (void);
+extern void init_vbd (void);
+extern void vbd_test (void);
+extern qemu_irq *init_iosapic (void);
+/* Firmware memory map:
+   Start  at 0xff000000  size: 16MB (16GB - 16MB)
+   HOB    at 0xff200000  size:  1MB (16GB - 14MB)
+   Stacks at 0xff300000  size:  2MB
+   dev    at 0xff700000  size:  1MB
+   stubfw at 0xff800000  size:  2MB
+   NVRAM  at 0xffa00000  size: 64KB (16GB -  6MB) 
+   EFI    at 0xffe00000  size:  2MB
+*/
+
+
+#define BUG_ON(cond)
+
+extern int
+build_hob(unsigned long dom_mem_size, unsigned long vcpus,
+         unsigned long nvram_addr);
+
+void *serial1;
+static void *rtc;
+static PCIDevice *i440fx_state;
+static int piix4_devfn;
+static PCIBus *pci_bus;
+
+volatile struct shared_info *shared_info = (struct shared_info 
*)0x00000000e4008000UL;
+
+void
+setup_shared_info (void)
+{
+  struct xen_add_to_physmap xatp;
+
+  xatp.domid = DOMID_SELF;
+  xatp.idx = 0;
+  xatp.space = XENMAPSPACE_shared_info;
+  xatp.gpfn = ((unsigned long)shared_info) >> PAGE_SHIFT;
+  if (HYPERVISOR_add_to_physmap (&xatp))
+    BUG();
+}
+
+void
+exit (void)
+{
+  HYPERVISOR_shutdown(SHUTDOWN_poweroff);
+  while (1) ;
+}
+
+void
+dump_shared_info (void)
+{
+  int i;
+  printk ("evtchn mask - pending:\n");
+  for (i = 0; i < 8; i++)
+    printk (" %016lx %016lx\n",
+           shared_info->evtchn_mask[i], shared_info->evtchn_pending[i]);
+  for (i = 0; i < 1; i++)
+    {
+      volatile struct vcpu_info *info = &shared_info->vcpu_info[i];
+      printk ("vcpu %d: pending=%d mask=%d sel=%016lx\n",
+             i,
+             info->evtchn_upcall_pending,
+             info->evtchn_upcall_mask,
+             info->evtchn_pending_sel);
+    }
+}
+
+
+extern const char callback_entry;
+
+struct cb_status {
+  unsigned long status;
+  unsigned long arg1;
+  unsigned long arg2;
+  unsigned long arg3;
+};
+
+int ioemu_trace;
+
+struct cb_status
+ia64_callback (unsigned long cause,
+              unsigned long arg1, unsigned long arg2,
+              unsigned long arg3, unsigned long arg4,
+              unsigned long arg5,
+              struct ia64_cb_regs *regs)
+{
+  if (ioemu_trace)
+    printk ("call_back: cause=%lx, arg1=%lx, arg2=%lx, arg3=%lx, arg4=%lx\n",
+           cause, arg1, arg2, arg3, arg4);
+
+  if (cause == 0) {
+    do_hypervisor_callback ();
+    return ((struct cb_status){0,0,0,0});
+  }
+  else if (cause == 1) {
+    int sz = arg4 & 0x07;
+    int mode_r = arg4 & 0x80;
+    unsigned long paddr = arg1;
+
+    static int count;
+
+    if (++count == 400)
+      printk ("$$$ CALLBACK: ip = %lx paddr=%lx\n", regs->ip, paddr);
+
+    if (paddr >= 0x0e0000000 && paddr < 0x0e4000000) {
+      /* IO port.  */
+      unsigned int port = (((paddr >> 12) & 0x3fff) << 2) | (paddr & 0x03);
+      //printk ("ioport=0x%x\n", port);
+      switch (sz | (mode_r >> 4))
+       {
+       case 0x8:
+         arg2 = cpu_inb (port);
+         break;
+       case 0x9:
+         arg2 = cpu_inw (port);
+         break;
+       case 0xa:
+         arg2 = cpu_inl (port);
+         break;
+       case 0x0:
+         cpu_outb (port, arg2);
+         break;
+       case 0x1:
+         cpu_outw (port, arg2);
+         break;
+       case 0x2:
+         cpu_outl (port, arg2);
+         break;
+       default:
+         printk ("callback: io emul port=%lx data=%lx sz=%d %c ",
+                 port, arg2, 1 << sz, mode_r ? 'r' : 'w');
+         printk ("ip = %lx\n", regs->ip);
+         exit ();
+       }
+      return ((struct cb_status){1,arg4,arg2,0});
+    }
+    printk ("callback: io emul addr=%lx data=%lx sz=%d %c\n",
+           paddr, arg2, 1 << sz, mode_r ? 'r' : 'w');
+    printk ("ip = %lx\n", regs->ip);
+
+    exit();
+  }
+  else {
+    printk ("call_back: cause=%lx, arg1=%lx, arg2=%lx, arg3=%lx, arg4=%lx\n",
+           cause, arg1, arg2, arg3, arg4);
+    exit ();
+  }
+  return ((struct cb_status){0xff,0,0,0});
+}
+
+void cmain (unsigned long xstore_desc, unsigned long cons_desc,
+           unsigned long mem_mb, unsigned long nvcpu)
+{
+  qemu_irq *iosapic;
+  CharDriverState *chr;
+
+  setup_shared_info ();
+  init_events ();
+  init_console ((void *)(cons_desc & ~0xfffUL), cons_desc & 0xfff);
+
+  printk ("xstore: %lx\n", xstore_desc);
+  printk ("console: %lx\n", cons_desc);
+  printk ("mem_mb: %d, vcpus: %d\n", mem_mb, nvcpu);
+
+  shared_info->vcpu_info[0].evtchn_upcall_mask = 1;
+
+  HYPERVISOR_HVMSTUB_set_callback(&callback_entry, (void *)0xff300000);
+
+  dump_shared_info ();
+
+  init_xenbus ((void *)(xstore_desc & ~0xfffUL), xstore_desc & 0xfff);
+#if 0
+  test_xenbus ();
+  exit ();
+#endif
+  init_gnttab ();
+  bdrv_init ();
+  init_vbd ();
+
+  chr = qemu_chr_open_xc ();
+
+  // vbd_test ();
+  init_ioports ();
+
+  iosapic = init_iosapic ();
+
+  /* Set up devices.  */
+  pci_bus = i440fx_init(&i440fx_state, iosapic);
+  piix4_devfn = -1;
+  piix4_devfn = piix4_init(pci_bus, -1);
+  
+  //pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);
+  pci_piix4_ide_init(pci_bus, bs_table, piix4_devfn + 1, iosapic);
+
+  serial1 = serial_init (0x3f8, iosapic[4], chr);
+  rtc = rtc_init (0x70, iosapic[8]);
+
+  pci_info ();
+
+  build_hob (mem_mb << 20, nvcpu, 0xffa00000UL);
+
+  /* psr= IA64_PSR_AC | IA64_PSR_BN  */
+  HYPERVISOR_HVMSTUB_fw_start(0x80000000ffffffb0UL,
+                             (1UL << 44) | (1UL << 3));
+
+  printk ("failed to start fw\n");
+  shared_info->vcpu_info[0].evtchn_upcall_mask = 0;
+
+  while (1)
+    ;
+}
diff -r 092232fa1fbd extras/stubfw/netfront.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/netfront.c  Wed Nov 14 02:19:13 2007 +0100
@@ -0,0 +1,456 @@
+/* Minimal network driver for Mini-OS. 
+ * Copyright (c) 2006-2007 Jacob Gorm Hansen, University of Copenhagen.
+ * Based on netfront.c from Xen Linux.
+ *
+ * Does not handle fragments or extras.
+ */
+
+#include <os.h>
+#include <xenbus.h>
+#include <events.h>
+#include <errno.h>
+#include <xen/io/netif.h>
+#include <gnttab.h>
+#include <xmalloc.h>
+#include <time.h>
+
+void init_rx_buffers(void);
+
+struct net_info {
+    struct netif_tx_front_ring tx;
+    struct netif_rx_front_ring rx;
+    int tx_ring_ref;
+    int rx_ring_ref;
+    unsigned int evtchn, local_port;
+
+} net_info;
+
+
+char* xenbus_printf(xenbus_transaction_t xbt,
+        char* node,char* path,
+        char* fmt,unsigned int arg)
+{
+    char fullpath[256];
+    char val[256];
+
+    sprintf(fullpath,"%s/%s",node,path);
+    sprintf(val,fmt,arg);
+    xenbus_write(xbt,fullpath,val);
+
+    return NULL;
+}
+
+
+#define NET_TX_RING_SIZE __RING_SIZE((struct netif_tx_sring *)0, PAGE_SIZE)
+#define NET_RX_RING_SIZE __RING_SIZE((struct netif_rx_sring *)0, PAGE_SIZE)
+#define GRANT_INVALID_REF 0
+
+
+unsigned short rx_freelist[NET_RX_RING_SIZE];
+unsigned short tx_freelist[NET_TX_RING_SIZE];
+
+struct net_buffer {
+    void* page;
+    int gref;
+};
+struct net_buffer rx_buffers[NET_RX_RING_SIZE];
+struct net_buffer tx_buffers[NET_TX_RING_SIZE];
+
+static inline void add_id_to_freelist(unsigned int id,unsigned short* freelist)
+{
+    freelist[id] = freelist[0];
+    freelist[0]  = id;
+}
+
+static inline unsigned short get_id_from_freelist(unsigned short* freelist)
+{
+    unsigned int id = freelist[0];
+    freelist[0] = freelist[id];
+    return id;
+}
+
+__attribute__((weak)) void netif_rx(unsigned char* data,int len)
+{
+    printk("%d bytes incoming at %p\n",len,data);
+}
+
+__attribute__((weak)) void net_app_main(void*si,unsigned char*mac) {}
+
+static inline int xennet_rxidx(RING_IDX idx)
+{
+    return idx & (NET_RX_RING_SIZE - 1);
+}
+
+void network_rx(void)
+{
+    struct net_info *np = &net_info;
+    RING_IDX rp,cons;
+    struct netif_rx_response *rx;
+
+
+moretodo:
+    rp = np->rx.sring->rsp_prod;
+    rmb(); /* Ensure we see queued responses up to 'rp'. */
+    cons = np->rx.rsp_cons;
+
+    int nr_consumed=0;
+    while ((cons != rp))
+    {
+        struct net_buffer* buf;
+        unsigned char* page;
+
+        rx = RING_GET_RESPONSE(&np->rx, cons);
+
+        if (rx->flags & NETRXF_extra_info)
+        {
+            printk("+++++++++++++++++++++ we have extras!\n");
+            continue;
+        }
+
+
+        if (rx->status == NETIF_RSP_NULL) continue;
+
+        int id = rx->id;
+
+        buf = &rx_buffers[id];
+        page = (unsigned char*)buf->page;
+        gnttab_end_access(buf->gref);
+
+        if(rx->status>0)
+        {
+            netif_rx(page+rx->offset,rx->status);
+        }
+
+        add_id_to_freelist(id,rx_freelist);
+
+        nr_consumed++;
+
+        ++cons;
+    }
+    np->rx.rsp_cons=rp;
+
+    int more;
+    RING_FINAL_CHECK_FOR_RESPONSES(&np->rx,more);
+    if(more) goto moretodo;
+
+    RING_IDX req_prod = np->rx.req_prod_pvt;
+
+    int i;
+    netif_rx_request_t *req;
+
+    for(i=0; i<nr_consumed; i++)
+    {
+        int id = xennet_rxidx(req_prod + i);
+        req = RING_GET_REQUEST(&np->rx, req_prod + i);
+        struct net_buffer* buf = &rx_buffers[id];
+        void* page = buf->page;
+
+        buf->gref = req->gref = 
+            gnttab_grant_access(0,virt_to_mfn(page),0);
+
+        req->id = id;
+    }
+
+    wmb();
+
+    np->rx.req_prod_pvt = req_prod + i;
+    
+    int notify;
+    RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->rx, notify);
+    if (notify)
+        notify_remote_via_evtchn(np->evtchn);
+
+}
+
+void network_tx_buf_gc(void)
+{
+
+
+    RING_IDX cons, prod;
+    unsigned short id;
+    struct net_info *np = &net_info;
+
+    do {
+        prod = np->tx.sring->rsp_prod;
+        rmb(); /* Ensure we see responses up to 'rp'. */
+
+        for (cons = np->tx.rsp_cons; cons != prod; cons++) 
+        {
+            struct netif_tx_response *txrsp;
+
+            txrsp = RING_GET_RESPONSE(&np->tx, cons);
+            if (txrsp->status == NETIF_RSP_NULL)
+                continue;
+
+            id  = txrsp->id;
+            struct net_buffer* buf = &tx_buffers[id];
+            gnttab_end_access(buf->gref);
+            buf->gref=GRANT_INVALID_REF;
+
+            add_id_to_freelist(id,tx_freelist);
+        }
+
+        np->tx.rsp_cons = prod;
+
+        /*
+         * Set a new event, then check for race with update of tx_cons.
+         * Note that it is essential to schedule a callback, no matter
+         * how few tx_buffers are pending. Even if there is space in the
+         * transmit ring, higher layers may be blocked because too much
+         * data is outstanding: in such cases notification from Xen is
+         * likely to be the only kick that we'll get.
+         */
+        np->tx.sring->rsp_event =
+            prod + ((np->tx.sring->req_prod - prod) >> 1) + 1;
+        mb();
+    } while ((cons == prod) && (prod != np->tx.sring->rsp_prod));
+
+
+}
+
+void netfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
+{
+    int flags;
+
+    local_irq_save(flags);
+
+    network_tx_buf_gc();
+    network_rx();
+
+    local_irq_restore(flags);
+}
+
+char* backend;
+
+void init_netfront(void* si)
+{
+    xenbus_transaction_t xbt;
+    struct net_info* info = &net_info;
+    char* err;
+    char* message=NULL;
+    char nodename[] = "device/vif/0";
+    struct netif_tx_sring *txs;
+    struct netif_rx_sring *rxs;
+    int retry=0;
+    int i;
+    char* mac;
+    char* msg;
+
+    printk("************************ NETFRONT **********\n\n\n");
+
+    for(i=0;i<NET_TX_RING_SIZE;i++)
+    {
+        add_id_to_freelist(i,tx_freelist);
+        tx_buffers[i].page = (char*)alloc_page();
+    }
+
+    for(i=0;i<NET_RX_RING_SIZE;i++)
+    {
+        add_id_to_freelist(i,rx_freelist);
+        rx_buffers[i].page = (char*)alloc_page();
+    }
+
+    txs = (struct netif_tx_sring*) alloc_page();
+    rxs = (struct netif_rx_sring *) alloc_page();
+    memset(txs,0,PAGE_SIZE);
+    memset(rxs,0,PAGE_SIZE);
+
+
+    SHARED_RING_INIT(txs);
+    SHARED_RING_INIT(rxs);
+    FRONT_RING_INIT(&info->tx, txs, PAGE_SIZE);
+    FRONT_RING_INIT(&info->rx, rxs, PAGE_SIZE);
+
+    info->tx_ring_ref = gnttab_grant_access(0,virt_to_mfn(txs),0);
+    info->rx_ring_ref = gnttab_grant_access(0,virt_to_mfn(rxs),0);
+
+    evtchn_alloc_unbound_t op;
+    op.dom = DOMID_SELF;
+    op.remote_dom = 0;
+    HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
+    clear_evtchn(op.port);        /* Without, handler gets invoked now! */
+    info->local_port = bind_evtchn(op.port, netfront_handler, NULL);
+    info->evtchn=op.port;
+
+again:
+    err = xenbus_transaction_start(&xbt);
+    if (err) {
+        printk("starting transaction\n");
+    }
+
+    err = xenbus_printf(xbt, nodename, "tx-ring-ref","%u",
+                info->tx_ring_ref);
+    if (err) {
+        message = "writing tx ring-ref";
+        goto abort_transaction;
+    }
+    err = xenbus_printf(xbt, nodename, "rx-ring-ref","%u",
+                info->rx_ring_ref);
+    if (err) {
+        message = "writing rx ring-ref";
+        goto abort_transaction;
+    }
+    err = xenbus_printf(xbt, nodename,
+                "event-channel", "%u", info->evtchn);
+    if (err) {
+        message = "writing event-channel";
+        goto abort_transaction;
+    }
+
+    err = xenbus_printf(xbt, nodename, "request-rx-copy", "%u", 1);
+
+    if (err) {
+        message = "writing request-rx-copy";
+        goto abort_transaction;
+    }
+
+    err = xenbus_printf(xbt, nodename, "state", "%u",
+            4); /* connected */
+
+
+    err = xenbus_transaction_end(xbt, 0, &retry);
+    if (retry) {
+            goto again;
+        printk("completing transaction\n");
+    }
+
+    goto done;
+
+abort_transaction:
+    xenbus_transaction_end(xbt, 1, &retry);
+
+done:
+
+    msg = xenbus_read(XBT_NIL, "device/vif/0/backend", &backend);
+    msg = xenbus_read(XBT_NIL, "device/vif/0/mac", &mac);
+
+    if ((backend == NULL) || (mac == NULL)) {
+        struct evtchn_close op = { info->local_port };
+        printk("%s: backend/mac failed\n", __func__);
+        unbind_evtchn(info->local_port);
+        HYPERVISOR_event_channel_op(EVTCHNOP_close, &op);
+        return;
+    }
+
+    printk("backend at %s\n",backend);
+    printk("mac is %s\n",mac);
+
+    char path[256];
+    sprintf(path,"%s/state",backend);
+
+    xenbus_watch_path(XBT_NIL, path);
+
+    xenbus_wait_for_value(path,"4");
+
+    //free(backend);
+
+    printk("**************************\n");
+
+    init_rx_buffers();
+
+    unsigned char rawmac[6];
+        /* Special conversion specifier 'hh' needed for __ia64__. Without
+           this mini-os panics with 'Unaligned reference'. */
+    sscanf(mac,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+            &rawmac[0],
+            &rawmac[1],
+            &rawmac[2],
+            &rawmac[3],
+            &rawmac[4],
+            &rawmac[5]);
+
+    net_app_main(si,rawmac);
+}
+
+void shutdown_netfront(void)
+{
+    //xenbus_transaction_t xbt;
+    char* err;
+    char nodename[] = "device/vif/0";
+
+    char path[256];
+
+    printk("close network: backend at %s\n",backend);
+
+    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6); /* closing */
+    sprintf(path,"%s/state",backend);
+
+    xenbus_wait_for_value(path,"6");
+
+    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
+
+    xenbus_wait_for_value(path,"2");
+
+    unbind_all_ports();
+
+}
+
+
+void init_rx_buffers(void)
+{
+    struct net_info* np = &net_info;
+    int i, requeue_idx;
+    netif_rx_request_t *req;
+    int notify;
+
+    /* Rebuild the RX buffer freelist and the RX ring itself. */
+    for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) 
+    {
+        struct net_buffer* buf = &rx_buffers[requeue_idx];
+        req = RING_GET_REQUEST(&np->rx, requeue_idx);
+
+        buf->gref = req->gref = 
+            gnttab_grant_access(0,virt_to_mfn(buf->page),0);
+
+        req->id = requeue_idx;
+
+        requeue_idx++;
+    }
+
+    np->rx.req_prod_pvt = requeue_idx;
+
+    RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->rx, notify);
+
+    if (notify) 
+        notify_remote_via_evtchn(np->evtchn);
+
+    np->rx.sring->rsp_event = np->rx.rsp_cons + 1;
+}
+
+
+void netfront_xmit(unsigned char* data,int len)
+{
+    int flags;
+    local_irq_save(flags);
+
+    struct net_info* info = &net_info;
+    struct netif_tx_request *tx;
+    RING_IDX i = info->tx.req_prod_pvt;
+    int notify;
+    int id = get_id_from_freelist(tx_freelist);
+    struct net_buffer* buf = &tx_buffers[id];
+    void* page = buf->page;
+
+    tx = RING_GET_REQUEST(&info->tx, i);
+
+    memcpy(page,data,len);
+
+    buf->gref = 
+        tx->gref = gnttab_grant_access(0,virt_to_mfn(page),0);
+
+    tx->offset=0;
+    tx->size = len;
+    tx->flags=0;
+    tx->id = id;
+    info->tx.req_prod_pvt = i + 1;
+
+    wmb();
+
+    RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->tx, notify);
+
+    if(notify) notify_remote_via_evtchn(info->evtchn);
+
+    network_tx_buf_gc();
+
+    local_irq_restore(flags);
+}
diff -r 092232fa1fbd extras/stubfw/printf.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/printf.c    Wed Nov 07 00:40:13 2007 +0100
@@ -0,0 +1,793 @@
+/* 
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ ****************************************************************************
+ *
+ *        File: printf.c
+ *      Author: Rolf Neugebauer (neugebar@xxxxxxxxxxxxx)
+ *     Changes: Grzegorz Milos (gm281@xxxxxxxxx) 
+ *              
+ *        Date: Aug 2003, Aug 2005
+ * 
+ * Environment: Xen Minimal OS
+ * Description: Library functions for printing
+ *              (freebsd port, mainly sys/subr_prf.c)
+ *
+ ****************************************************************************
+ *
+ *-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/libkern/divdi3.c,v 1.6 1999/08/28 00:46:31 peter Exp $
+ */
+
+#if !defined HAVE_LIBC
+
+#include <os.h>
+#include <types.h>
+#include <hypervisor.h>
+#include <lib.h>
+#include <ctype.h>
+
+/**
+ * simple_strtoul - convert a string to an unsigned long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
+{
+    unsigned long result = 0,value;
+
+    if (!base) {
+        base = 10;
+        if (*cp == '0') {
+            base = 8;
+            cp++;
+            if ((*cp == 'x') && isxdigit(cp[1])) {
+                cp++;
+                base = 16;
+            }
+        }
+    }
+    while (isxdigit(*cp) &&
+           (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
+        result = result*base + value;
+        cp++;
+    }
+    if (endp)
+        *endp = (char *)cp;
+    return result;
+}
+
+/**
+ * simple_strtol - convert a string to a signed long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+long simple_strtol(const char *cp,char **endp,unsigned int base)
+{
+    if(*cp=='-')
+        return -simple_strtoul(cp+1,endp,base);
+    return simple_strtoul(cp,endp,base);
+}
+
+/**
+ * simple_strtoull - convert a string to an unsigned long long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int 
base)
+{
+    unsigned long long result = 0,value;
+
+    if (!base) {
+        base = 10;
+        if (*cp == '0') {
+            base = 8;
+            cp++;
+            if ((*cp == 'x') && isxdigit(cp[1])) {
+                cp++;
+                base = 16;
+            }
+        }
+    }
+    while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
+                                                               ? toupper(*cp) 
: *cp)-'A'+10) < base) {
+        result = result*base + value;
+        cp++;
+    }
+    if (endp)
+        *endp = (char *)cp;
+    return result;
+}
+
+/**
+ * simple_strtoll - convert a string to a signed long long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+long long simple_strtoll(const char *cp,char **endp,unsigned int base)
+{
+    if(*cp=='-')
+        return -simple_strtoull(cp+1,endp,base);
+    return simple_strtoull(cp,endp,base);
+}
+
+static int skip_atoi(const char **s)
+{
+    int i=0;
+
+    while (isdigit(**s))
+        i = i*10 + *((*s)++) - '0';
+    return i;
+}
+
+#define ZEROPAD 1               /* pad with zero */
+#define SIGN    2               /* unsigned/signed long */
+#define PLUS    4               /* show plus */
+#define SPACE   8               /* space if plus */
+#define LEFT    16              /* left justified */
+#define SPECIAL 32              /* 0x */
+#define LARGE   64              /* use 'ABCDEF' instead of 'abcdef' */
+
+static char * number(char * buf, char * end, long long num, int base, int 
size, int precision, int type)
+{
+    char c,sign,tmp[66];
+    const char *digits;
+    const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+    const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    int i;
+
+    digits = (type & LARGE) ? large_digits : small_digits;
+    if (type & LEFT)
+        type &= ~ZEROPAD;
+    if (base < 2 || base > 36)
+        return buf;
+    c = (type & ZEROPAD) ? '0' : ' ';
+    sign = 0;
+    if (type & SIGN) {
+        if (num < 0) {
+            sign = '-';
+            num = -num;
+            size--;
+        } else if (type & PLUS) {
+            sign = '+';
+            size--;
+        } else if (type & SPACE) {
+            sign = ' ';
+            size--;
+        }
+    }
+    if (type & SPECIAL) {
+        if (base == 16)
+            size -= 2;
+        else if (base == 8)
+            size--;
+    }
+    i = 0;
+    if (num == 0)
+        tmp[i++]='0';
+    else 
+    {
+        /* XXX KAF: force unsigned mod and div. */
+        unsigned long long num2=(unsigned long long)num;
+        unsigned int base2=(unsigned int)base;
+        while (num2 != 0) { tmp[i++] = digits[num2%base2]; num2 /= base2; }
+    }
+    if (i > precision)
+        precision = i;
+    size -= precision;
+    if (!(type&(ZEROPAD+LEFT))) {
+        while(size-->0) {
+            if (buf <= end)
+                *buf = ' ';
+            ++buf;
+        }
+    }
+    if (sign) {
+        if (buf <= end)
+            *buf = sign;
+        ++buf;
+    }
+    if (type & SPECIAL) {
+        if (base==8) {
+            if (buf <= end)
+                *buf = '0';
+            ++buf;
+        } else if (base==16) {
+            if (buf <= end)
+                *buf = '0';
+            ++buf;
+            if (buf <= end)
+                *buf = digits[33];
+            ++buf;
+        }
+    }
+    if (!(type & LEFT)) {
+        while (size-- > 0) {
+            if (buf <= end)
+                *buf = c;
+            ++buf;
+        }
+    }
+    while (i < precision--) {
+        if (buf <= end)
+            *buf = '0';
+        ++buf;
+    }
+    while (i-- > 0) {
+        if (buf <= end)
+            *buf = tmp[i];
+        ++buf;
+    }
+    while (size-- > 0) {
+        if (buf <= end)
+            *buf = ' ';
+        ++buf;
+    }
+    return buf;
+}
+
+/**
+* vsnprintf - Format a string and place it in a buffer
+* @buf: The buffer to place the result into
+* @size: The size of the buffer, including the trailing null space
+* @fmt: The format string to use
+* @args: Arguments for the format string
+*
+* Call this function if you are already dealing with a va_list.
+* You probably want snprintf instead.
+ */
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+    int len;
+    unsigned long long num;
+    int i, base;
+    char *str, *end, c;
+    const char *s;
+
+    int flags;          /* flags to number() */
+
+    int field_width;    /* width of output field */
+    int precision;              /* min. # of digits for integers; max
+                                   number of chars for from string */
+    int qualifier;              /* 'h', 'l', or 'L' for integer fields */
+                                /* 'z' support added 23/7/1999 S.H.    */
+                                /* 'z' changed to 'Z' --davidm 1/25/99 */
+
+    str = buf;
+    end = buf + size - 1;
+
+    if (end < buf - 1) {
+        end = ((void *) -1);
+        size = end - buf + 1;
+    }
+
+    for (; *fmt ; ++fmt) {
+        if (*fmt != '%') {
+            if (str <= end)
+                *str = *fmt;
+            ++str;
+            continue;
+        }
+
+        /* process flags */
+        flags = 0;
+    repeat:
+        ++fmt;          /* this also skips first '%' */
+        switch (*fmt) {
+        case '-': flags |= LEFT; goto repeat;
+        case '+': flags |= PLUS; goto repeat;
+        case ' ': flags |= SPACE; goto repeat;
+        case '#': flags |= SPECIAL; goto repeat;
+        case '0': flags |= ZEROPAD; goto repeat;
+        }
+
+        /* get field width */
+        field_width = -1;
+        if (isdigit(*fmt))
+            field_width = skip_atoi(&fmt);
+        else if (*fmt == '*') {
+            ++fmt;
+            /* it's the next argument */
+            field_width = va_arg(args, int);
+            if (field_width < 0) {
+                field_width = -field_width;
+                flags |= LEFT;
+            }
+        }
+
+        /* get the precision */
+        precision = -1;
+        if (*fmt == '.') {
+            ++fmt;
+            if (isdigit(*fmt))
+                precision = skip_atoi(&fmt);
+            else if (*fmt == '*') {
+                ++fmt;
+                          /* it's the next argument */
+                precision = va_arg(args, int);
+            }
+            if (precision < 0)
+                precision = 0;
+        }
+
+        /* get the conversion qualifier */
+        qualifier = -1;
+        if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
+            qualifier = *fmt;
+            ++fmt;
+            if (qualifier == 'l' && *fmt == 'l') {
+                qualifier = 'L';
+                ++fmt;
+            }
+        }
+        if (*fmt == 'q') {
+            qualifier = 'L';
+            ++fmt;
+        }
+
+        /* default base */
+        base = 10;
+
+        switch (*fmt) {
+        case 'c':
+            if (!(flags & LEFT)) {
+                while (--field_width > 0) {
+                    if (str <= end)
+                        *str = ' ';
+                    ++str;
+                }
+            }
+            c = (unsigned char) va_arg(args, int);
+            if (str <= end)
+                *str = c;
+            ++str;
+            while (--field_width > 0) {
+                if (str <= end)
+                    *str = ' ';
+                ++str;
+            }
+            continue;
+
+        case 's':
+            s = va_arg(args, char *);
+            if (!s)
+                s = "<NULL>";
+
+            len = strnlen(s, precision);
+
+            if (!(flags & LEFT)) {
+                while (len < field_width--) {
+                    if (str <= end)
+                        *str = ' ';
+                    ++str;
+                }
+            }
+            for (i = 0; i < len; ++i) {
+                if (str <= end)
+                    *str = *s;
+                ++str; ++s;
+            }
+            while (len < field_width--) {
+                if (str <= end)
+                    *str = ' ';
+                ++str;
+            }
+            continue;
+
+        case 'p':
+            if (field_width == -1) {
+                field_width = 2*sizeof(void *);
+                flags |= ZEROPAD;
+            }
+            str = number(str, end,
+                         (unsigned long) va_arg(args, void *),
+                         16, field_width, precision, flags);
+            continue;
+
+
+        case 'n':
+            /* FIXME:
+             * What does C99 say about the overflow case here? */
+            if (qualifier == 'l') {
+                long * ip = va_arg(args, long *);
+                *ip = (str - buf);
+            } else if (qualifier == 'Z') {
+                size_t * ip = va_arg(args, size_t *);
+                *ip = (str - buf);
+            } else {
+                int * ip = va_arg(args, int *);
+                *ip = (str - buf);
+            }
+            continue;
+
+        case '%':
+            if (str <= end)
+                *str = '%';
+            ++str;
+            continue;
+
+                        /* integer number formats - set up the flags and 
"break" */
+        case 'o':
+            base = 8;
+            break;
+
+        case 'X':
+            flags |= LARGE;
+        case 'x':
+            base = 16;
+            break;
+
+        case 'd':
+        case 'i':
+            flags |= SIGN;
+        case 'u':
+            break;
+
+        default:
+            if (str <= end)
+                *str = '%';
+            ++str;
+            if (*fmt) {
+                if (str <= end)
+                    *str = *fmt;
+                ++str;
+            } else {
+                --fmt;
+            }
+            continue;
+        }
+        if (qualifier == 'L')
+            num = va_arg(args, long long);
+        else if (qualifier == 'l') {
+            num = va_arg(args, unsigned long);
+            if (flags & SIGN)
+                num = (signed long) num;
+        } else if (qualifier == 'Z') {
+            num = va_arg(args, size_t);
+        } else if (qualifier == 'h') {
+            num = (unsigned short) va_arg(args, int);
+            if (flags & SIGN)
+                num = (signed short) num;
+        } else {
+            num = va_arg(args, unsigned int);
+            if (flags & SIGN)
+                num = (signed int) num;
+        }
+
+        str = number(str, end, num, base,
+                     field_width, precision, flags);
+    }
+    if (str <= end)
+        *str = '\0';
+    else if (size > 0)
+        /* don't write out a null byte if the buf size is zero */
+        *end = '\0';
+    /* the trailing null byte doesn't count towards the total
+     * ++str;
+     */
+    return str-buf;
+}
+
+/**
+ * snprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ */
+int snprintf(char * buf, size_t size, const char *fmt, ...)
+{
+    va_list args;
+    int i;
+
+    va_start(args, fmt);
+    i=vsnprintf(buf,size,fmt,args);
+    va_end(args);
+    return i;
+}
+
+/**
+ * vsprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * Call this function if you are already dealing with a va_list.
+ * You probably want sprintf instead.
+ */
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+    return vsnprintf(buf, 0xFFFFFFFFUL, fmt, args);
+}
+
+
+/**
+ * sprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ */
+int sprintf(char * buf, const char *fmt, ...)
+{
+    va_list args;
+    int i;
+
+    va_start(args, fmt);
+    i=vsprintf(buf,fmt,args);
+    va_end(args);
+    return i;
+}
+
+/**
+ * vsscanf - Unformat a buffer into a list of arguments
+ * @buf:       input buffer
+ * @fmt:       format of buffer
+ * @args:      arguments
+ */
+int vsscanf(const char * buf, const char * fmt, va_list args)
+{
+       const char *str = buf;
+       char *next;
+       char digit;
+       int num = 0;
+       int qualifier;
+       int base;
+       int field_width;
+       int is_sign = 0;
+
+       while(*fmt && *str) {
+               /* skip any white space in format */
+               /* white space in format matchs any amount of
+                * white space, including none, in the input.
+                */
+               if (isspace(*fmt)) {
+                       while (isspace(*fmt))
+                               ++fmt;
+                       while (isspace(*str))
+                               ++str;
+               }
+
+               /* anything that is not a conversion must match exactly */
+               if (*fmt != '%' && *fmt) {
+                       if (*fmt++ != *str++)
+                               break;
+                       continue;
+               }
+
+               if (!*fmt)
+                       break;
+               ++fmt;
+               
+               /* skip this conversion.
+                * advance both strings to next white space
+                */
+               if (*fmt == '*') {
+                       while (!isspace(*fmt) && *fmt)
+                               fmt++;
+                       while (!isspace(*str) && *str)
+                               str++;
+                       continue;
+               }
+
+               /* get field width */
+               field_width = -1;
+               if (isdigit(*fmt))
+                       field_width = skip_atoi(&fmt);
+
+               /* get conversion qualifier */
+               qualifier = -1;
+               if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
+                   *fmt == 'Z' || *fmt == 'z') {
+                       qualifier = *fmt++;
+                       if (unlikely(qualifier == *fmt)) {
+                               if (qualifier == 'h') {
+                                       qualifier = 'H';
+                                       fmt++;
+                               } else if (qualifier == 'l') {
+                                       qualifier = 'L';
+                                       fmt++;
+                               }
+                       }
+               }
+               base = 10;
+               is_sign = 0;
+
+               if (!*fmt || !*str)
+                       break;
+
+               switch(*fmt++) {
+               case 'c':
+               {
+                       char *s = (char *) va_arg(args,char*);
+                       if (field_width == -1)
+                               field_width = 1;
+                       do {
+                               *s++ = *str++;
+                       } while (--field_width > 0 && *str);
+                       num++;
+               }
+               continue;
+               case 's':
+               {
+                       char *s = (char *) va_arg(args, char *);
+                       if(field_width == -1)
+                               field_width = INT_MAX;
+                       /* first, skip leading white space in buffer */
+                       while (isspace(*str))
+                               str++;
+
+                       /* now copy until next white space */
+                       while (*str && !isspace(*str) && field_width--) {
+                               *s++ = *str++;
+                       }
+                       *s = '\0';
+                       num++;
+               }
+               continue;
+               case 'n':
+                       /* return number of characters read so far */
+               {
+                       int *i = (int *)va_arg(args,int*);
+                       *i = str - buf;
+               }
+               continue;
+               case 'o':
+                       base = 8;
+                       break;
+               case 'x':
+               case 'X':
+                       base = 16;
+                       break;
+               case 'i':
+                        base = 0;
+               case 'd':
+                       is_sign = 1;
+               case 'u':
+                       break;
+               case '%':
+                       /* looking for '%' in str */
+                       if (*str++ != '%') 
+                               return num;
+                       continue;
+               default:
+                       /* invalid format; stop here */
+                       return num;
+               }
+
+               /* have some sort of integer conversion.
+                * first, skip white space in buffer.
+                */
+               while (isspace(*str))
+                       str++;
+
+               digit = *str;
+               if (is_sign && digit == '-')
+                       digit = *(str + 1);
+
+               if (!digit
+                    || (base == 16 && !isxdigit(digit))
+                    || (base == 10 && !isdigit(digit))
+                    || (base == 8 && (!isdigit(digit) || digit > '7'))
+                    || (base == 0 && !isdigit(digit)))
+                               break;
+
+               switch(qualifier) {
+               case 'H':       /* that's 'hh' in format */
+                       if (is_sign) {
+                               signed char *s = (signed char *) 
va_arg(args,signed char *);
+                               *s = (signed char) 
simple_strtol(str,&next,base);
+                       } else {
+                               unsigned char *s = (unsigned char *) 
va_arg(args, unsigned char *);
+                               *s = (unsigned char) simple_strtoul(str, &next, 
base);
+                       }
+                       break;
+               case 'h':
+                       if (is_sign) {
+                               short *s = (short *) va_arg(args,short *);
+                               *s = (short) simple_strtol(str,&next,base);
+                       } else {
+                               unsigned short *s = (unsigned short *) 
va_arg(args, unsigned short *);
+                               *s = (unsigned short) simple_strtoul(str, 
&next, base);
+                       }
+                       break;
+               case 'l':
+                       if (is_sign) {
+                               long *l = (long *) va_arg(args,long *);
+                               *l = simple_strtol(str,&next,base);
+                       } else {
+                               unsigned long *l = (unsigned long*) 
va_arg(args,unsigned long*);
+                               *l = simple_strtoul(str,&next,base);
+                       }
+                       break;
+               case 'L':
+                       if (is_sign) {
+                               long long *l = (long long*) va_arg(args,long 
long *);
+                               *l = simple_strtoll(str,&next,base);
+                       } else {
+                               unsigned long long *l = (unsigned long long*) 
va_arg(args,unsigned long long*);
+                               *l = simple_strtoull(str,&next,base);
+                       }
+                       break;
+               case 'Z':
+               case 'z':
+               {
+                       size_t *s = (size_t*) va_arg(args,size_t*);
+                       *s = (size_t) simple_strtoul(str,&next,base);
+               }
+               break;
+               default:
+                       if (is_sign) {
+                               int *i = (int *) va_arg(args, int*);
+                               *i = (int) simple_strtol(str,&next,base);
+                       } else {
+                               unsigned int *i = (unsigned int*) va_arg(args, 
unsigned int*);
+                               *i = (unsigned int) 
simple_strtoul(str,&next,base);
+                       }
+                       break;
+               }
+               num++;
+
+               if (!next)
+                       break;
+               str = next;
+       }
+       return num;
+}
+
+/**
+ * sscanf - Unformat a buffer into a list of arguments
+ * @buf:       input buffer
+ * @fmt:       formatting of buffer
+ * @...:       resulting arguments
+ */
+int sscanf(const char * buf, const char * fmt, ...)
+{
+       va_list args;
+       int i;
+
+       va_start(args,fmt);
+       i = vsscanf(buf,fmt,args);
+       va_end(args);
+       return i;
+}
+
+#endif
diff -r 092232fa1fbd extras/stubfw/startup.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/startup.S   Sat Nov 17 05:07:17 2007 +0100
@@ -0,0 +1,94 @@
+       .section .start,"ax"
+
+       .psr abi64
+       .psr lsb
+       .lsb
+
+       .globl _start
+       .proc _start
+_start:
+       /* IO-base.  */
+       movl r4=0x000000e0000000
+       ;;
+       mov ar.k0=r4
+       /* Init tpr.  */
+       mov cr.tpr=r0
+       /* Init RSE & stack. */
+       movl r2=0xff280000
+       mov ar.rsc=0    // lazy mode, 0 dirty bytes.
+       ;;
+       add r12=0x10000-16,r2
+       loadrs
+       ;;
+       movl r1=__gp
+       mov ar.bspstore=r2
+       ;;
+       srlz.d
+       movl r4=cmain
+       ;;
+       alloc   loc0=ar.pfs,0,1,4,0
+       mov out0=r8 // store
+       mov out1=r9 // console
+       mov out2=r10 // mem mb
+       mov out3=r11 // vcpu
+       //mov ar.rsc=3  // eager mode
+       ;;
+       bsw.1           // Use standard bank
+       ;;
+       movl r16=bss_start
+       movl r17=end
+       ;;
+       // Clear bss
+1:     cmp.ltu p6,p7=r16,r17
+       ;;
+       st8 [r16]=r0,8
+(p6)   br 1b
+       ;; 
+       mov  b1=r4
+       movl r5=pal_proc
+       ;;
+       mov  ar.k5=r5   // Pal entry point
+       br.call.sptk.many rp=b1
+       ;;
+       .endp _start
+
+       .text
+       
+       /* Pal.  */
+       .proc pal_proc
+pal_proc:
+       tbit.nz p7,p8=r28,8             /* 1-255 or 512-767: static conv (p8)*/
+       ;;
+       /* Xen always use the static convention.  */
+(p7)   mov r29=r33
+(p7)   mov r30=r34
+(p7)   mov r31=r35
+       ;;
+       break 0x110000
+       ;;
+(p7)   br.ret.sptk.few rp
+(p8)   br.cond.sptk.few rp
+       .endp pal_proc
+
+       .proc __hypercall
+       .globl __hypercall
+__hypercall:   
+       mov r2=r37
+       break 0x1000
+       br.ret.sptk.many b0
+       ;;
+       .endp __hypercall
+
+
+       .proc __hvmstub_hypercall
+       .globl __hvmstub_hypercall
+__hvmstub_hypercall:
+       mov r8=r32
+       mov r9=r33
+       mov r10=r34
+       mov r11=r35
+       mov r2=r36
+       break 0x1000
+       br.ret.sptk.many b0
+       ;;
+       .endp __hvmstub_hypercall
diff -r 092232fa1fbd extras/stubfw/string.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/string.c    Wed Nov 07 00:40:13 2007 +0100
@@ -0,0 +1,158 @@
+/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ ****************************************************************************
+ *
+ *        File: string.c
+ *      Author: Rolf Neugebauer (neugebar@xxxxxxxxxxxxx)
+ *     Changes: 
+ *              
+ *        Date: Aug 2003
+ * 
+ * Environment: Xen Minimal OS
+ * Description: Library function for string and memory manipulation
+ *              Origin unknown
+ *
+ ****************************************************************************
+ * $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $
+ ****************************************************************************
+ */
+
+#if !defined HAVE_LIBC
+
+#include <os.h>
+#include <types.h>
+#include <lib.h>
+
+int memcmp(const void * cs,const void * ct,size_t count)
+{
+       const unsigned char *su1, *su2;
+       signed char res = 0;
+
+       for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+               if ((res = *su1 - *su2) != 0)
+                       break;
+       return res;
+}
+
+void * memcpy(void * dest,const void *src,size_t count)
+{
+       char *tmp = (char *) dest;
+    const char *s = src;
+
+       while (count--)
+               *tmp++ = *s++;
+
+       return dest;
+}
+
+int strncmp(const char * cs,const char * ct,size_t count)
+{
+       register signed char __res = 0;
+
+       while (count) {
+               if ((__res = *cs - *ct++) != 0 || !*cs++)
+                       break;
+               count--;
+       }
+
+       return __res;
+}
+
+int strcmp(const char * cs,const char * ct)
+{
+        register signed char __res;
+
+        while (1) {
+                if ((__res = *cs - *ct++) != 0 || !*cs++)
+                        break;
+        }
+
+        return __res;
+}
+
+char * strcpy(char * dest,const char *src)
+{
+        char *tmp = dest;
+
+        while ((*dest++ = *src++) != '\0')
+                /* nothing */;
+        return tmp;
+}
+
+char * strncpy(char * dest,const char *src,size_t count)
+{
+        char *tmp = dest;
+
+        while (count-- && (*dest++ = *src++) != '\0')
+                /* nothing */;
+
+        return tmp;
+}
+
+void * memset(void * s,int c,size_t count)
+{
+        char *xs = (char *) s;
+
+        while (count--)
+                *xs++ = c;
+
+        return s;
+}
+
+size_t strnlen(const char * s, size_t count)
+{
+        const char *sc;
+
+        for (sc = s; count-- && *sc != '\0'; ++sc)
+                /* nothing */;
+        return sc - s;
+}
+
+
+char * strcat(char * dest, const char * src)
+{
+    char *tmp = dest;
+    
+    while (*dest)
+        dest++;
+    
+    while ((*dest++ = *src++) != '\0');
+    
+    return tmp;
+}
+
+size_t strlen(const char * s)
+{
+       const char *sc;
+
+       for (sc = s; *sc != '\0'; ++sc)
+               /* nothing */;
+       return sc - s;
+}
+
+char * strchr(const char * s, int c)
+{
+        for(; *s != (char) c; ++s)
+                if (*s == '\0')
+                        return NULL;
+        return (char *)s;
+}
+
+char * strstr(const char * s1,const char * s2)
+{
+        int l1, l2;
+
+        l2 = strlen(s2);
+        if (!l2)
+                return (char *) s1;
+        l1 = strlen(s1);
+        while (l1 >= l2) {
+                l1--;
+                if (!memcmp(s1,s2,l2))
+                        return (char *) s1;
+                s1++;
+        }
+        return NULL;
+}
+#endif
diff -r 092232fa1fbd extras/stubfw/stubfw.lds
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/stubfw.lds  Sat Nov 17 05:10:41 2007 +0100
@@ -0,0 +1,49 @@
+OUTPUT_FORMAT("elf64-ia64-little")
+OUTPUT_ARCH(ia64)
+ENTRY(_start)
+SECTIONS
+{
+  . = 0xff800000;
+  .text :
+  {
+   *(.start)
+   *(.text)
+   *(.got)
+   *(.got.plt)
+   *(.rodata)
+   *(.rodata.*)
+   *(.opd)
+  }
+  .sdata :
+  {
+   *(.sdata)
+   *(.scommon)
+  }
+  .data : 
+  {
+   *(.data)
+   . = ALIGN(16,.);
+   bss_start = .;
+   *(.bss)
+   *(COMMON)
+   . = ALIGN(16,.);
+   end = .;
+  }
+  .pad :
+  {
+   . = 0xffa00000 - ABSOLUTE(.) - 1;
+   BYTE(0);
+  }
+
+
+  /DISCARD/ :
+  {
+    *(.rela.plabel)
+    *(.rela.reloc)
+    *(.rela.*)
+    *(.IA_64.unwind*)
+    *(.IA64.unwind*)
+    *(.modname)
+    *(.moddeps)
+  }
+}
diff -r 092232fa1fbd extras/stubfw/stubfw.map
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/stubfw.map  Thu Nov 22 04:45:39 2007 +0100
@@ -0,0 +1,548 @@
+
+Allocating common symbols
+Common symbol       size              file
+
+pci_mem_base        0x8               ioemu/pci.o
+serial1             0x8               main.o
+piix4_dev           0x8               ioemu/piix_pci.o
+bs_table            0x28              ioemu.o
+ioemu_trace         0x4               main.o
+piix3_dev           0x8               ioemu/piix_pci.o
+
+Discarded input sections
+
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 main.o
+ .IA_64.unwind  0x0000000000000000        0x0 main.o
+ .rela.start    0x0000000000000000        0x0 main.o
+ .rela.sdata    0x0000000000000000        0x0 main.o
+ .rela.text     0x0000000000000000        0x0 main.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 hobs.o
+ .IA_64.unwind  0x0000000000000000        0x0 hobs.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 events.o
+ .IA_64.unwind  0x0000000000000000        0x0 events.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 ioemu/serial.o
+ .IA_64.unwind  0x0000000000000000        0x0 ioemu/serial.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 ioemu/mc146818rtc.o
+ .IA_64.unwind  0x0000000000000000        0x0 ioemu/mc146818rtc.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 ioemu/pci.o
+ .IA_64.unwind  0x0000000000000000        0x0 ioemu/pci.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 ioemu/irq.o
+ .IA_64.unwind  0x0000000000000000        0x0 ioemu/irq.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 ioemu/piix_pci.o
+ .IA_64.unwind  0x0000000000000000        0x0 ioemu/piix_pci.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 ioemu/ide.o
+ .IA_64.unwind  0x0000000000000000        0x0 ioemu/ide.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 ioemu/cdrom.o
+ .IA_64.unwind  0x0000000000000000        0x0 ioemu/cdrom.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 ioemu/block.o
+ .IA_64.unwind  0x0000000000000000        0x0 ioemu/block.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 ioemu/vl.o
+ .IA_64.unwind  0x0000000000000000        0x0 ioemu/vl.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 ioemu.o
+ .IA_64.unwind  0x0000000000000000        0x0 ioemu.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 console.o
+ .IA_64.unwind  0x0000000000000000        0x0 console.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 xenbus.o
+ .IA_64.unwind  0x0000000000000000        0x0 xenbus.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 xenbus_test.o
+ .IA_64.unwind  0x0000000000000000        0x0 xenbus_test.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 gnttab.o
+ .IA_64.unwind  0x0000000000000000        0x0 gnttab.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 vbd.o
+ .IA_64.unwind  0x0000000000000000        0x0 vbd.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 block-vbd.o
+ .IA_64.unwind  0x0000000000000000        0x0 block-vbd.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 printf.o
+ .IA_64.unwind  0x0000000000000000        0x0 printf.o
+ .IA_64.unwind_info
+                0x0000000000000000        0x0 string.o
+ .IA_64.unwind  0x0000000000000000        0x0 string.o
+
+Memory Configuration
+
+Name             Origin             Length             Attributes
+*default*        0x0000000000000000 0xffffffffffffffff
+
+Linker script and memory map
+
+                0x00000000ff800000                . = 0xff800000
+
+.text           0x00000000ff800000    0x1e9e0
+ *(.start)
+ .start         0x00000000ff800000      0x120 startup.o
+                0x00000000ff800000                _start
+ *(.text)
+ .text          0x00000000ff800120      0xbe0 main.o
+                0x00000000ff8008f0                cmain
+                0x00000000ff8002b0                dump_shared_info
+                0x00000000ff800420                ia64_callback
+                0x00000000ff800240                exit
+                0x00000000ff800120                setup_shared_info
+ .text          0x00000000ff800d00       0x70 startup.o
+                0x00000000ff800d40                __hvmstub_hypercall
+                0x00000000ff800d30                __hypercall
+ .text          0x00000000ff800d70      0x500 hobs.o
+                0x00000000ff801190                build_hob
+ .text          0x00000000ff801270      0xe90 events.o
+                0x00000000ff8018f0                bind_virq
+                0x00000000ff801a50                init_events
+                0x00000000ff8015b0                bind_evtchn
+                0x00000000ff801270                unbind_all_ports
+                0x00000000ff8017f0                unbind_evtchn
+                0x00000000ff801b70                evtchn_alloc_unbound
+                0x00000000ff802020                poll_evtchn
+                0x00000000ff801c50                evtchn_bind_interdomain
+                0x00000000ff801e00                do_hypervisor_callback
+ .text          0x00000000ff802100      0xa50 ioemu/serial.o
+                0x00000000ff802980                serial_event
+                0x00000000ff8027e0                serial_can_receive
+                0x00000000ff802930                serial_receive1
+                0x00000000ff8028e0                serial_can_receive1
+                0x00000000ff8029f0                serial_init
+                0x00000000ff802800                serial_receive_byte
+ .text          0x00000000ff802b50      0x450 ioemu/mc146818rtc.o
+                0x00000000ff802e80                rtc_init
+                0x00000000ff802e50                rtc_set_memory
+                0x00000000ff802cc0                cmos_ioport_read
+                0x00000000ff802b50                cmos_ioport_write
+ .text          0x00000000ff802fa0     0x1620 ioemu/pci.o
+                0x00000000ff803b80                pci_data_write
+                0x00000000ff803330                pci_register_io_region
+                0x00000000ff802fa0                pci_register_bus
+                0x00000000ff803720                pci_default_read_config
+                0x00000000ff8037f0                pci_default_write_config
+                0x00000000ff8030f0                pci_bus_num
+                0x00000000ff804570                pci_info
+                0x00000000ff804420                pci_for_each_device
+                0x00000000ff8033d0                pci_to_cpu_addr
+                0x00000000ff803100                pci_register_device
+                0x00000000ff803040                pci_register_secondary_bus
+                0x00000000ff803cc0                pci_data_read
+ .text          0x00000000ff8045c0      0x2c0 ioemu/irq.o
+                0x00000000ff804820                qemu_irq_invert
+                0x00000000ff8045c0                qemu_set_irq
+                0x00000000ff8046a0                qemu_allocate_irqs
+ .text          0x00000000ff804880      0xfa0 ioemu/piix_pci.o
+                0x00000000ff805620                piix3_init
+                0x00000000ff805510                piix_init
+                0x00000000ff805720                piix4_init
+                0x00000000ff804c90                i440fx_init
+ .text          0x00000000ff805820     0x9070 ioemu/ide.o
+                0x00000000ff80dff0                pci_cmd646_ide_init
+                0x00000000ff80e620                pci_piix4_ide_init
+                0x00000000ff80e3c0                pci_piix3_ide_init
+ .text          0x00000000ff80e890      0x770 ioemu/cdrom.o
+                0x00000000ff80ea10                cdrom_read_toc
+                0x00000000ff80ec80                cdrom_read_toc_raw
+ .text          0x00000000ff80f000     0x12c0 ioemu/block.o
+                0x00000000ff80f960                bdrv_get_type_hint
+                0x00000000ff80f8b0                bdrv_set_type_hint
+                0x00000000ff80f9e0                bdrv_set_change_cb
+                0x00000000ff80fad0                bdrv_aio_read
+                0x00000000ff80fff0                bdrv_media_changed
+                0x00000000ff80f1a0                bdrv_close
+                0x00000000ff80f000                bdrv_register
+                0x00000000ff810210                bdrv_set_locked
+                0x00000000ff80fa00                bdrv_flush
+                0x00000000ff80f080                bdrv_new
+                0x00000000ff80f880                bdrv_set_geometry_hint
+                0x00000000ff80f270                bdrv_read
+                0x00000000ff80f4b0                bdrv_write
+                0x00000000ff80f980                bdrv_get_translation_hint
+                0x00000000ff80f690                bdrv_getlength
+                0x00000000ff80f9c0                bdrv_is_read_only
+                0x00000000ff8100d0                bdrv_eject
+                0x00000000ff80ff20                bdrv_is_inserted
+                0x00000000ff80f7d0                bdrv_set_boot_sector
+                0x00000000ff80f8f0                bdrv_set_translation_hint
+                0x00000000ff80fd70                bdrv_aio_cancel
+                0x00000000ff80f760                bdrv_get_geometry
+                0x00000000ff80fc20                bdrv_aio_write
+                0x00000000ff80f9a0                bdrv_is_removable
+                0x00000000ff8101f0                bdrv_is_locked
+                0x00000000ff80f910                bdrv_get_geometry_hint
+ .text          0x00000000ff8102c0      0x520 ioemu/vl.o
+                0x00000000ff810350                qemu_chr_reset
+                0x00000000ff810360                qemu_chr_write
+                0x00000000ff8102c0                qemu_chr_event
+                0x00000000ff8103d0                qemu_chr_ioctl
+                0x00000000ff8105b0                qemu_chr_printf
+                0x00000000ff810530                qemu_chr_read
+                0x00000000ff810480                qemu_chr_can_read
+                0x00000000ff810680                qemu_chr_send_event
+                0x00000000ff810710                qemu_chr_add_handlers
+ .text          0x00000000ff8107e0     0x1720 ioemu.o
+                0x00000000ff810ec0                default_ioport_readb
+                0x00000000ff8107e0                pstrcpy
+                0x00000000ff811c10                cpu_physical_memory_rw
+                0x00000000ff811890                cpu_outl
+                0x00000000ff811510                register_ioport_write
+                0x00000000ff810fe0                default_ioport_readw
+                0x00000000ff8116f0                cpu_outb
+                0x00000000ff811ae0                cpu_inl
+                0x00000000ff8108d0                hw_error
+                0x00000000ff811170                default_ioport_writel
+                0x00000000ff811060                default_ioport_writew
+                0x00000000ff8117c0                cpu_outw
+                0x00000000ff811200                init_ioports
+                0x00000000ff810f50                default_ioport_writeb
+                0x00000000ff8110e0                default_ioport_readl
+                0x00000000ff810860                qemu_mallocz
+                0x00000000ff811a20                cpu_inw
+                0x00000000ff811960                cpu_inb
+                0x00000000ff811eb0                init_iosapic
+                0x00000000ff811330                register_ioport_read
+ .text          0x00000000ff811f00     0x14e0 console.o
+                0x00000000ff813350                term_printf
+                0x00000000ff8132b0                printf
+                0x00000000ff812fd0                qemu_chr_open_xc
+                0x00000000ff8120e0                xencons_wait_send
+                0x00000000ff812010                xencons_ring_send
+                0x00000000ff8130a0                vprintf
+                0x00000000ff811f00                xencons_ring_send_no_notify
+                0x00000000ff813220                printk
+                0x00000000ff812190                xencons_input
+                0x00000000ff8123d0                init_console
+ .text          0x00000000ff8133e0     0x1c30 xenbus.o
+                0x00000000ff8142c0                xenbus_debug_msg
+                0x00000000ff8145c0                xenbus_read
+                0x00000000ff814960                xenbus_rm
+                0x00000000ff8133e0                xenbus_allocate_req
+                0x00000000ff813a70                init_xenbus
+                0x00000000ff814de0                xenbus_transaction_end
+                0x00000000ff813b60                xenbus_wait_for_value
+                0x00000000ff8143c0                xenbus_ls
+                0x00000000ff814820                xenbus_watch_path
+                0x00000000ff814b60                xenbus_set_perms
+                0x00000000ff8146d0                xenbus_write
+                0x00000000ff814cf0                xenbus_transaction_start
+                0x00000000ff814f30                xenbus_read_integer
+                0x00000000ff814a50                xenbus_get_perms
+ .text          0x00000000ff815010      0x6f0 xenbus_test.o
+                0x00000000ff815440                test_xenbus
+ .text          0x00000000ff815700      0x950 gnttab.o
+                0x00000000ff815a30                gnttab_end_transfer
+                0x00000000ff815d60                gnttabop_error
+                0x00000000ff815780                gnttab_grant_access
+                0x00000000ff815db0                init_gnttab
+                0x00000000ff815c30                alloc_pages
+                0x00000000ff815930                gnttab_end_access
+                0x00000000ff815ce0                gnttab_alloc_and_grant
+                0x00000000ff815870                gnttab_grant_transfer
+ .text          0x00000000ff816050     0x17f0 vbd.o
+                0x00000000ff816a10                init_vbd
+                0x00000000ff816050                xenbus_printf
+                0x00000000ff8175e0                vbd_test
+                0x00000000ff816130                xenbus_scanf
+                0x00000000ff8170b0                vbd_request
+ .text          0x00000000ff817840      0x610 block-vbd.o
+                0x00000000ff817e00                bdrv_init
+                0x00000000ff817c60                bdrv_open_vbd
+ *fill*         0x00000000ff817e50       0x10 00
+ .text          0x00000000ff817e60      0x420 event-asm.o
+                0x00000000ff817e60                callback_entry
+ .text          0x00000000ff818280     0x2a30 printf.o
+                0x00000000ff819af0                vsprintf
+                0x00000000ff818730                simple_strtoll
+                0x00000000ff819a60                snprintf
+                0x00000000ff818450                simple_strtol
+                0x00000000ff819be0                vsscanf
+                0x00000000ff818f10                vsnprintf
+                0x00000000ff81ac20                sscanf
+                0x00000000ff819b50                sprintf
+                0x00000000ff818280                simple_strtoul
+                0x00000000ff818500                simple_strtoull
+ .text          0x00000000ff81acb0      0x500 string.o
+                0x00000000ff81ae20                strcpy
+                0x00000000ff81ad10                memcpy
+                0x00000000ff81aee0                strnlen
+                0x00000000ff81af70                strcat
+                0x00000000ff81b0a0                strstr
+                0x00000000ff81ad50                strncmp
+                0x00000000ff81ae50                strncpy
+                0x00000000ff81acb0                memcmp
+                0x00000000ff81aea0                memset
+                0x00000000ff81add0                strcmp
+                0x00000000ff81afd0                strlen
+                0x00000000ff81b020                strchr
+ *fill*         0x00000000ff81b1b0       0x10 00
+ .text          0x00000000ff81b1c0      0x120 __umoddi3.o
+                0x00000000ff81b1c0                __umoddi3
+ .text          0x00000000ff81b2e0      0x110 __divdi3.o
+                0x00000000ff81b2e0                __divdi3
+ *fill*         0x00000000ff81b3f0       0x10 00
+ .text          0x00000000ff81b400      0x110 __udivdi3.o
+                0x00000000ff81b400                __udivdi3
+ *fill*         0x00000000ff81b510       0x10 00
+ .text          0x00000000ff81b520       0xe0 __udivsi3.o
+                0x00000000ff81b520                __udivsi3
+ .text          0x00000000ff81b600       0xf0 __umodsi3.o
+                0x00000000ff81b600                __umodsi3
+ *(.got)
+ .got           0x00000000ff81b6f0      0x220 main.o
+ *(.got.plt)
+ .got.plt       0x00000000ff81b910        0x0 main.o
+                0x00000000ff81b910                _GLOBAL_OFFSET_TABLE_
+ *(.rodata)
+ .rodata        0x00000000ff81b910       0x78 main.o
+ .rodata        0x00000000ff81b988       0x1a events.o
+ *fill*         0x00000000ff81b9a2        0x6 00
+ .rodata        0x00000000ff81b9a8       0x80 ioemu/serial.o
+ .rodata        0x00000000ff81ba28       0xd8 ioemu/mc146818rtc.o
+ .rodata        0x00000000ff81bb00      0x3e0 ioemu/pci.o
+ .rodata        0x00000000ff81bee0      0x850 ioemu/ide.o
+ .rodata        0x00000000ff81c730       0x1a ioemu.o
+ *fill*         0x00000000ff81c74a        0x6 00
+ .rodata        0x00000000ff81c750      0x238 console.o
+ .rodata        0x00000000ff81c988       0x1a xenbus.o
+ *fill*         0x00000000ff81c9a2        0x6 00
+ .rodata        0x00000000ff81c9a8       0x1a xenbus_test.o
+ *fill*         0x00000000ff81c9c2        0x6 00
+ .rodata        0x00000000ff81c9c8       0xa8 gnttab.o
+ .rodata        0x00000000ff81ca70       0x1a vbd.o
+ *fill*         0x00000000ff81ca8a        0x6 00
+ .rodata        0x00000000ff81ca90      0x780 printf.o
+ .rodata        0x00000000ff81d210       0x1a string.o
+ *(.rodata.*)
+ *fill*         0x00000000ff81d22a        0x6 00
+ .rodata.str1.8
+                0x00000000ff81d230      0x194 main.o
+ *fill*         0x00000000ff81d3c4        0x4 00
+ .rodata.str1.8
+                0x00000000ff81d3c8       0xcc events.o
+ *fill*         0x00000000ff81d494        0x4 00
+ .rodata.str1.8
+                0x00000000ff81d498      0x34b ioemu/pci.o
+ *fill*         0x00000000ff81d7e3        0x5 00
+ .rodata.str1.8
+                0x00000000ff81d7e8       0x22 ioemu/irq.o
+ *fill*         0x00000000ff81d80a        0x6 00
+ .rodata.str1.8
+                0x00000000ff81d810       0x36 ioemu/piix_pci.o
+ *fill*         0x00000000ff81d846        0x2 00
+ .rodata.str1.8
+                0x00000000ff81d848       0x72 ioemu/ide.o
+ *fill*         0x00000000ff81d8ba        0x6 00
+ .rodata.str1.8
+                0x00000000ff81d8c0       0x21 ioemu/block.o
+ *fill*         0x00000000ff81d8e1        0x7 00
+ .rodata.str1.8
+                0x00000000ff81d8e8      0x1cb ioemu.o
+                                        0x1d3 (size before relaxing)
+ *fill*         0x00000000ff81dab3        0x5 00
+ .rodata.str1.8
+                0x00000000ff81dab8      0x18c console.o
+                                        0x192 (size before relaxing)
+ *fill*         0x00000000ff81dc44        0x4 00
+ .rodata.str1.8
+                0x00000000ff81dc48      0x173 xenbus.o
+                                        0x193 (size before relaxing)
+ *fill*         0x00000000ff81ddbb        0x5 00
+ .rodata.str1.8
+                0x00000000ff81ddc0      0x1e3 xenbus_test.o
+                                        0x25b (size before relaxing)
+ *fill*         0x00000000ff81dfa3        0x5 00
+ .rodata.str1.8
+                0x00000000ff81dfa8      0x1cc gnttab.o
+ *fill*         0x00000000ff81e174        0x4 00
+ .rodata.str1.8
+                0x00000000ff81e178      0x2be vbd.o
+                                        0x2fe (size before relaxing)
+ *fill*         0x00000000ff81e436        0x2 00
+ .rodata.str1.8
+                0x00000000ff81e438       0xc7 block-vbd.o
+ *fill*         0x00000000ff81e4ff        0x1 00
+ .rodata.str1.8
+                0x00000000ff81e500       0x58 printf.o
+                                         0x57 (size before relaxing)
+ *(.opd)
+ *fill*         0x00000000ff81e558        0x8 00
+ .opd           0x00000000ff81e560      0x480 main.o
+
+.sdata          0x00000000ff81e9e0       0x58
+ *(.sdata)
+ .sdata         0x00000000ff81e9e0        0x8 main.o
+                0x00000000ff81e9e0                shared_info
+ .sdata         0x00000000ff81e9e8        0x4 ioemu/ide.o
+ *fill*         0x00000000ff81e9ec        0x4 00
+ .sdata         0x00000000ff81e9f0        0x8 ioemu.o
+ .sdata         0x00000000ff81e9f8        0x4 console.o
+ *fill*         0x00000000ff81e9fc        0x4 00
+ .sdata         0x00000000ff81ea00        0x8 gnttab.o
+ .sdata         0x00000000ff81ea08        0x8 vbd.o
+ *(.scommon)
+ .scommon       0x00000000ff81ea10        0xc main.o
+                0x00000000ff81ea10                serial1
+                0x00000000ff81ea18                ioemu_trace
+ *fill*         0x00000000ff81ea1c        0x4 00
+ .scommon       0x00000000ff81ea20        0x8 ioemu/pci.o
+                0x00000000ff81ea20                pci_mem_base
+ .scommon       0x00000000ff81ea28       0x10 ioemu/piix_pci.o
+                0x00000000ff81ea28                piix4_dev
+                0x00000000ff81ea30                piix3_dev
+
+.sbss           0x00000000ff81ea38       0x80
+ .sbss          0x00000000ff81ea38       0x28 main.o
+ .sbss          0x00000000ff81ea60       0x10 ioemu/pci.o
+ .sbss          0x00000000ff81ea70        0x8 ioemu/block.o
+ .sbss          0x00000000ff81ea78        0x8 ioemu.o
+ .sbss          0x00000000ff81ea80       0x14 console.o
+ *fill*         0x00000000ff81ea94        0x4 00
+ .sbss          0x00000000ff81ea98       0x10 xenbus.o
+ .sbss          0x00000000ff81eaa8        0x8 gnttab.o
+ .sbss          0x00000000ff81eab0        0x8 vbd.o
+
+.data           0x00000000ff81eab8     0xb6f0
+ *(.data)
+ .data          0x00000000ff81eab8        0x0 main.o
+ .data          0x00000000ff81eab8        0x0 startup.o
+ .data          0x00000000ff81eab8        0x0 hobs.o
+ .data          0x00000000ff81eab8        0x0 events.o
+ .data          0x00000000ff81eab8        0x0 ioemu/serial.o
+ .data          0x00000000ff81eab8        0x0 ioemu/mc146818rtc.o
+ .data          0x00000000ff81eab8      0x240 ioemu/pci.o
+ .data          0x00000000ff81ecf8        0x0 ioemu/irq.o
+ .data          0x00000000ff81ecf8        0x0 ioemu/piix_pci.o
+ .data          0x00000000ff81ecf8        0x0 ioemu/ide.o
+ .data          0x00000000ff81ecf8        0x0 ioemu/cdrom.o
+ .data          0x00000000ff81ecf8        0x0 ioemu/block.o
+ .data          0x00000000ff81ecf8        0x0 ioemu/vl.o
+ .data          0x00000000ff81ecf8        0x0 ioemu.o
+ .data          0x00000000ff81ecf8       0x40 console.o
+ .data          0x00000000ff81ed38       0xe0 xenbus.o
+ .data          0x00000000ff81ee18       0xe0 xenbus_test.o
+ .data          0x00000000ff81eef8        0x0 gnttab.o
+ .data          0x00000000ff81eef8        0x0 vbd.o
+ .data          0x00000000ff81eef8      0x108 block-vbd.o
+                0x00000000ff81eef8                bdrv_vbd
+ .data          0x00000000ff81f000        0x0 event-asm.o
+ .data          0x00000000ff81f000      0x100 printf.o
+                0x00000000ff81f000                _ctype
+ .data          0x00000000ff81f100        0x0 string.o
+ .data          0x00000000ff81f100        0x0 __umoddi3.o
+ .data          0x00000000ff81f100        0x0 __divdi3.o
+ .data          0x00000000ff81f100        0x0 __udivdi3.o
+ .data          0x00000000ff81f100        0x0 __udivsi3.o
+ .data          0x00000000ff81f100        0x0 __umodsi3.o
+                0x00000000ff81f100                . = (0x10 ALIGN .)
+                0x00000000ff81f100                bss_start = .
+ *(.bss)
+ .bss           0x00000000ff81f100        0x0 main.o
+ .bss           0x00000000ff81f100        0x0 startup.o
+ .bss           0x00000000ff81f100        0x0 hobs.o
+ .bss           0x00000000ff81f100     0x6080 events.o
+ .bss           0x00000000ff825180        0x0 ioemu/serial.o
+ .bss           0x00000000ff825180        0x0 ioemu/mc146818rtc.o
+ .bss           0x00000000ff825180        0x0 ioemu/pci.o
+ .bss           0x00000000ff825180        0x0 ioemu/irq.o
+ .bss           0x00000000ff825180       0x10 ioemu/piix_pci.o
+ .bss           0x00000000ff825190        0x0 ioemu/ide.o
+ .bss           0x00000000ff825190        0x0 ioemu/cdrom.o
+ .bss           0x00000000ff825190        0x0 ioemu/block.o
+ .bss           0x00000000ff825190        0x0 ioemu/vl.o
+ .bss           0x00000000ff825190     0x1c90 ioemu.o
+ .bss           0x00000000ff826e20      0x4e0 console.o
+ .bss           0x00000000ff827300      0x500 xenbus.o
+ .bss           0x00000000ff827800        0x0 xenbus_test.o
+ .bss           0x00000000ff827800     0x2000 gnttab.o
+ .bss           0x00000000ff829800      0x980 vbd.o
+ .bss           0x00000000ff82a180        0x0 block-vbd.o
+ .bss           0x00000000ff82a180        0x0 event-asm.o
+ .bss           0x00000000ff82a180        0x0 printf.o
+ .bss           0x00000000ff82a180        0x0 string.o
+ .bss           0x00000000ff82a180        0x0 __umoddi3.o
+ .bss           0x00000000ff82a180        0x0 __divdi3.o
+ .bss           0x00000000ff82a180        0x0 __udivdi3.o
+ .bss           0x00000000ff82a180        0x0 __udivsi3.o
+ .bss           0x00000000ff82a180        0x0 __umodsi3.o
+ *(COMMON)
+ COMMON         0x00000000ff82a180       0x28 ioemu.o
+                0x00000000ff82a180                bs_table
+                0x00000000ff82a1a8                . = (0x10 ALIGN .)
+                0x00000000ff82a1a8                end = .
+
+.pad            0x00000000ff82a1a8   0x1d5e58
+                0x00000000ff9fffff                . = ((0xffa00000 - <code 
342> (.)) - 0x1)
+ *fill*         0x00000000ff82a1a8   0x1d5e57 00
+                0x00000000ff9fffff        0x1 BYTE 0x0
+
+/DISCARD/
+ *(.rela.plabel)
+ *(.rela.reloc)
+ *(.rela.*)
+ *(.IA_64.unwind*)
+ *(.IA64.unwind*)
+ *(.modname)
+ *(.moddeps)
+LOAD main.o
+LOAD startup.o
+LOAD hobs.o
+LOAD events.o
+LOAD ioemu/serial.o
+LOAD ioemu/mc146818rtc.o
+LOAD ioemu/pci.o
+LOAD ioemu/irq.o
+LOAD ioemu/piix_pci.o
+LOAD ioemu/ide.o
+LOAD ioemu/cdrom.o
+LOAD ioemu/block.o
+LOAD ioemu/vl.o
+LOAD ioemu.o
+LOAD console.o
+LOAD xenbus.o
+LOAD xenbus_test.o
+LOAD gnttab.o
+LOAD vbd.o
+LOAD block-vbd.o
+LOAD event-asm.o
+LOAD printf.o
+LOAD string.o
+LOAD __umoddi3.o
+LOAD __divdi3.o
+LOAD __udivdi3.o
+LOAD __udivsi3.o
+LOAD __umodsi3.o
+OUTPUT(stubfw.elf elf64-ia64-little)
+
+.comment        0x0000000000000000      0x31e
+ .comment       0x0000000000000000       0x26 main.o
+ .comment       0x0000000000000026       0x26 hobs.o
+ .comment       0x000000000000004c       0x26 events.o
+ .comment       0x0000000000000072       0x26 ioemu/serial.o
+ .comment       0x0000000000000098       0x26 ioemu/mc146818rtc.o
+ .comment       0x00000000000000be       0x26 ioemu/pci.o
+ .comment       0x00000000000000e4       0x26 ioemu/irq.o
+ .comment       0x000000000000010a       0x26 ioemu/piix_pci.o
+ .comment       0x0000000000000130       0x26 ioemu/ide.o
+ .comment       0x0000000000000156       0x26 ioemu/cdrom.o
+ .comment       0x000000000000017c       0x26 ioemu/block.o
+ .comment       0x00000000000001a2       0x26 ioemu/vl.o
+ .comment       0x00000000000001c8       0x26 ioemu.o
+ .comment       0x00000000000001ee       0x26 console.o
+ .comment       0x0000000000000214       0x26 xenbus.o
+ .comment       0x000000000000023a       0x26 xenbus_test.o
+ .comment       0x0000000000000260       0x26 gnttab.o
+ .comment       0x0000000000000286       0x26 vbd.o
+ .comment       0x00000000000002ac       0x26 block-vbd.o
+ .comment       0x00000000000002d2       0x26 printf.o
+ .comment       0x00000000000002f8       0x26 string.o
diff -r 092232fa1fbd extras/stubfw/stubfw.mk
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/stubfw.mk   Fri Nov 16 03:48:09 2007 +0100
@@ -0,0 +1,59 @@
+#
+# The file contains the common make rules for building mini-os.
+#
+
+#debug = y
+
+# Define some default flags.
+# NB. '-Wcast-qual' is nasty, so I omitted it.
+DEF_CFLAGS := -fno-builtin -Wall -Werror -Wredundant-decls -Wno-format
+DEF_CFLAGS += -Wstrict-prototypes -Wnested-externs -Wpointer-arith #-Winline
+DEF_CFLAGS += -D__XEN_INTERFACE_VERSION__=$(XEN_INTERFACE_VERSION)
+#DEF_CFLAGS += -nostdinc
+
+DEF_ASFLAGS = -D__ASSEMBLY__
+DEF_LDFLAGS =
+
+ifeq ($(debug),y)
+DEF_CFLAGS += -g
+else
+DEF_CFLAGS += -O
+endif
+
+# Build the CFLAGS and ASFLAGS for compiling and assembling.
+# DEF_... flags are the common mini-os flags,
+# ARCH_... flags may be defined in arch/$(TARGET_ARCH_FAM/rules.mk
+CFLAGS := $(DEF_CFLAGS) $(ARCH_CFLAGS)
+ASFLAGS := $(DEF_ASFLAGS) $(ARCH_ASFLAGS)
+LDFLAGS := $(DEF_LDFLAGS) $(ARCH_LDFLAGS)
+
+# The path pointing to the architecture specific header files.
+ARCH_INC := $(STUBFW_ROOT)/include/$(TARGET_ARCH_FAM)
+
+# Special build dependencies.
+# Rebuild all after touching this/these file(s)
+EXTRA_DEPS = $(STUBFW_ROOT)/stubfw.mk 
+
+# Find all header files for checking dependencies.
+HDRS := $(wildcard $(STUBFW_ROOT)/include/*.h)
+HDRS += $(wildcard $(STUBFW_ROOT)/*.h)
+HDRS += $(wildcard $(STUBFW_ROOT)/include/xen/*.h)
+HDRS += $(wildcard $(ARCH_INC)/*.h)
+# For special wanted header directories.
+extra_heads := $(foreach dir,$(EXTRA_INC),$(wildcard $(dir)/*.h))
+HDRS += $(extra_heads)
+
+# Add the special header directories to the include paths.
+#extra_incl := $(foreach dir,$(EXTRA_INC),-I$(STUBFW_ROOT)/include/$(dir))
+override CPPFLAGS := -I$(STUBFW_ROOT)/include $(CPPFLAGS) -I$(ARCH_INC) 
$(extra_incl)
+
+
+%.o: %.c
+       $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
+
+%.o: %.S
+       $(CC) $(ASFLAGS) $(CPPFLAGS) -c $< -o $@
+
+
+
+
diff -r 092232fa1fbd extras/stubfw/vbd.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/vbd.c       Wed Nov 21 03:26:48 2007 +0100
@@ -0,0 +1,409 @@
+#include "os.h"
+#include "xenbus.h"
+#include "events.h"
+#include "errno.h"
+#include <xen/io/blkif.h>
+#include <xen/io/protocols.h>
+#include <xen/io/xenbus.h>
+#include "gnttab.h"
+#include "vbd.h"
+#include "ioemu/vl.h"
+
+const char*
+xenbus_printf(struct xenbus_req *req,
+             xenbus_transaction_t xbt,
+             const char* node, const char* path,
+             const char* fmt, ...)
+{
+    va_list args;
+    char fullpath[256];
+    char val[256];
+
+    sprintf(fullpath,"%s/%s",node,path);
+    va_start(args, fmt);
+    vsprintf(val,fmt,args);
+    va_end(args);
+    return xenbus_write(req, xbt, fullpath, val);
+}
+
+const char*
+xenbus_scanf(struct xenbus_req *req,
+            xenbus_transaction_t xbt,
+             const char* node, const char* path,
+             const char* fmt, ...)
+{
+    va_list args;
+    const char *msg;
+    char *res;
+    char fullpath[256];
+
+    sprintf(fullpath,"%s/%s",node,path);
+    msg = xenbus_read(req, xbt, fullpath, &res);
+    if (msg)
+      return msg;
+    
+    va_start(args, fmt);
+    vsscanf(res,fmt,args);
+    va_end(args);
+
+    return NULL;
+}
+
+
+#define MAX_VBD 4
+
+static struct vbd_info vbds[MAX_VBD];
+static struct xenbus_req *vbd_req;
+static char vbd_req_buf[1024];
+
+static void vbd_handler (evtchn_port_t port, void *data)
+{
+  //printk ("vbd_handler\n");
+}
+
+static int setup_blkring(struct vbd_info *info)
+{
+       blkif_sring_t *sring;
+       //int err;
+
+       info->ring_ref = GRANT_INVALID_REF;
+       info->otherend_id = 0; //FIXME
+
+       sring = (blkif_sring_t *)alloc_pages (1);
+       if (!sring) {
+         //xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
+               return -ENOMEM;
+       }
+       SHARED_RING_INIT(sring);
+       FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE);
+
+       info->ring_ref = gnttab_grant_access (info->otherend_id,
+                                             addr_to_mfn(info->ring.sring),
+                                             0);
+       if (info->ring_ref == GRANT_INVALID_REF)
+         goto fail;
+
+       if (evtchn_alloc_unbound (info->otherend_id, vbd_handler, info,
+                                 &info->evtchn) != 0)
+         goto fail;
+       return 0;
+ fail:
+       // FIXME: free blk
+       return -1;
+}
+
+/* Common code used when first setting up, and when resuming. */
+static int
+talk_to_backend(struct vbd_info *info)
+{
+       xenbus_transaction_t xbt;
+       const char *msg;
+       int retry;
+
+again:
+       msg = xenbus_transaction_start(vbd_req, &xbt);
+       if (msg) {
+         //xenbus_dev_fatal(dev, err, "starting transaction");
+               goto destroy_blkring;
+       }
+
+       msg = xenbus_printf(vbd_req, xbt, info->node_name,
+                           "ring-ref", "%u", info->ring_ref);
+       if (msg) {
+         //message = "writing ring-ref";
+               goto abort_transaction;
+       }
+       msg = xenbus_printf(vbd_req, xbt, info->node_name,
+                           "event-channel", "%u", info->evtchn);
+       if (msg) {
+         //message = "writing event-channel";
+               goto abort_transaction;
+       }
+       msg = xenbus_printf(vbd_req, xbt, info->node_name, "protocol", "%s",
+                           XEN_IO_PROTO_ABI_NATIVE);
+       if (msg) {
+         //message = "writing protocol";
+               goto abort_transaction;
+       }
+
+       msg = xenbus_transaction_end(vbd_req, xbt, 0, &retry);
+       if (msg) {
+         if (retry)
+           goto again;
+         //xenbus_dev_fatal(dev, err, "completing transaction");
+         goto destroy_blkring;
+       }
+
+       msg = xenbus_printf(vbd_req, XBT_NIL, info->node_name,
+                           "state", "%u", XenbusStateConnected);
+       if (msg)
+         printk ("vbd: cannot switch state: %s\n", msg);
+       return 0;
+
+ abort_transaction:
+       printk ("vbd: abort transaction: %s\n", msg);
+       xenbus_transaction_end(vbd_req, xbt, 1, &retry);
+       //if (message)
+       //xenbus_dev_fatal(dev, err, "%s", message);
+ destroy_blkring:
+       //blkif_free(info, 0);
+       // out:
+       return -1;
+}
+
+static int
+find_backend (struct vbd_info *info)
+{
+      const char *msg;
+      char *res;
+      snprintf (info->backend, sizeof (info->backend),
+               "%s/%s", info->node_name, "backend");
+      msg = xenbus_read(vbd_req, XBT_NIL, info->backend,
+                       &res);
+      if (msg)
+       return -1;
+      pstrcpy (info->backend, sizeof (info->backend), res);
+      return 0;
+}
+
+static int
+wait_backend (struct vbd_info *info)
+{
+    char path[256];
+    sprintf(path,"%s/state",info->backend);
+
+    xenbus_watch_path(vbd_req, XBT_NIL, path);
+
+    if (xenbus_wait_for_value(vbd_req, path, "4") == NULL)
+      return 0;
+    else
+      return -1;
+}
+
+static int
+vbd_connect (struct vbd_info *info)
+{
+  const char *msg;
+  unsigned int binfo;
+
+  msg = xenbus_scanf (vbd_req, XBT_NIL, info->backend, "sectors", "%Lu",
+                     &info->sectors);
+  if (msg)
+    return -1;
+  msg = xenbus_scanf (vbd_req, XBT_NIL, info->backend, "info", "%u",
+                     &binfo);
+  if (msg)
+    return -1;
+  msg = xenbus_scanf (vbd_req, XBT_NIL, info->backend, "sector-size", "%lu",
+                     &info->sector_size);
+  if (msg)
+    return -1;
+  printk ("%s: %lu sectors (%lu bytes), info=%u\n",
+         info->node_name, info->sectors, info->sector_size, binfo);
+  info->is_ro = (binfo & VDISK_READONLY) ? 1 : 0;
+  return 0;
+}
+
+void init_vbd(void)
+{
+    char *dirs[MAX_VBD];
+    int nbr_entries;
+    const char* msg;
+    int i;
+
+    vbd_req = xenbus_allocate_req (vbd_req_buf, sizeof (vbd_req_buf));
+    nbr_entries = ARRAY_SIZE(dirs);
+    msg = xenbus_ls (vbd_req, XBT_NIL, "device/vbd", dirs, &nbr_entries);
+    if (msg != NULL) {
+      printk ("can't list vbd: %s\n", msg);
+      return;
+    }
+    if (nbr_entries == 0) {
+      printk ("no vbd devices\n");
+      return;
+    }
+    if (nbr_entries > MAX_VBD)
+      nbr_entries = MAX_VBD;
+    printk ("VBD:");
+    for (i = 0; i < nbr_entries; i++)
+      printk (" %s", dirs[i]);
+    printk ("\n");
+
+    for (i = 0; i < nbr_entries; i++) {
+      snprintf (vbds[i].node_name, sizeof (vbds[i].node_name),
+               "device/vbd/%s", dirs[i]);
+      vbds[i].handle = simple_strtoul(dirs[i], NULL, 0);
+    }
+    for (i = 0; i < nbr_entries; i++) {
+      if (find_backend (&vbds[i]) != 0) {
+       printk ("vbd: failed to find backend for %s\n", vbds[i].node_name);
+       continue;
+      }
+      if (setup_blkring (&vbds[i]) != 0) {
+       printk ("vbd: failed to setup %s\n", vbds[i].node_name);
+       continue;
+      }
+      if (talk_to_backend (&vbds[i]) != 0) {
+       printk ("vbd: failed to talk to backend %s\n", vbds[i].node_name);
+       continue;
+      }
+      if (wait_backend (&vbds[i]) != 0) {
+       printk ("vbd: backend is not ready %s\n", vbds[i].node_name);
+       continue;
+      }
+      if (vbd_connect (&vbds[i]) != 0) {
+       printk ("vbd: cannot get backend info: %s\n", vbds[i].node_name);
+       continue;
+      }
+      vbds[i].state = 1;
+
+      char buf[64];
+      snprintf(buf, sizeof(buf), "hd%c", i + 'a');
+      bs_table[i] = bdrv_new(buf);
+      if (bdrv_open_vbd(bs_table[i], &vbds[i], 0) < 0) {
+       printk("qemu: could not open hard disk image '%s'\n", buf);
+       exit();
+      }
+    }
+}
+
+int
+vbd_request(struct vbd_info *info,
+           int op_write, unsigned long sector, char *buf)
+{
+       blkif_request_t *ring_req;
+       static unsigned long id = 0x12;
+       grant_ref_t ref;
+       unsigned long buf_off;
+
+       //printf ("vbd_request: sec=%d buf=%p\n", sector, buf);
+       
+#if 0
+       if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
+               return -1;
+#endif
+
+       ref = gnttab_grant_access (info->otherend_id, addr_to_mfn (buf),
+                                  op_write);
+
+       /* Fill out a communications ring structure. */
+       ring_req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt);
+
+       ring_req->id = ++id;
+       ring_req->sector_number = (blkif_sector_t)sector;
+       ring_req->handle = info->handle;
+
+       ring_req->operation = op_write ? BLKIF_OP_WRITE : BLKIF_OP_READ;
+
+       ring_req->nr_segments = 0;
+       buf_off = ((unsigned long)buf & (PAGE_SIZE - 1)) >> 9;
+       ring_req->seg[ring_req->nr_segments] =
+         (struct blkif_request_segment) {
+           .gref       = ref,
+           .first_sect = buf_off,
+           .last_sect  = buf_off};
+
+       ring_req->nr_segments++;
+       info->ring.req_prod_pvt++;
+
+       int notify;
+
+       RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->ring, notify);
+
+       notify_remote_via_evtchn(info->evtchn);
+
+       /* Keep a private copy so we can reissue requests when recovering. */
+       //info->shadow[id].req = *ring_req;
+
+       //gnttab_free_grant_references(gref_head);
+
+       /* Wait for reply.  */
+       RING_IDX i, rp;
+       do {
+         poll_evtchn (info->evtchn);
+
+         rp = info->ring.sring->rsp_prod;
+         rmb(); /* Ensure we see queued responses up to 'rp'. */
+         //printk ("vbd wait: %u %u\n", rp, info->ring.rsp_cons);
+       } while (rp == info->ring.rsp_cons);
+
+
+       rp = info->ring.sring->rsp_prod;
+       rmb(); /* Ensure we see queued responses up to 'rp'. */
+
+       for (i = info->ring.rsp_cons; i != rp; i++) {
+               blkif_response_t *bret;
+
+               bret = RING_GET_RESPONSE(&info->ring, i);
+               if (bret->id != id) {
+                 printk ("Bad id (%lx expect %lx)\n", bret->id, id);
+                 exit();
+               }
+               //printk ("ret: op=%u status=%u, id=%lu\n",
+               //bret->operation, bret->status, bret->id);
+               //req  = (struct request *)info->shadow[id].request;
+
+               //blkif_completion(&info->shadow[id]);
+
+               //ADD_ID_TO_FREELIST(info, id);
+
+               //uptodate = (bret->status == BLKIF_RSP_OKAY);
+               switch (bret->operation) {
+               case BLKIF_OP_READ:
+               case BLKIF_OP_WRITE:
+                       if (unlikely(bret->status != BLKIF_RSP_OKAY))
+                         printk("Bad return from blkdev data "
+                                "request: %x\n", bret->status);
+                       break;
+               default:
+                       BUG();
+               }
+       }
+
+       gnttab_end_access (ref);
+
+       info->ring.rsp_cons = i;
+
+       if (i != info->ring.req_prod_pvt) {
+               int more_to_do;
+               RING_FINAL_CHECK_FOR_RESPONSES(&info->ring, more_to_do);
+#if 0
+               if (more_to_do)
+                       goto again;
+#endif
+       } else
+               info->ring.sring->rsp_event = i + 1;
+
+       return 0;
+}
+
+void
+vbd_test (void)
+{
+  int i;
+  char *buf = (char *)PAGE_SIZE; // alloc_free_page ();
+  int j;
+  int sect;
+
+  for (i = 0; i < MAX_VBD; i++) {
+    if (vbds[i].state != 1)
+      continue;
+    for (sect = 2; sect < 4; sect++) {
+      printk ("Sector %d of %s:\n", sect, vbds[i].node_name);
+
+      for (j = 0; j < 64; j++)
+       buf[j] = j ^ 0x51;
+
+      vbd_request (&vbds[i], 0, sect, buf);
+
+      for (j = 0; j < 64; j += 16) {
+       int k;
+       printk ("%04x:", j);
+       for (k = 0; k < 16; k++)
+         printk (" %02x", (unsigned char)buf[j + k]);
+       printk ("\n");
+      }
+    }
+  }
+}
+
diff -r 092232fa1fbd extras/stubfw/vbd.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/vbd.h       Sat Nov 17 02:58:51 2007 +0100
@@ -0,0 +1,25 @@
+#ifndef __VBD_H__
+#define __VBD_H__
+#include <xen/xen.h>
+#include <xen/event_channel.h>
+#include <xen/io/blkif.h>
+
+struct vbd_info {
+  unsigned int state;
+  char node_name[24];
+  char backend[256];
+  unsigned int handle;
+  int ring_ref;
+  domid_t otherend_id;
+  blkif_front_ring_t ring;
+  evtchn_port_t evtchn;
+  unsigned long sectors;
+  unsigned long sector_size;
+  unsigned char is_ro;
+};
+
+int
+vbd_request(struct vbd_info *info,
+           int op_write, unsigned long sector, char *buf);
+
+#endif
diff -r 092232fa1fbd extras/stubfw/xenbus.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/xenbus.c    Wed Nov 14 03:42:54 2007 +0100
@@ -0,0 +1,518 @@
+/* 
+ ****************************************************************************
+ * (C) 2006 - Cambridge University
+ ****************************************************************************
+ *
+ *        File: xenbus.c
+ *      Author: Steven Smith (sos22@xxxxxxxxx) 
+ *     Changes: Grzegorz Milos (gm281@xxxxxxxxx)
+ *     Changes: John D. Ramsdell
+ *              
+ *        Date: Jun 2006, chages Aug 2005
+ * 
+ * Environment: Xen Minimal OS
+ * Description: Minimal implementation of xenbus
+ *
+ ****************************************************************************
+ **/
+#include "os.h"
+#include "lib.h"
+#include "xenbus.h"
+#include "events.h"
+#include <xen/io/xs_wire.h>
+
+//#define XENBUS_DEBUG
+
+#define BUG_ON(x) do { \
+    if (x) {printk("BUG at %s:%d\n", __FILE__, __LINE__); BUG(); } \
+} while (0)
+
+#define min(x,y) ({                       \
+        typeof(x) tmpx = (x);                 \
+        typeof(y) tmpy = (y);                 \
+        tmpx < tmpy ? tmpx : tmpy;            \
+        })
+
+#ifdef XENBUS_DEBUG
+#define DEBUG(_f, _a...) \
+    printk("MINI_OS(file=xenbus.c, line=%d) " _f , __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...)    ((void)0)
+#endif
+
+static volatile struct xenstore_domain_interface *xenstore_buf;
+static int xenstore_evtchn;
+
+struct xenbus_req
+{
+    int id;
+
+    struct xsd_sockmsg reply;
+    char *reply_buf;
+    size_t reply_size;
+};
+
+#define NR_REQS 32
+static struct xenbus_req xb_reqs[NR_REQS];
+static int next_xb_reqs;
+
+struct xenbus_req *
+xenbus_allocate_req (char *buf, int size)
+{
+    if (next_xb_reqs == NR_REQS)
+       return NULL;
+    xb_reqs[next_xb_reqs].reply_buf = buf;
+    xb_reqs[next_xb_reqs].reply_size = size;
+    return &xb_reqs[next_xb_reqs++];
+}
+
+static void memcpy_from_ring(const void *Ring,
+        void *Dest,
+        int off,
+        int len)
+{
+    int c1, c2;
+    const char *ring = Ring;
+    char *dest = Dest;
+    c1 = min(len, XENSTORE_RING_SIZE - off);
+    c2 = len - c1;
+    memcpy(dest, ring + off, c1);
+    memcpy(dest + c1, ring, c2);
+}
+
+static void
+xenbus_wait_event (void)
+{
+    int res;
+    evtchn_port_t port = xenstore_evtchn;
+    sched_poll_t poll;
+
+    set_xen_guest_handle (poll.ports, &port);
+    poll.nr_ports = 1;
+    poll.timeout = 1000000000UL;
+    res = HYPERVISOR_poll (&poll);
+    //printk ("poll: res=%d\n", res);
+}
+
+static void 
+xenbus_wait_reply (struct xenbus_req *req)
+{
+    struct xsd_sockmsg msg;
+    unsigned prod;
+
+    while (1) {
+       prod = xenstore_buf->rsp_prod;
+       DEBUG("Rsp_cons %d, rsp_prod %d.\n", xenstore_buf->rsp_cons,
+             xenstore_buf->rsp_prod);
+       while (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons < sizeof(msg))
+           xenbus_wait_event ();
+       rmb();
+       memcpy_from_ring((char *)xenstore_buf->rsp,
+                        &msg,
+                        MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
+                        sizeof(msg));
+       DEBUG("Msg len %d+%d, %d avail, id %d.\n",
+             sizeof(msg), msg.len,
+             xenstore_buf->rsp_prod - xenstore_buf->rsp_cons,
+             msg.req_id);
+       while (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons <
+              sizeof(msg) + msg.len)
+           xenbus_wait_event ();
+       
+       DEBUG("Message is good type=%d.\n", msg.type);
+       
+       if (msg.type == XS_WATCH_EVENT) {
+           printk ("Unexpected watch event\n");
+           xenstore_buf->rsp_cons += msg.len + sizeof(msg);
+#if 0
+           char* payload = (char*)malloc(sizeof(msg) + msg.len);
+           char *path,*token;
+           
+           memcpy_from_ring(xenstore_buf->rsp,
+                            payload,
+                            MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
+                            msg.len + sizeof(msg));
+           
+           path = payload + sizeof(msg);
+           token = path + strlen(path) + 1;
+           
+           xenstore_buf->rsp_cons += msg.len + sizeof(msg);
+           free(payload);
+           wake_up(&watch_queue);
+#endif
+       }
+       else {
+           size_t len;
+           if (msg.req_id != req->id) {
+               printk ("unexpected reply for %d (was waiting for %d)\n",
+                       msg.req_id, req->id);
+           }
+           else {
+               memcpy (&req->reply, &msg, sizeof (msg));
+               xenstore_buf->rsp_cons += sizeof(msg);
+               len = min (msg.len, req->reply_size - 1);
+               memcpy_from_ring((char *)xenstore_buf->rsp,
+                                req->reply_buf,
+                                MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
+                                len);
+               /* Always put a NUL.  */
+               req->reply_buf[len] = 0;
+               xenstore_buf->rsp_cons += msg.len;
+               return;
+           }
+       }
+    }
+}
+
+static void xenbus_evtchn_handler(evtchn_port_t port, void *ign)
+{
+    printk ("xenbus event!\n");
+    //    wake_up(&xb_waitq);
+}
+
+/* Initialise xenbus. */
+void init_xenbus(void *interface, int evtchn)
+{
+    int err;
+    int i;
+
+    printk("Initialising xenbus\n");
+    DEBUG("init_xenbus called.\n");
+    xenstore_buf = (struct xenstore_domain_interface *)interface;
+    //create_thread("xenstore", xenbus_thread_func, NULL);
+    DEBUG("buf at %p.\n", xenstore_buf);
+    xenstore_evtchn = evtchn;
+    err = bind_evtchn(evtchn, xenbus_evtchn_handler, NULL);
+    DEBUG("xenbus on irq %d\n", err);
+
+    for (i = 0; i < NR_REQS; i++) {
+       xb_reqs[i].id = (i << 8) + 1;
+       xb_reqs[i].reply_size = 0;
+    }
+}
+
+const char*
+xenbus_wait_for_value(struct xenbus_req *r,
+                     const char* path, const char* value)
+{
+    while (1) {
+       const char *msg;
+        char *res;
+
+        msg = xenbus_read(r, XBT_NIL, path, &res);
+        if (msg)
+           return msg;
+       DEBUG("xenbus_wait_for_value: get %s, expect %s\n", res, value);
+        if (strcmp (value, res) == 0)
+           return NULL;
+       xenbus_wait_event ();
+    }
+}
+
+struct write_req {
+    const void *data;
+    unsigned len;
+};
+
+/* Send data to xenbus.  This can block.  All of the requests are seen
+   by xenbus as if sent atomically.  The header is added
+   automatically, using type %type, req_id %req_id, and trans_id
+   %trans_id. */
+static void xb_write(int type, struct xenbus_req *xb_req,
+                    xenbus_transaction_t trans_id,
+                    const struct write_req *req, int nr_reqs)
+{
+    XENSTORE_RING_IDX prod;
+    int r;
+    int len = 0;
+    const struct write_req *cur_req;
+    int req_off;
+    int total_off;
+    int this_chunk;
+    struct xsd_sockmsg m = {.type = type,
+                           .req_id = xb_req->id,
+                           .tx_id = trans_id };
+    struct write_req header_req = { &m, sizeof(m) };
+
+    for (r = 0; r < nr_reqs; r++)
+        len += req[r].len;
+    m.len = len;
+    len += sizeof(m);
+
+    cur_req = &header_req;
+
+    BUG_ON(len > XENSTORE_RING_SIZE);
+    /* Wait for the ring to drain to the point where we can send the
+       message. */
+    prod = xenstore_buf->req_prod;
+    if (prod + len - xenstore_buf->req_cons > XENSTORE_RING_SIZE) 
+    {
+       BUG();
+#if 0
+        /* Wait for there to be space on the ring */
+        DEBUG("prod %d, len %d, cons %d, size %d; waiting.\n",
+                prod, len, xenstore_buf->req_cons, XENSTORE_RING_SIZE);
+        wait_event(xb_waitq,
+                xenstore_buf->req_prod + len - xenstore_buf->req_cons <=
+                XENSTORE_RING_SIZE);
+        DEBUG("Back from wait.\n");
+        prod = xenstore_buf->req_prod;
+#endif
+    }
+
+    /* We're now guaranteed to be able to send the message without
+       overflowing the ring.  Do so. */
+    total_off = 0;
+    req_off = 0;
+    while (total_off < len) 
+    {
+        this_chunk = min(cur_req->len - req_off,
+                XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod));
+        memcpy((char *)xenstore_buf->req + MASK_XENSTORE_IDX(prod),
+                (char *)cur_req->data + req_off, this_chunk);
+        prod += this_chunk;
+        req_off += this_chunk;
+        total_off += this_chunk;
+        if (req_off == cur_req->len) 
+        {
+            req_off = 0;
+            if (cur_req == &header_req)
+                cur_req = req;
+            else
+                cur_req++;
+        }
+    }
+
+    DEBUG("Complete main loop of xb_write.\n");
+    BUG_ON(req_off != 0);
+    BUG_ON(total_off != len);
+    BUG_ON(prod > xenstore_buf->req_cons + XENSTORE_RING_SIZE);
+
+    /* Remote must see entire message before updating indexes */
+    wmb();
+
+    xenstore_buf->req_prod += len;
+
+    /* Send evtchn to notify remote */
+    notify_remote_via_evtchn(xenstore_evtchn);
+}
+
+/* Send a mesasge to xenbus, in the same fashion as xb_write, and
+   block waiting for a reply.  The reply is malloced and should be
+   freed by the caller. */
+static void
+xenbus_msg_reply(int type,
+                struct xenbus_req *req,
+                xenbus_transaction_t trans,
+                struct write_req *io,
+                int nr_reqs)
+{
+    xb_write(type, req, trans, io, nr_reqs);
+
+    xenbus_wait_reply (req);
+}
+
+static const char *errmsg(struct xenbus_req *req)
+{
+    if (!req->reply.len) {
+       return "No reply";
+    }
+    if (req->reply.len > req->reply_size) {
+       return "Truncated reply";
+    }
+    if (req->reply.type != XS_ERROR)
+       return NULL;
+    return req->reply_buf;
+}      
+
+/* Send a debug message to xenbus.  Can block. */
+void xenbus_debug_msg(struct xenbus_req *r, const char *msg)
+{
+    int len = strlen(msg);
+    struct write_req req[] = {
+        { "print", sizeof("print") },
+        { msg, len },
+        { "", 1 }};
+
+    xenbus_msg_reply(XS_DEBUG, r, 0, req, ARRAY_SIZE(req));
+    DEBUG("Got a reply, type %d, id %d, len %d.\n",
+            r->reply.type, r->reply.req_id, r->reply.len);
+}
+
+/* List the contents of a directory.  Returns a malloc()ed array of
+   pointers to malloc()ed strings.  The array is NULL terminated.  May
+   block. */
+const char *xenbus_ls(struct xenbus_req *r, xenbus_transaction_t xbt,
+                     const char *dir, char **contents, int *contents_len)
+{
+    char *reply;
+    struct write_req req[] = { { dir, strlen(dir)+1 } };
+    int nr_elems, x;
+
+    xenbus_msg_reply(XS_DIRECTORY, r, xbt, req, ARRAY_SIZE(req));
+    const char *msg = errmsg(r);
+    if (msg) {
+       *contents = NULL;
+       return msg;
+    }
+    /* Count number of elements.  */
+    reply = r->reply_buf;
+    if (*contents_len > 0)
+       contents[0] = reply;
+    for (x = nr_elems = 0; x < r->reply.len; x++, reply++) {
+       if (*reply == 0) {
+           nr_elems++;
+           if (nr_elems < *contents_len)
+               contents[nr_elems] = reply + 1;
+       }
+    }
+    *contents_len = nr_elems;
+    return NULL;
+}
+
+const char *
+xenbus_read(struct xenbus_req *r, xenbus_transaction_t xbt,
+           const char *path, char **value)
+{
+    struct write_req req[] = { {path, strlen(path) + 1} };
+    xenbus_msg_reply(XS_READ, r, xbt, req, ARRAY_SIZE(req));
+    const char *msg = errmsg(r);
+    if (msg) {
+       *value = NULL;
+       return msg;
+    }
+    *value = r->reply_buf;
+    return NULL;
+}
+
+const char *xenbus_write(struct xenbus_req *r, xenbus_transaction_t xbt, const 
char *path, const char *value)
+{
+    struct write_req req[] = { 
+       {path, strlen(path) + 1},
+       {value, strlen(value) + 1},
+    };
+    xenbus_msg_reply(XS_WRITE, r, xbt, req, ARRAY_SIZE(req));
+    const char *msg = errmsg(r);
+    if (msg)
+       return msg;
+    return NULL;
+}
+
+const char*
+xenbus_watch_path(struct xenbus_req *r, xenbus_transaction_t xbt,
+                 const char *path)
+{
+    /* in the future one could have multiple watch queues, and use
+     * the token for demuxing. For now the token is 0. */
+    struct write_req req[] = { 
+        {path, strlen(path) + 1},
+        {"0",2 },
+    };
+
+    xenbus_msg_reply(XS_WATCH, r, xbt, req, ARRAY_SIZE(req));
+
+    const char *msg = errmsg(r);
+    if (msg)
+       return msg;
+    return NULL;
+}
+
+const char *xenbus_rm(struct xenbus_req *r, xenbus_transaction_t xbt, const 
char *path)
+{
+    struct write_req req[] = { {path, strlen(path) + 1} };
+    xenbus_msg_reply(XS_RM, r, xbt, req, ARRAY_SIZE(req));
+    const char *msg = errmsg(r);
+    if (msg)
+       return msg;
+    return NULL;
+}
+
+const char *xenbus_get_perms(struct xenbus_req *r, xenbus_transaction_t xbt, 
const char *path, char **value)
+{
+    struct write_req req[] = { {path, strlen(path) + 1} };
+    xenbus_msg_reply(XS_GET_PERMS, r, xbt, req, ARRAY_SIZE(req));
+    const char *msg = errmsg(r);
+    if (msg) {
+       *value = NULL;
+       return msg;
+    }
+    *value = r->reply_buf;
+    return NULL;
+}
+
+#define PERM_MAX_SIZE 32
+const char *xenbus_set_perms(struct xenbus_req *r, xenbus_transaction_t xbt, 
const char *path, domid_t dom, char perm)
+{
+    char value[PERM_MAX_SIZE];
+    snprintf(value, PERM_MAX_SIZE, "%c%hu", perm, dom);
+    struct write_req req[] = { 
+       {path, strlen(path) + 1},
+       {value, strlen(value) + 1},
+    };
+    xenbus_msg_reply(XS_SET_PERMS, r, xbt, req, ARRAY_SIZE(req));
+    const char *msg = errmsg(r);
+    if (msg)
+       return msg;
+    return NULL;
+}
+
+const char *xenbus_transaction_start(struct xenbus_req *r, 
xenbus_transaction_t *xbt)
+{
+    /* xenstored becomes angry if you send a length 0 message, so just
+       shove a nul terminator on the end */
+    struct write_req req = { "", 1};
+    const char *err;
+
+    xenbus_msg_reply(XS_TRANSACTION_START, r, 0, &req, 1);
+    err = errmsg(r);
+    if (err)
+       return err;
+    sscanf(r->reply_buf, "%u", xbt);
+    return NULL;
+}
+
+const char *
+xenbus_transaction_end(struct xenbus_req *r, xenbus_transaction_t t, int 
abort, int *retry)
+{
+    struct write_req req;
+    const char *err;
+
+    *retry = 0;
+
+    req.data = abort ? "F" : "T";
+    req.len = 2;
+    xenbus_msg_reply(XS_TRANSACTION_END, r, t, &req, 1);
+    err = errmsg(r);
+    if (err) {
+       if (!strcmp(err, "EAGAIN")) {
+           *retry = 1;
+           return NULL;
+       } else {
+           return err;
+       }
+    }
+    return NULL;
+}
+
+int xenbus_read_integer(struct xenbus_req *r, char *path)
+{
+    const char *res;
+    char *buf;
+    int t;
+
+    res = xenbus_read(r, XBT_NIL, path, &buf);
+    if (res) {
+       printk("Failed to read %s.\n", path);
+       return -1;
+    }
+    sscanf(buf, "%d", &t);
+    return t;
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * End:
+ */
diff -r 092232fa1fbd extras/stubfw/xenbus_test.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/stubfw/xenbus_test.c       Wed Nov 14 01:47:42 2007 +0100
@@ -0,0 +1,90 @@
+#include "os.h"
+#include "lib.h"
+#include "xenbus.h"
+#include "events.h"
+#include <xen/io/xs_wire.h>
+
+static void do_ls_test(struct xenbus_req *r, const char *pre)
+{
+#define MAX_ENTRIES 32
+    char *dirs[MAX_ENTRIES];
+    int len = MAX_ENTRIES;
+    int x;
+
+    printk("ls %s...\n", pre);
+    const char *msg = xenbus_ls(r, XBT_NIL, pre, dirs, &len);
+    if (msg) {
+       printk("Error in xenbus ls: %s\n", msg);
+       return;
+    }
+    if (len > MAX_ENTRIES)
+       len = MAX_ENTRIES;
+    for (x = 0; x < len; x++) 
+    {
+        printk("ls %s[%d] -> %s\n", pre, x, dirs[x]);
+    }
+}
+
+static void do_read_test(struct xenbus_req *r, const char *path)
+{
+    char *res;
+    printk("Read %s...\n", path);
+    const char *msg = xenbus_read(r, XBT_NIL, path, &res);
+    if (msg) {
+       printk("Error in xenbus read: %s\n", msg);
+       return;
+    }
+    printk("Read %s -> %s.\n", path, res);
+}
+
+static void do_write_test(struct xenbus_req *r, const char *path, const char 
*val)
+{
+    printk("Write %s to %s...\n", val, path);
+    const char *msg = xenbus_write(r, XBT_NIL, path, val);
+    if (msg) {
+       printk("Result %s\n", msg);
+    } else {
+       printk("Success.\n");
+    }
+}
+
+static void do_rm_test(struct xenbus_req *r, const char *path)
+{
+    printk("rm %s...\n", path);
+    const char *msg = xenbus_rm(r, XBT_NIL, path);
+    if (msg) {
+       printk("Result %s\n", msg);
+    } else {
+       printk("Success.\n");
+    }
+}
+
+/* Simple testing thing */
+void test_xenbus(void)
+{
+    char buf[1024];
+    struct xenbus_req *r = xenbus_allocate_req (buf, sizeof (buf));
+
+    printk("Doing xenbus test.\n");
+    xenbus_debug_msg(r, "Testing xenbus...\n");
+
+    printk("Doing ls test.\n");
+    do_ls_test(r, "device");
+    do_ls_test(r, "device/vbd");
+    do_ls_test(r, "device/vbd/769");
+
+    printk("Doing read test.\n");
+    do_read_test(r, "device/vif/0/mac");
+    do_read_test(r, "device/vif/0/backend");
+
+    printk("Doing write test.\n");
+    do_write_test(r, "device/vif/0/flibble", "flobble");
+    do_read_test(r, "device/vif/0/flibble");
+    do_write_test(r, "device/vif/0/flibble", "widget");
+    do_read_test(r, "device/vif/0/flibble");
+
+    printk("Doing rm test.\n");
+    do_rm_test(r, "device/vif/0/flibble");
+    do_read_test(r, "device/vif/0/flibble");
+    printk("(Should have said ENOENT)\n");
+}

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


 


Rackspace

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