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(®, 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
|