From 927ad4986670f4938049c97e1bbabd5714e410e7 Mon Sep 17 00:00:00 2001
From: Richard Purdie <richard@openedhand.com>
Date: Thu, 24 Apr 2008 22:10:12 +0000
Subject: qemu-svn: Upgrade from r4027 -> 4242. Removes the need for gcc 3.x,
 adds USB networking for the n800

git-svn-id: https://svn.o-hand.com/repos/poky/trunk@4332 311d38ba-8fff-0310-9ca6-ca027cbcb966
---
 meta/conf/distro/poky.conf                         |     6 +-
 .../qemu-0.9.1+svn/02_snapshot_use_tmpdir.patch    |    23 -
 .../04_do_not_print_rtc_freq_if_ok.patch           |    26 -
 .../05_non-fatal_if_linux_hd_missing.patch         |    10 +-
 .../qemu/qemu-0.9.1+svn/06_exit_segfault.patch     |    12 +-
 .../qemu/qemu-0.9.1+svn/10_signal_jobs.patch       |     6 +-
 .../qemu/qemu-0.9.1+svn/11_signal_sigaction.patch  |     6 +-
 .../qemu/qemu-0.9.1+svn/22_net_tuntap_stall.patch  |     6 +-
 .../packages/qemu/qemu-0.9.1+svn/31_syscalls.patch |    12 +-
 .../qemu/qemu-0.9.1+svn/32_syscall_sysctl.patch    |     6 +-
 .../qemu/qemu-0.9.1+svn/33_syscall_ppc_clone.patch |     6 +-
 .../qemu/qemu-0.9.1+svn/39_syscall_fadvise64.patch |     6 +-
 .../qemu/qemu-0.9.1+svn/41_arm_fpa_sigfpe.patch    |   104 -
 .../qemu/qemu-0.9.1+svn/52_ne2000_return.patch     |     8 +-
 .../qemu/qemu-0.9.1+svn/61_safe_64bit_int.patch    |     4 +-
 .../qemu/qemu-0.9.1+svn/63_sparc_build.patch       |     6 +-
 .../qemu-0.9.1+svn/64_ppc_asm_constraints.patch    |     8 +-
 .../packages/qemu/qemu-0.9.1+svn/65_kfreebsd.patch |    10 +-
 meta/packages/qemu/qemu-0.9.1+svn/66_tls_ld.patch  |    16 +-
 .../qemu/qemu-0.9.1+svn/91-oh-sdl-cursor.patch     |     6 +-
 meta/packages/qemu/qemu-0.9.1+svn/fix_brk.patch    |    20 +-
 .../qemu/qemu-0.9.1+svn/fix_segfault.patch         |     8 +-
 meta/packages/qemu/qemu-0.9.1+svn/no-strip.patch   |    20 +-
 .../qemu-0.9.1+svn/qemu-0.9.0-nptl-update.patch    |   219 -
 .../qemu/qemu-0.9.1+svn/qemu-0.9.0-nptl.patch      |   450 +-
 .../qemu-amd64-32b-mapping-0.9.0.patch             |    10 +-
 .../qemu/qemu-0.9.1+svn/qemu-n800-support.patch    | 16147 +++----------------
 meta/packages/qemu/qemu-0.9.1+svn/series           |    20 +-
 meta/packages/qemu/qemu-0.9.1+svn/writev_fix.patch |    17 -
 meta/packages/qemu/qemu_0.9.1.bb                   |     1 -
 meta/packages/qemu/qemu_svn.bb                     |     5 +-
 31 files changed, 2738 insertions(+), 14466 deletions(-)
 delete mode 100644 meta/packages/qemu/qemu-0.9.1+svn/02_snapshot_use_tmpdir.patch
 delete mode 100644 meta/packages/qemu/qemu-0.9.1+svn/04_do_not_print_rtc_freq_if_ok.patch
 delete mode 100644 meta/packages/qemu/qemu-0.9.1+svn/41_arm_fpa_sigfpe.patch
 delete mode 100644 meta/packages/qemu/qemu-0.9.1+svn/qemu-0.9.0-nptl-update.patch
 delete mode 100644 meta/packages/qemu/qemu-0.9.1+svn/writev_fix.patch

(limited to 'meta')

diff --git a/meta/conf/distro/poky.conf b/meta/conf/distro/poky.conf
index 44b5ec797..fb176d0f9 100644
--- a/meta/conf/distro/poky.conf
+++ b/meta/conf/distro/poky.conf
@@ -149,9 +149,9 @@ SRCREV_pn-opkg ?= "4209"
 SRCREV_pn-opkg-native ?= "4209"
 SRCREV_pn-opkg-sdk ?= "4209"
 SRCREV_pn-libxosd ?= "627"
-SRCREV_pn-qemu-native ?= "4027"
-SRCREV_pn-qemu-sdk ?= "4027"
-SRCREV_pn-qemu ?= "4027"
+SRCREV_pn-qemu-native ?= "4242"
+SRCREV_pn-qemu-sdk ?= "4242"
+SRCREV_pn-qemu ?= "4242"
 SRCREV_pn-vincent ?= "246"
 
 # Previously floating revisions
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/02_snapshot_use_tmpdir.patch b/meta/packages/qemu/qemu-0.9.1+svn/02_snapshot_use_tmpdir.patch
deleted file mode 100644
index 40264ed44..000000000
--- a/meta/packages/qemu/qemu-0.9.1+svn/02_snapshot_use_tmpdir.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-#DPATCHLEVEL=0
----
-# block.c |    6 +++++-
-# 1 file changed, 5 insertions(+), 1 deletion(-)
-#
-Index: block.c
-===================================================================
---- block.c.orig	2007-12-03 23:47:25.000000000 +0000
-+++ block.c	2007-12-03 23:47:31.000000000 +0000
-@@ -191,8 +191,12 @@ void get_tmp_filename(char *filename, in
- void get_tmp_filename(char *filename, int size)
- {
-     int fd;
-+    char *tmpdir;
-     /* XXX: race condition possible */
--    pstrcpy(filename, size, "/tmp/vl.XXXXXX");
-+    tmpdir = getenv("TMPDIR");
-+    if (!tmpdir)
-+        tmpdir = "/tmp";
-+    snprintf(filename, size, "%s/vl.XXXXXX", tmpdir);
-     fd = mkstemp(filename);
-     close(fd);
- }
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/04_do_not_print_rtc_freq_if_ok.patch b/meta/packages/qemu/qemu-0.9.1+svn/04_do_not_print_rtc_freq_if_ok.patch
deleted file mode 100644
index 31c9da491..000000000
--- a/meta/packages/qemu/qemu-0.9.1+svn/04_do_not_print_rtc_freq_if_ok.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-#DPATCHLEVEL=1
----
-# vl.c |    5 ++++-
-# 1 file changed, 4 insertions(+), 1 deletion(-)
-#
-Index: qemu/vl.c
-===================================================================
---- qemu.orig/vl.c	2007-12-03 15:44:35.000000000 +0000
-+++ qemu/vl.c	2007-12-03 15:51:03.000000000 +0000
-@@ -1289,12 +1289,15 @@ static void hpet_stop_timer(struct qemu_
- 
- static int rtc_start_timer(struct qemu_alarm_timer *t)
- {
-+    unsigned long current_rtc_freq = 0;
-     int rtc_fd;
- 
-     TFR(rtc_fd = open("/dev/rtc", O_RDONLY));
-     if (rtc_fd < 0)
-         return -1;
--    if (ioctl(rtc_fd, RTC_IRQP_SET, RTC_FREQ) < 0) {
-+    ioctl(rtc_fd, RTC_IRQP_READ, &current_rtc_freq);
-+    if (current_rtc_freq != RTC_FREQ &&
-+        ioctl(rtc_fd, RTC_IRQP_SET, RTC_FREQ) < 0) {
-         fprintf(stderr, "Could not configure '/dev/rtc' to have a 1024 Hz timer. This is not a fatal\n"
-                 "error, but for better emulation accuracy either use a 2.6 host Linux kernel or\n"
-                 "type 'echo 1024 > /proc/sys/dev/rtc/max-user-freq' as root.\n");
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/05_non-fatal_if_linux_hd_missing.patch b/meta/packages/qemu/qemu-0.9.1+svn/05_non-fatal_if_linux_hd_missing.patch
index fdd922605..a66737d9c 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/05_non-fatal_if_linux_hd_missing.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/05_non-fatal_if_linux_hd_missing.patch
@@ -3,12 +3,12 @@
 # hw/pc.c |    1 -
 # 1 file changed, 1 deletion(-)
 #
-Index: qemu/hw/pc.c
+Index: trunk/hw/pc.c
 ===================================================================
---- qemu.orig/hw/pc.c	2007-12-03 23:47:25.000000000 +0000
-+++ qemu/hw/pc.c	2007-12-03 23:47:38.000000000 +0000
-@@ -385,7 +385,6 @@ static void generate_bootsect(uint32_t g
-     if (bs_table[0] == NULL) {
+--- trunk.orig/hw/pc.c	2008-04-24 20:15:46.000000000 +0100
++++ trunk/hw/pc.c	2008-04-24 20:15:49.000000000 +0100
+@@ -399,7 +399,6 @@
+     if (hda == -1) {
  	fprintf(stderr, "A disk image must be given for 'hda' when booting "
  		"a Linux kernel\n");
 -	exit(1);
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/06_exit_segfault.patch b/meta/packages/qemu/qemu-0.9.1+svn/06_exit_segfault.patch
index 06123d062..bc02d3183 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/06_exit_segfault.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/06_exit_segfault.patch
@@ -5,9 +5,9 @@
 #
 Index: linux-user/main.c
 ===================================================================
---- linux-user/main.c.orig	2007-12-03 23:47:25.000000000 +0000
-+++ linux-user/main.c	2007-12-03 23:47:41.000000000 +0000
-@@ -714,7 +714,7 @@ void cpu_loop (CPUSPARCState *env)
+--- linux-user/main.c.orig	2008-04-24 20:15:46.000000000 +0100
++++ linux-user/main.c	2008-04-24 20:15:53.000000000 +0100
+@@ -765,7 +765,7 @@
          default:
              printf ("Unhandled trap: 0x%x\n", trapnr);
              cpu_dump_state(env, stderr, fprintf, 0);
@@ -16,7 +16,7 @@ Index: linux-user/main.c
          }
          process_pending_signals (env);
      }
-@@ -1634,7 +1634,7 @@ void cpu_loop (CPUState *env)
+@@ -1697,7 +1697,7 @@
          default:
              printf ("Unhandled trap: 0x%x\n", trapnr);
              cpu_dump_state(env, stderr, fprintf, 0);
@@ -25,7 +25,7 @@ Index: linux-user/main.c
          }
          process_pending_signals (env);
      }
-@@ -1954,7 +1954,7 @@ int main(int argc, char **argv)
+@@ -2026,7 +2026,7 @@
                  for(item = cpu_log_items; item->mask != 0; item++) {
                      printf("%-10s %s\n", item->name, item->help);
                  }
@@ -34,7 +34,7 @@ Index: linux-user/main.c
              }
              cpu_set_log(mask);
          } else if (!strcmp(r, "s")) {
-@@ -1973,7 +1973,7 @@ int main(int argc, char **argv)
+@@ -2045,7 +2045,7 @@
              if (qemu_host_page_size == 0 ||
                  (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
                  fprintf(stderr, "page size must be a power of two\n");
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/10_signal_jobs.patch b/meta/packages/qemu/qemu-0.9.1+svn/10_signal_jobs.patch
index 34282adc9..d79482d2f 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/10_signal_jobs.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/10_signal_jobs.patch
@@ -5,9 +5,9 @@
 #
 Index: linux-user/signal.c
 ===================================================================
---- linux-user/signal.c.orig	2007-12-03 15:40:26.000000000 +0000
-+++ linux-user/signal.c	2007-12-03 15:55:49.000000000 +0000
-@@ -364,10 +364,15 @@ int queue_signal(int sig, target_siginfo
+--- linux-user/signal.c.orig	2008-04-24 20:15:46.000000000 +0100
++++ linux-user/signal.c	2008-04-24 20:15:55.000000000 +0100
+@@ -364,10 +364,15 @@
      k = &sigact_table[sig - 1];
      handler = k->sa._sa_handler;
      if (handler == TARGET_SIG_DFL) {
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/11_signal_sigaction.patch b/meta/packages/qemu/qemu-0.9.1+svn/11_signal_sigaction.patch
index 33c5e8b12..cd56541b7 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/11_signal_sigaction.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/11_signal_sigaction.patch
@@ -5,9 +5,9 @@
 #
 Index: linux-user/signal.c
 ===================================================================
---- linux-user/signal.c.orig	2007-12-03 23:47:44.000000000 +0000
-+++ linux-user/signal.c	2007-12-03 23:47:46.000000000 +0000
-@@ -512,6 +512,11 @@ int do_sigaction(int sig, const struct t
+--- linux-user/signal.c.orig	2008-04-24 20:15:55.000000000 +0100
++++ linux-user/signal.c	2008-04-24 20:15:57.000000000 +0100
+@@ -512,6 +512,11 @@
  
      if (sig < 1 || sig > TARGET_NSIG || sig == SIGKILL || sig == SIGSTOP)
          return -EINVAL;
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/22_net_tuntap_stall.patch b/meta/packages/qemu/qemu-0.9.1+svn/22_net_tuntap_stall.patch
index 6017df0f6..0e1038983 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/22_net_tuntap_stall.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/22_net_tuntap_stall.patch
@@ -5,9 +5,9 @@
 #
 Index: vl.c
 ===================================================================
---- vl.c.orig	2007-12-03 23:47:36.000000000 +0000
-+++ vl.c	2007-12-03 23:47:48.000000000 +0000
-@@ -4023,7 +4023,7 @@ static int tap_open(char *ifname, int if
+--- vl.c.orig	2008-04-24 20:15:46.000000000 +0100
++++ vl.c	2008-04-24 20:15:58.000000000 +0100
+@@ -4155,7 +4155,7 @@
          return -1;
      }
      memset(&ifr, 0, sizeof(ifr));
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/31_syscalls.patch b/meta/packages/qemu/qemu-0.9.1+svn/31_syscalls.patch
index 95a7332ee..15565ae11 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/31_syscalls.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/31_syscalls.patch
@@ -5,9 +5,9 @@
 #
 Index: linux-user/syscall.c
 ===================================================================
---- linux-user/syscall.c.orig	2007-12-03 19:32:56.000000000 +0000
-+++ linux-user/syscall.c	2007-12-03 19:33:41.000000000 +0000
-@@ -250,6 +250,7 @@ extern int getresuid(uid_t *, uid_t *, u
+--- linux-user/syscall.c.orig	2008-04-24 20:15:46.000000000 +0100
++++ linux-user/syscall.c	2008-04-24 20:15:59.000000000 +0100
+@@ -250,6 +250,7 @@
  extern int setresgid(gid_t, gid_t, gid_t);
  extern int getresgid(gid_t *, gid_t *, gid_t *);
  extern int setgroups(int, gid_t *);
@@ -15,7 +15,7 @@ Index: linux-user/syscall.c
  
  #define ERRNO_TABLE_SIZE 1200
  
-@@ -4024,7 +4025,8 @@ abi_long do_syscall(void *cpu_env, int n
+@@ -4041,7 +4042,8 @@
  #endif
  #ifdef TARGET_NR_uselib
      case TARGET_NR_uselib:
@@ -25,7 +25,7 @@ Index: linux-user/syscall.c
  #endif
  #ifdef TARGET_NR_swapon
      case TARGET_NR_swapon:
-@@ -5289,7 +5291,9 @@ abi_long do_syscall(void *cpu_env, int n
+@@ -5322,7 +5324,9 @@
          goto unimplemented;
  #ifdef TARGET_NR_mincore
      case TARGET_NR_mincore:
@@ -36,7 +36,7 @@ Index: linux-user/syscall.c
  #endif
  #ifdef TARGET_NR_madvise
      case TARGET_NR_madvise:
-@@ -5429,7 +5433,8 @@ abi_long do_syscall(void *cpu_env, int n
+@@ -5462,7 +5466,8 @@
          break;
  #ifdef TARGET_NR_readahead
      case TARGET_NR_readahead:
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/32_syscall_sysctl.patch b/meta/packages/qemu/qemu-0.9.1+svn/32_syscall_sysctl.patch
index 5e8dd75b0..d42c44ceb 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/32_syscall_sysctl.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/32_syscall_sysctl.patch
@@ -5,8 +5,8 @@
 #
 Index: linux-user/syscall.c
 ===================================================================
---- linux-user/syscall.c.orig	2007-12-03 15:56:24.000000000 +0000
-+++ linux-user/syscall.c	2007-12-03 15:57:36.000000000 +0000
+--- linux-user/syscall.c.orig	2008-04-24 20:15:59.000000000 +0100
++++ linux-user/syscall.c	2008-04-24 20:16:01.000000000 +0100
 @@ -52,6 +52,7 @@
  //#include <sys/user.h>
  #include <netinet/ip.h>
@@ -15,7 +15,7 @@ Index: linux-user/syscall.c
  
  #define termios host_termios
  #define winsize host_winsize
-@@ -4739,9 +4740,34 @@ abi_long do_syscall(void *cpu_env, int n
+@@ -4758,9 +4759,34 @@
          break;
  #endif
      case TARGET_NR__sysctl:
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/33_syscall_ppc_clone.patch b/meta/packages/qemu/qemu-0.9.1+svn/33_syscall_ppc_clone.patch
index 3f733b6ab..962f82152 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/33_syscall_ppc_clone.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/33_syscall_ppc_clone.patch
@@ -5,9 +5,9 @@
 #
 Index: linux-user/syscall.c
 ===================================================================
---- linux-user/syscall.c.orig	2007-12-03 15:58:11.000000000 +0000
-+++ linux-user/syscall.c	2007-12-03 15:58:46.000000000 +0000
-@@ -2750,11 +2750,7 @@ int do_fork(CPUState *env, unsigned int 
+--- linux-user/syscall.c.orig	2008-04-24 20:16:01.000000000 +0100
++++ linux-user/syscall.c	2008-04-24 20:16:02.000000000 +0100
+@@ -2760,11 +2760,7 @@
          if (!newsp)
              newsp = env->gpr[1];
          new_env->gpr[1] = newsp;
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/39_syscall_fadvise64.patch b/meta/packages/qemu/qemu-0.9.1+svn/39_syscall_fadvise64.patch
index 54ee3e094..845232cfc 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/39_syscall_fadvise64.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/39_syscall_fadvise64.patch
@@ -4,9 +4,9 @@
 
 Index: linux-user/syscall.c
 ===================================================================
---- linux-user/syscall.c.orig	2007-12-03 19:33:47.000000000 +0000
-+++ linux-user/syscall.c	2007-12-03 19:33:48.000000000 +0000
-@@ -5317,6 +5317,12 @@ abi_long do_syscall(void *cpu_env, int n
+--- linux-user/syscall.c.orig	2008-04-24 20:16:02.000000000 +0100
++++ linux-user/syscall.c	2008-04-24 20:16:03.000000000 +0100
+@@ -5350,6 +5350,12 @@
          ret = get_errno(mincore((void*)arg1, (size_t)arg2, (unsigned char*)arg3));
          break;
  #endif
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/41_arm_fpa_sigfpe.patch b/meta/packages/qemu/qemu-0.9.1+svn/41_arm_fpa_sigfpe.patch
deleted file mode 100644
index cea3afc7f..000000000
--- a/meta/packages/qemu/qemu-0.9.1+svn/41_arm_fpa_sigfpe.patch
+++ /dev/null
@@ -1,104 +0,0 @@
-#DPATCHLEVEL=0
----
-# linux-user/main.c        |   51 ++++++++++++++++++++++++++++++++++++++++++++++-
-# target-arm/nwfpe/fpa11.c |    7 ++++++
-# 2 files changed, 57 insertions(+), 1 deletion(-)
-#
-Index: linux-user/main.c
-===================================================================
---- linux-user/main.c.orig	2007-12-03 15:59:10.000000000 +0000
-+++ linux-user/main.c	2007-12-03 16:01:27.000000000 +0000
-@@ -377,18 +377,67 @@ void cpu_loop(CPUARMState *env)
-             {
-                 TaskState *ts = env->opaque;
-                 uint32_t opcode;
-+                int rc;
- 
-                 /* we handle the FPU emulation here, as Linux */
-                 /* we get the opcode */
-                 /* FIXME - what to do if get_user() fails? */
-                 get_user_u32(opcode, env->regs[15]);
- 
--                if (EmulateAll(opcode, &ts->fpa, env) == 0) {
-+                rc = EmulateAll(opcode, &ts->fpa, env);
-+                if (rc == 0) { /* illegal instruction */
-                     info.si_signo = SIGILL;
-                     info.si_errno = 0;
-                     info.si_code = TARGET_ILL_ILLOPN;
-                     info._sifields._sigfault._addr = env->regs[15];
-                     queue_signal(info.si_signo, &info);
-+                } else if (rc < 0) { /* FP exception */
-+                    int arm_fpe=0;
-+
-+                     /* translate softfloat flags to FPSR flags */
-+                    if (-rc & float_flag_invalid)
-+                      arm_fpe |= BIT_IOC;
-+                    if (-rc & float_flag_divbyzero)
-+                      arm_fpe |= BIT_DZC;
-+                    if (-rc & float_flag_overflow)
-+                      arm_fpe |= BIT_OFC;
-+                    if (-rc & float_flag_underflow)
-+                      arm_fpe |= BIT_UFC;
-+                    if (-rc & float_flag_inexact)
-+                      arm_fpe |= BIT_IXC;
-+
-+                    FPSR fpsr = ts->fpa.fpsr;
-+                    //printf("fpsr 0x%x, arm_fpe 0x%x\n",fpsr,arm_fpe);
-+
-+                    if (fpsr & (arm_fpe << 16)) { /* exception enabled? */
-+                      info.si_signo = SIGFPE;
-+                      info.si_errno = 0;
-+
-+                      /* ordered by priority, least first */
-+                      if (arm_fpe & BIT_IXC) info.si_code = TARGET_FPE_FLTRES;
-+                      if (arm_fpe & BIT_UFC) info.si_code = TARGET_FPE_FLTUND;
-+                      if (arm_fpe & BIT_OFC) info.si_code = TARGET_FPE_FLTOVF;
-+                      if (arm_fpe & BIT_DZC) info.si_code = TARGET_FPE_FLTDIV;
-+                      if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV;
-+
-+                      info._sifields._sigfault._addr = env->regs[15];
-+                      queue_signal(info.si_signo, &info);
-+                    } else {
-+                      env->regs[15] += 4;
-+                    }
-+
-+                    /* accumulate unenabled exceptions */
-+                    if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC))
-+                      fpsr |= BIT_IXC;
-+                    if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC))
-+                      fpsr |= BIT_UFC;
-+                    if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC))
-+                      fpsr |= BIT_OFC;
-+                    if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC))
-+                      fpsr |= BIT_DZC;
-+                    if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC))
-+                      fpsr |= BIT_IOC;
-+                    ts->fpa.fpsr=fpsr;
-                 } else {
-                     /* increment PC */
-                     env->regs[15] += 4;
-Index: target-arm/nwfpe/fpa11.c
-===================================================================
---- target-arm/nwfpe/fpa11.c.orig	2007-12-03 15:40:26.000000000 +0000
-+++ target-arm/nwfpe/fpa11.c	2007-12-03 15:59:11.000000000 +0000
-@@ -162,6 +162,8 @@ unsigned int EmulateAll(unsigned int opc
-     fpa11->initflag = 1;
-   }
- 
-+  set_float_exception_flags(0, &fpa11->fp_status);  
-+
-   if (TEST_OPCODE(opcode,MASK_CPRT))
-   {
-     //fprintf(stderr,"emulating CPRT\n");
-@@ -191,6 +193,11 @@ unsigned int EmulateAll(unsigned int opc
-   }
- 
- //  restore_flags(flags);
-+  if(nRc == 1 && get_float_exception_flags(&fpa11->fp_status))
-+  {
-+    //printf("fef 0x%x\n",float_exception_flags);
-+    nRc=-get_float_exception_flags(&fpa11->fp_status);
-+  }
- 
-   //printf("returning %d\n",nRc);
-   return(nRc);
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/52_ne2000_return.patch b/meta/packages/qemu/qemu-0.9.1+svn/52_ne2000_return.patch
index e4ea33f2c..e364bff73 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/52_ne2000_return.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/52_ne2000_return.patch
@@ -2,11 +2,11 @@
  hw/ne2000.c |    2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
 
-Index: qemu/hw/ne2000.c
+Index: trunk/hw/ne2000.c
 ===================================================================
---- qemu.orig/hw/ne2000.c	2007-12-03 19:32:52.000000000 +0000
-+++ qemu/hw/ne2000.c	2007-12-03 19:33:55.000000000 +0000
-@@ -217,7 +217,7 @@ static int ne2000_can_receive(void *opaq
+--- trunk.orig/hw/ne2000.c	2008-04-24 20:15:46.000000000 +0100
++++ trunk/hw/ne2000.c	2008-04-24 20:16:05.000000000 +0100
+@@ -217,7 +217,7 @@
      NE2000State *s = opaque;
  
      if (s->cmd & E8390_STOP)
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/61_safe_64bit_int.patch b/meta/packages/qemu/qemu-0.9.1+svn/61_safe_64bit_int.patch
index 9b1ace81a..9a67feac6 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/61_safe_64bit_int.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/61_safe_64bit_int.patch
@@ -5,8 +5,8 @@
 #
 Index: dyngen-exec.h
 ===================================================================
---- dyngen-exec.h.orig	2007-12-31 13:06:21.000000000 +0000
-+++ dyngen-exec.h	2007-12-31 13:08:54.000000000 +0000
+--- dyngen-exec.h.orig	2008-04-24 20:15:46.000000000 +0100
++++ dyngen-exec.h	2008-04-24 20:16:06.000000000 +0100
 @@ -38,7 +38,7 @@
  // Linux/Sparc64 defines uint64_t
  #if !(defined (__sparc_v9__) && defined(__linux__))
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/63_sparc_build.patch b/meta/packages/qemu/qemu-0.9.1+svn/63_sparc_build.patch
index 37b38f641..097f55a09 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/63_sparc_build.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/63_sparc_build.patch
@@ -5,9 +5,9 @@
 #
 Index: sparc.ld
 ===================================================================
---- sparc.ld.orig	2007-12-03 15:40:26.000000000 +0000
-+++ sparc.ld	2007-12-03 16:05:06.000000000 +0000
-@@ -6,7 +6,7 @@ ENTRY(_start)
+--- sparc.ld.orig	2008-04-24 20:15:46.000000000 +0100
++++ sparc.ld	2008-04-24 20:16:07.000000000 +0100
+@@ -6,7 +6,7 @@
  SECTIONS
  {
    /* Read-only sections, merged into text segment: */
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/64_ppc_asm_constraints.patch b/meta/packages/qemu/qemu-0.9.1+svn/64_ppc_asm_constraints.patch
index e4858b79d..7d1981727 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/64_ppc_asm_constraints.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/64_ppc_asm_constraints.patch
@@ -3,11 +3,11 @@
 # cpu-all.h |    2 +-
 # 1 file changed, 1 insertion(+), 1 deletion(-)
 #
-Index: qemu/cpu-all.h
+Index: trunk/cpu-all.h
 ===================================================================
---- qemu.orig/cpu-all.h	2007-06-13 11:48:22.000000000 +0100
-+++ qemu/cpu-all.h	2007-06-13 11:51:56.000000000 +0100
-@@ -250,7 +250,7 @@ static inline void stw_le_p(void *ptr, i
+--- trunk.orig/cpu-all.h	2008-04-24 20:15:46.000000000 +0100
++++ trunk/cpu-all.h	2008-04-24 20:16:08.000000000 +0100
+@@ -285,7 +285,7 @@
  static inline void stl_le_p(void *ptr, int v)
  {
  #ifdef __powerpc__
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/65_kfreebsd.patch b/meta/packages/qemu/qemu-0.9.1+svn/65_kfreebsd.patch
index dfece800a..028e85a87 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/65_kfreebsd.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/65_kfreebsd.patch
@@ -5,9 +5,9 @@
 
 Index: configure
 ===================================================================
---- configure.orig	2007-12-03 15:40:26.000000000 +0000
-+++ configure	2007-12-03 16:05:34.000000000 +0000
-@@ -129,6 +129,12 @@ if [ "$cpu" = "i386" -o "$cpu" = "x86_64
+--- configure.orig	2008-04-24 20:15:46.000000000 +0100
++++ configure	2008-04-24 20:16:09.000000000 +0100
+@@ -135,6 +135,12 @@
      kqemu="yes"
  fi
  ;;
@@ -22,8 +22,8 @@ Index: configure
  oss="yes"
 Index: vl.c
 ===================================================================
---- vl.c.orig	2007-12-03 16:05:32.000000000 +0000
-+++ vl.c	2007-12-03 16:05:34.000000000 +0000
+--- vl.c.orig	2008-04-24 20:15:58.000000000 +0100
++++ vl.c	2008-04-24 20:16:09.000000000 +0100
 @@ -97,6 +97,8 @@
  #include <stropts.h>
  #endif
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/66_tls_ld.patch b/meta/packages/qemu/qemu-0.9.1+svn/66_tls_ld.patch
index 54e02eff8..cbd3f873d 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/66_tls_ld.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/66_tls_ld.patch
@@ -5,9 +5,9 @@
 
 Index: arm.ld
 ===================================================================
---- arm.ld.orig	2007-06-13 11:48:22.000000000 +0100
-+++ arm.ld	2007-06-13 11:51:56.000000000 +0100
-@@ -26,6 +26,10 @@ SECTIONS
+--- arm.ld.orig	2008-04-24 20:15:45.000000000 +0100
++++ arm.ld	2008-04-24 20:16:11.000000000 +0100
+@@ -26,6 +26,10 @@
      { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
    .rela.rodata   :
      { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
@@ -18,7 +18,7 @@ Index: arm.ld
    .rel.got       : { *(.rel.got)		}
    .rela.got      : { *(.rela.got)		}
    .rel.ctors     : { *(.rel.ctors)	}
-@@ -58,6 +62,9 @@ SECTIONS
+@@ -58,6 +62,9 @@
    .ARM.exidx   : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) }
     __exidx_end = .;
    .reginfo : { *(.reginfo) }
@@ -30,9 +30,9 @@ Index: arm.ld
    . = ALIGN(0x100000) + (. & (0x100000 - 1));
 Index: i386.ld
 ===================================================================
---- i386.ld.orig	2007-06-13 11:48:22.000000000 +0100
-+++ i386.ld	2007-06-13 11:51:56.000000000 +0100
-@@ -28,6 +28,10 @@ SECTIONS
+--- i386.ld.orig	2008-04-24 20:15:45.000000000 +0100
++++ i386.ld	2008-04-24 20:16:11.000000000 +0100
+@@ -28,6 +28,10 @@
      { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
    .rela.rodata   :
      { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
@@ -43,7 +43,7 @@ Index: i386.ld
    .rel.got       : { *(.rel.got)		}
    .rela.got      : { *(.rela.got)		}
    .rel.ctors     : { *(.rel.ctors)	}
-@@ -53,6 +57,9 @@ SECTIONS
+@@ -53,6 +57,9 @@
    _etext = .;
    PROVIDE (etext = .);
    .fini      : { *(.fini)    } =0x47ff041f
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/91-oh-sdl-cursor.patch b/meta/packages/qemu/qemu-0.9.1+svn/91-oh-sdl-cursor.patch
index 0d60c1c30..b3d95a453 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/91-oh-sdl-cursor.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/91-oh-sdl-cursor.patch
@@ -5,9 +5,9 @@
 
 Index: sdl.c
 ===================================================================
---- sdl.c.orig	2007-12-03 19:32:15.000000000 +0000
-+++ sdl.c	2007-12-03 19:34:04.000000000 +0000
-@@ -247,7 +247,7 @@ static void sdl_hide_cursor(void)
+--- sdl.c.orig	2008-04-24 20:15:45.000000000 +0100
++++ sdl.c	2008-04-24 20:16:12.000000000 +0100
+@@ -247,7 +247,7 @@
  
      if (kbd_mouse_is_absolute()) {
          SDL_ShowCursor(1);
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/fix_brk.patch b/meta/packages/qemu/qemu-0.9.1+svn/fix_brk.patch
index 783198d9e..f15e001dd 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/fix_brk.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/fix_brk.patch
@@ -1,6 +1,8 @@
---- qemu/linux-user/syscall.c1	(revision 16)
-+++ qemu/linux-user/syscall.c	(working copy)
-@@ -441,7 +441,7 @@
+Index: trunk/linux-user/syscall.c
+===================================================================
+--- trunk.orig/linux-user/syscall.c	2008-04-24 20:16:24.000000000 +0100
++++ trunk/linux-user/syscall.c	2008-04-24 20:16:32.000000000 +0100
+@@ -440,7 +440,7 @@
      if (!new_brk)
          return target_brk;
      if (new_brk < target_original_brk)
@@ -9,7 +11,7 @@
  
      brk_page = HOST_PAGE_ALIGN(target_brk);
  
-@@ -456,12 +456,11 @@
+@@ -455,12 +455,11 @@
      mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
                                          PROT_READ|PROT_WRITE,
                                          MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
@@ -26,9 +28,11 @@
  }
  
  static inline abi_long copy_from_user_fdset(fd_set *fds,
---- qemu/linux-user/mmap.c1	(revision 16)
-+++ qemu/linux-user/mmap.c	(working copy)
-@@ -260,6 +259,9 @@
+Index: trunk/linux-user/mmap.c
+===================================================================
+--- trunk.orig/linux-user/mmap.c	2008-04-24 20:16:16.000000000 +0100
++++ trunk/linux-user/mmap.c	2008-04-24 20:16:32.000000000 +0100
+@@ -264,6 +264,9 @@
              host_start += offset - host_offset;
          start = h2g(host_start);
      } else {
@@ -38,7 +42,7 @@
          if (start & ~TARGET_PAGE_MASK) {
              errno = EINVAL;
              return -1;
-@@ -267,6 +269,14 @@
+@@ -271,6 +274,14 @@
          end = start + len;
          real_end = HOST_PAGE_ALIGN(end);
          
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/fix_segfault.patch b/meta/packages/qemu/qemu-0.9.1+svn/fix_segfault.patch
index 443c33065..224a8b813 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/fix_segfault.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/fix_segfault.patch
@@ -2,11 +2,11 @@
  linux-user/syscall.c |   22 ----------------------
  1 file changed, 22 deletions(-)
 
-Index: qemu/linux-user/syscall.c
+Index: trunk/linux-user/syscall.c
 ===================================================================
---- qemu.orig/linux-user/syscall.c	2007-12-03 23:40:11.000000000 +0000
-+++ qemu/linux-user/syscall.c	2007-12-03 23:40:21.000000000 +0000
-@@ -5695,28 +5695,6 @@ abi_long do_syscall(void *cpu_env, int n
+--- trunk.orig/linux-user/syscall.c	2008-04-24 20:16:21.000000000 +0100
++++ trunk/linux-user/syscall.c	2008-04-24 20:16:24.000000000 +0100
+@@ -5728,28 +5728,6 @@
             goto unimplemented_nowarn;
  #endif
  
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/no-strip.patch b/meta/packages/qemu/qemu-0.9.1+svn/no-strip.patch
index fc69b37e1..4813dd4e2 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/no-strip.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/no-strip.patch
@@ -1,6 +1,8 @@
---- qemu.orig/Makefile	2008-01-29 23:16:27.000000000 -0800
-+++ qemu-0.9.1/Makefile	2008-01-29 23:16:38.000000000 -0800
-@@ -174,7 +174,7 @@
+Index: trunk/Makefile
+===================================================================
+--- trunk.orig/Makefile	2008-04-24 20:15:37.000000000 +0100
++++ trunk/Makefile	2008-04-24 20:16:30.000000000 +0100
+@@ -196,7 +196,7 @@
  install: all $(if $(BUILD_DOCS),install-doc)
  	mkdir -p "$(DESTDIR)$(bindir)"
  ifneq ($(TOOLS),)
@@ -8,10 +10,12 @@
 +	$(INSTALL) -m 755 $(TOOLS) "$(DESTDIR)$(bindir)"
  endif
  	mkdir -p "$(DESTDIR)$(datadir)"
- 	for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
---- qemu.orig/Makefile.target	2008-01-29 23:16:27.000000000 -0800
-+++ qemu-0.9.1/Makefile.target	2008-01-29 23:17:33.000000000 -0800
-@@ -632,7 +632,7 @@
+ 	set -e; for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
+Index: trunk/Makefile.target
+===================================================================
+--- trunk.orig/Makefile.target	2008-04-24 20:15:37.000000000 +0100
++++ trunk/Makefile.target	2008-04-24 20:16:30.000000000 +0100
+@@ -685,7 +685,7 @@
  
  install: all
  ifneq ($(PROGS),)
@@ -19,4 +23,4 @@
 +	$(INSTALL) -m 755 $(PROGS) "$(DESTDIR)$(bindir)"
  endif
  
- ifneq ($(wildcard .depend),)
+ # Include automatically generated dependency files
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/qemu-0.9.0-nptl-update.patch b/meta/packages/qemu/qemu-0.9.1+svn/qemu-0.9.0-nptl-update.patch
deleted file mode 100644
index ebc996e87..000000000
--- a/meta/packages/qemu/qemu-0.9.1+svn/qemu-0.9.0-nptl-update.patch
+++ /dev/null
@@ -1,219 +0,0 @@
----
- linux-user/main.c    |    7 ++-
- linux-user/syscall.c |  114 ++++++++++++++++++++++++++++++++++++++++++++++-----
- 2 files changed, 111 insertions(+), 10 deletions(-)
-
-Index: qemu/linux-user/main.c
-===================================================================
---- qemu.orig/linux-user/main.c	2007-12-03 19:34:09.000000000 +0000
-+++ qemu/linux-user/main.c	2007-12-03 23:44:45.000000000 +0000
-@@ -391,7 +391,7 @@ do_kernel_trap(CPUARMState *env)
-         cpu_unlock();
-         break;
-     case 0xffff0fe0: /* __kernel_get_tls */
--        env->regs[0] = env->cp15.c13_tls;
-+        env->regs[0] = env->cp15.c13_tls2;
-         break;
-     default:
-         return 1;
-@@ -2037,6 +2037,11 @@ int main(int argc, char **argv)
-     int drop_ld_preload = 0, environ_count = 0;
-     char **target_environ, **wrk, **dst;
- 
-+    char *assume_kernel = getenv("QEMU_ASSUME_KERNEL");
-+
-+    if (assume_kernel)
-+       setenv("LD_ASSUME_KERNEL", assume_kernel, 1);
-+
-     if (argc <= 1)
-         usage();
- 
-Index: qemu/linux-user/syscall.c
-===================================================================
---- qemu.orig/linux-user/syscall.c	2007-12-03 19:34:09.000000000 +0000
-+++ qemu/linux-user/syscall.c	2007-12-03 23:46:54.000000000 +0000
-@@ -61,6 +61,7 @@
- #define tchars host_tchars /* same as target */
- #define ltchars host_ltchars /* same as target */
- 
-+#include <linux/futex.h>
- #include <linux/termios.h>
- #include <linux/unistd.h>
- #include <linux/utsname.h>
-@@ -2694,7 +2695,6 @@ abi_long do_arch_prctl(CPUX86State *env,
-     return 0;
- }
- #endif
--
- #endif /* defined(TARGET_I386) */
- 
- /* this stack is the equivalent of the kernel stack associated with a
-@@ -2729,16 +2729,19 @@ int do_fork(CPUState *env, unsigned int 
-     TaskState *ts;
-     uint8_t *new_stack;
-     CPUState *new_env;
--
-+#if defined(TARGET_I386)
-+     uint64_t *new_gdt_table;
-+#endif
- #ifdef USE_NPTL
-     unsigned int nptl_flags;
- 
-     if (flags & CLONE_PARENT_SETTID)
-         *parent_tidptr = gettid();
- #endif
--
-     if (flags & CLONE_VM) {
-         ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE);
-+        if (!ts)
-+          return -ENOMEM;
-         memset(ts, 0, sizeof(TaskState));
-         new_stack = ts->stack;
-         ts->used = 1;
-@@ -2750,6 +2753,29 @@ int do_fork(CPUState *env, unsigned int 
- #if defined(TARGET_I386)
-         if (!newsp)
-             newsp = env->regs[R_ESP];
-+       new_gdt_table = malloc(9 * 8);
-+       if (!new_gdt_table) {
-+               free(new_env);
-+               return -ENOMEM;
-+       }
-+       /* Copy main GDT table from parent, but clear TLS entries */
-+       memcpy(new_gdt_table, g2h(env->gdt.base), 6 * 8);
-+       memset(&new_gdt_table[6], 0, 3 * 8); 
-+       new_env->gdt.base = h2g(new_gdt_table);
-+       if (flags & 0x00080000 /* CLONE_SETTLS */) {
-+               ret = do_set_thread_area(new_env, new_env->regs[R_ESI]);
-+               if (ret) {
-+                       free(new_gdt_table);
-+                       free(new_env);
-+                       return ret;
-+               }
-+       }
-+       cpu_x86_load_seg(env, R_CS, new_env->regs[R_CS]);
-+       cpu_x86_load_seg(env, R_DS, new_env->regs[R_DS]);
-+       cpu_x86_load_seg(env, R_ES, new_env->regs[R_ES]);
-+       cpu_x86_load_seg(env, R_SS, new_env->regs[R_SS]);
-+       cpu_x86_load_seg(env, R_FS, new_env->regs[R_FS]);
-+       cpu_x86_load_seg(env, R_GS, new_env->regs[R_GS]);
-         new_env->regs[R_ESP] = newsp;
-         new_env->regs[R_EAX] = 0;
- #elif defined(TARGET_ARM)
-@@ -3121,6 +3147,68 @@ static inline abi_long host_to_target_ti
-     unlock_user_struct(target_ts, target_addr, 1);
- }
- 
-+static long do_futex(target_ulong uaddr, int op, uint32_t val,
-+                    target_ulong utime, target_ulong uaddr2,
-+                    uint32_t val3)
-+{
-+       struct timespec host_utime;
-+       unsigned long val2 = utime;
-+
-+       if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) {
-+               target_to_host_timespec(&host_utime, utime);
-+               val2 = (unsigned long)&host_utime;
-+       }
-+ 
-+#ifdef BSWAP_NEEDED
-+       switch(op) {
-+       case FUTEX_CMP_REQUEUE:
-+               val3 = tswap32(val3);
-+       case FUTEX_REQUEUE:
-+               val2 = tswap32(val2);
-+       case FUTEX_WAIT:
-+       case FUTEX_WAKE:
-+               val = tswap32(val);
-+       case FUTEX_LOCK_PI: /* This one's icky, but comes out OK */
-+       case FUTEX_UNLOCK_PI:
-+               break;
-+       default: 
-+               gemu_log("qemu: Unsupported futex op %d\n", op);
-+               return -ENOSYS;
-+       } 
-+#if 0 /* No, it's worse than this */
-+       if (op == FUTEX_WAKE_OP) {
-+               /* Need to munge the secondary operation (val3) */
-+               val3 = tswap32(val3);
-+               int op2 = (val3 >> 28) & 7;
-+               int cmp = (val3 >> 24) & 15;
-+               int oparg = (val3 << 8) >> 20;
-+               int cmparg = (val3 << 20) >> 20;
-+               int shift = val3 & (FUTEX_OP_OPARG_SHIFT << 28);
-+
-+               if (shift)
-+                   oparg = (oparg & 7) + 24 - (oparg & 24);
-+               else oparg = 
-+               if (op2 == FUTEX_OP_ADD) {
-+                       gemu_log("qemu: Unsupported wrong-endian FUTEX_OP_ADD\n");
-+                       return -ENOSYS;
-+               }
-+               if (cmparg == FUTEX_OP_CMP_LT || cmparg == FUTEX_OP_CMP_GE ||
-+                   cmparg == FUTEX_OP_CMP_LE || cmparg == FUTEX_OP_CMP_GT) {
-+                       gemu_log("qemu: Unsupported wrong-endian futex cmparg %d\n", cmparg);
-+                       return -ENOSYS;
-+               }
-+               val3 = shift | (op2<<28) | (cmp<<24) | (oparg<<12) | cmparg;
-+       }
-+#endif
-+#endif
-+       return syscall(__NR_futex, g2h(uaddr), op, val, val2, g2h(uaddr2), val3);
-+}
-+
-+int do_set_tid_address(target_ulong tidptr)
-+{
-+       return syscall(__NR_set_tid_address, g2h(tidptr));
-+}
-+
- /* do_syscall() should always have a single exit point at the end so
-    that actions, such as logging of syscall results, can be performed.
-    All errnos that do_syscall() returns must be -TARGET_<errcode>. */
-@@ -3145,7 +3233,7 @@ abi_long do_syscall(void *cpu_env, int n
-         _mcleanup();
- #endif
-         gdb_exit(cpu_env, arg1);
--        /* XXX: should free thread stack and CPU env */
-+        /* XXX: should free thread stack, GDT and CPU env */
-         _exit(arg1);
-         ret = 0; /* avoid warning */
-         break;
-@@ -5569,6 +5657,9 @@ abi_long do_syscall(void *cpu_env, int n
- #elif defined(TARGET_I386) && defined(TARGET_ABI32)
-       ret = do_set_thread_area(cpu_env, arg1);
-       break;
-+#elif TARGET_i386
-+	  ret = get_errno(do_set_thread_area(cpu_env, arg1));
-+	  break;
- #else
-       goto unimplemented_nowarn;
- #endif
-@@ -5586,6 +5677,16 @@ abi_long do_syscall(void *cpu_env, int n
-         goto unimplemented_nowarn;
- #endif
- 
-+#ifdef TARGET_NR_futex
-+    case TARGET_NR_futex:
-+       ret = get_errno(do_futex(arg1, arg2, arg3, arg4, arg5, arg6));
-+       break;
-+#endif
-+#ifdef TARGET_NR_set_robust_list
-+    case TARGET_NR_set_robust_list:
-+           goto unimplemented_nowarn;
-+#endif
-+
- #ifdef TARGET_NR_clock_gettime
-     case TARGET_NR_clock_gettime:
-     {
-@@ -5627,11 +5728,6 @@ abi_long do_syscall(void *cpu_env, int n
- 	break;
- #endif
- 
--#ifdef TARGET_NR_set_robust_list
--    case TARGET_NR_set_robust_list:
--	goto unimplemented_nowarn;
--#endif
--
- #if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
-     case TARGET_NR_utimensat:
-         {
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/qemu-0.9.0-nptl.patch b/meta/packages/qemu/qemu-0.9.1+svn/qemu-0.9.0-nptl.patch
index 4a87d8d63..ac68ebf46 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/qemu-0.9.0-nptl.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/qemu-0.9.0-nptl.patch
@@ -1,19 +1,3 @@
-These are Paul Brook's patches to QEMU-0.8.2 to enable the running of single
-ARM binaries under QEMU's user-emulation mode. Without them, QEMU-0.8.1
-immediately dies saying:
-	Error: f0005
-	qemu: uncaught target signal 6 (Aborted) - exiting
-while qemu-0.8.2 dies saying:
-	qemu: Unsupported syscall: 983045
-	cannot set up thread-local storage: unknown error
-
-This file is a rediffing of the patches visible at
-https://nowt.dyndns.org/patch.qemu_nptl on 27 Sept 2006
-which "patch" fails to apply automatically.
-See also http://lists.gnu.org/archive/html/qemu-devel/2006-09/msg00194.html
-
-	Martin Guy, 27 Sept 2006
-
 ---
  configure                |   25 ++++++
  exec-all.h               |  165 ------------------------------------------
@@ -27,11 +11,11 @@ See also http://lists.gnu.org/archive/html/qemu-devel/2006-09/msg00194.html
  target-arm/translate.c   |    9 ++
  10 files changed, 405 insertions(+), 183 deletions(-)
 
-Index: qemu/configure
+Index: trunk/configure
 ===================================================================
---- qemu.orig/configure	2008-04-09 23:02:37.000000000 +0100
-+++ qemu/configure	2008-04-09 23:06:36.000000000 +0100
-@@ -109,6 +109,7 @@
+--- trunk.orig/configure	2008-04-24 20:16:52.000000000 +0100
++++ trunk/configure	2008-04-24 20:16:53.000000000 +0100
+@@ -112,6 +112,7 @@
  build_docs="no"
  uname_release=""
  curses="yes"
@@ -39,7 +23,7 @@ Index: qemu/configure
  
  # OS specific
  targetos=`uname -s`
-@@ -334,6 +335,8 @@
+@@ -339,6 +340,8 @@
    ;;
    *) echo "ERROR: unknown option $opt"; show_help="yes"
    ;;
@@ -48,7 +32,7 @@ Index: qemu/configure
    esac
  done
  
-@@ -429,6 +432,7 @@
+@@ -436,6 +439,7 @@
  echo "  --disable-linux-user     disable all linux usermode emulation targets"
  echo "  --enable-darwin-user     enable all darwin usermode emulation targets"
  echo "  --disable-darwin-user    disable all darwin usermode emulation targets"
@@ -56,7 +40,7 @@ Index: qemu/configure
  echo "  --fmod-lib               path to FMOD library"
  echo "  --fmod-inc               path to FMOD includes"
  echo "  --enable-uname-release=R Return R for uname -r in usermode emulation"
-@@ -595,6 +599,23 @@
+@@ -647,6 +651,23 @@
  }
  EOF
  
@@ -80,7 +64,7 @@ Index: qemu/configure
  ##########################################
  # SDL probe
  
-@@ -778,6 +799,7 @@
+@@ -845,6 +866,7 @@
  echo "Documentation     $build_docs"
  [ ! -z "$uname_release" ] && \
  echo "uname -r          $uname_release"
@@ -88,24 +72,48 @@ Index: qemu/configure
  
  if test $sdl_too_old = "yes"; then
  echo "-> Your SDL version is too old - please upgrade to have SDL support"
-@@ -1115,6 +1137,9 @@
-   echo "TARGET_ARCH=arm" >> $config_mak
-   echo "#define TARGET_ARCH \"arm\"" >> $config_h
-   echo "#define TARGET_ARM 1" >> $config_h
-+  if test "$nptl" = "yes" ; then
-+	  echo "#define USE_NPTL 1" >> $config_h
-+  fi
-   bflt="yes"
- elif test "$target_cpu" = "sparc" ; then
-   echo "TARGET_ARCH=sparc" >> $config_mak
-Index: qemu/exec-all.h
+@@ -1228,6 +1250,9 @@
+     echo "#define TARGET_ARM 1" >> $config_h
+     echo "#define CONFIG_NO_DYNGEN_OP 1" >> $config_h
+     bflt="yes"
++    if test "$nptl" = "yes" ; then
++      echo "#define USE_NPTL 1" >> $config_h
++    fi
+   ;;
+   cris)
+     echo "TARGET_ARCH=cris" >> $config_mak
+Index: trunk/exec-all.h
 ===================================================================
---- qemu.orig/exec-all.h	2008-04-09 22:39:38.000000000 +0100
-+++ qemu/exec-all.h	2008-04-09 23:05:55.000000000 +0100
-@@ -297,170 +297,7 @@
+--- trunk.orig/exec-all.h	2008-04-24 20:16:41.000000000 +0100
++++ trunk/exec-all.h	2008-04-24 20:16:53.000000000 +0100
+@@ -303,217 +303,7 @@
  extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
  extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
  
+-#if defined(__hppa__)
+-
+-typedef int spinlock_t[4];
+-
+-#define SPIN_LOCK_UNLOCKED { 1, 1, 1, 1 }
+-
+-static inline void resetlock (spinlock_t *p)
+-{
+-    (*p)[0] = (*p)[1] = (*p)[2] = (*p)[3] = 1;
+-}
+-
+-#else
+-
+-typedef int spinlock_t;
+-
+-#define SPIN_LOCK_UNLOCKED 0
+-
+-static inline void resetlock (spinlock_t *p)
+-{
+-    *p = SPIN_LOCK_UNLOCKED;
+-}
+-
+-#endif
+-
 -#if defined(__powerpc__)
 -static inline int testandset (int *p)
 -{
@@ -205,6 +213,33 @@ Index: qemu/exec-all.h
 -                         : "cc","memory");
 -    return ret;
 -}
+-#elif defined(__hppa__)
+-
+-/* Because malloc only guarantees 8-byte alignment for malloc'd data,
+-   and GCC only guarantees 8-byte alignment for stack locals, we can't
+-   be assured of 16-byte alignment for atomic lock data even if we
+-   specify "__attribute ((aligned(16)))" in the type declaration.  So,
+-   we use a struct containing an array of four ints for the atomic lock
+-   type and dynamically select the 16-byte aligned int from the array
+-   for the semaphore.  */
+-#define __PA_LDCW_ALIGNMENT 16
+-static inline void *ldcw_align (void *p) {
+-    unsigned long a = (unsigned long)p;
+-    a = (a + __PA_LDCW_ALIGNMENT - 1) & ~(__PA_LDCW_ALIGNMENT - 1);
+-    return (void *)a;
+-}
+-
+-static inline int testandset (spinlock_t *p)
+-{
+-    unsigned int ret;
+-    p = ldcw_align(p);
+-    __asm__ __volatile__("ldcw 0(%1),%0"
+-                         : "=r" (ret)
+-                         : "r" (p)
+-                         : "memory" );
+-    return !ret;
+-}
+-
 -#elif defined(__ia64)
 -
 -#include <ia64intrin.h>
@@ -237,10 +272,6 @@ Index: qemu/exec-all.h
 -#error unimplemented CPU support
 -#endif
 -
--typedef int spinlock_t;
--
--#define SPIN_LOCK_UNLOCKED 0
--
 -#if defined(CONFIG_USER_ONLY)
 -static inline void spin_lock(spinlock_t *lock)
 -{
@@ -249,7 +280,7 @@ Index: qemu/exec-all.h
 -
 -static inline void spin_unlock(spinlock_t *lock)
 -{
--    *lock = 0;
+-    resetlock(lock);
 -}
 -
 -static inline int spin_trylock(spinlock_t *lock)
@@ -274,10 +305,10 @@ Index: qemu/exec-all.h
  
  extern spinlock_t tb_lock;
  
-Index: qemu/linux-user/arm/syscall.h
+Index: trunk/linux-user/arm/syscall.h
 ===================================================================
---- qemu.orig/linux-user/arm/syscall.h	2007-11-27 12:09:33.000000000 +0000
-+++ qemu/linux-user/arm/syscall.h	2008-04-09 23:05:55.000000000 +0100
+--- trunk.orig/linux-user/arm/syscall.h	2008-04-24 20:16:41.000000000 +0100
++++ trunk/linux-user/arm/syscall.h	2008-04-24 20:16:53.000000000 +0100
 @@ -28,7 +28,9 @@
  #define ARM_SYSCALL_BASE	0x900000
  #define ARM_THUMB_SYSCALL	0
@@ -289,11 +320,11 @@ Index: qemu/linux-user/arm/syscall.h
  
  #define ARM_NR_semihosting	  0x123456
  #define ARM_NR_thumb_semihosting  0xAB
-Index: qemu/linux-user/main.c
+Index: trunk/linux-user/main.c
 ===================================================================
---- qemu.orig/linux-user/main.c	2008-04-09 23:02:37.000000000 +0100
-+++ qemu/linux-user/main.c	2008-04-09 23:05:55.000000000 +0100
-@@ -364,6 +364,50 @@
+--- trunk.orig/linux-user/main.c	2008-04-24 20:16:47.000000000 +0100
++++ trunk/linux-user/main.c	2008-04-24 20:17:38.000000000 +0100
+@@ -365,6 +365,50 @@
      }
  }
  
@@ -325,7 +356,7 @@ Index: qemu/linux-user/main.c
 +        cpu_unlock();
 +        break;
 +    case 0xffff0fe0: /* __kernel_get_tls */
-+        env->regs[0] = env->cp15.c13_tls;
++        env->regs[0] = env->cp15.c13_tls2;
 +        break;
 +    default:
 +        return 1;
@@ -344,7 +375,7 @@ Index: qemu/linux-user/main.c
  void cpu_loop(CPUARMState *env)
  {
      int trapnr;
-@@ -474,10 +518,8 @@
+@@ -475,10 +519,8 @@
                      }
                  }
  
@@ -357,7 +388,7 @@ Index: qemu/linux-user/main.c
                      env->regs[0] = do_arm_semihosting (env);
                  } else if (n == 0 || n >= ARM_SYSCALL_BASE
                             || (env->thumb && n == ARM_THUMB_SYSCALL)) {
-@@ -488,14 +530,34 @@
+@@ -489,14 +531,34 @@
                          n -= ARM_SYSCALL_BASE;
                          env->eabi = 0;
                      }
@@ -400,7 +431,7 @@ Index: qemu/linux-user/main.c
                  } else {
                      goto error;
                  }
-@@ -534,6 +596,10 @@
+@@ -535,6 +597,10 @@
                    }
              }
              break;
@@ -411,7 +442,19 @@ Index: qemu/linux-user/main.c
          default:
          error:
              fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
-@@ -2402,6 +2468,10 @@
+@@ -1994,6 +2060,11 @@
+     int drop_ld_preload = 0, environ_count = 0;
+     char **target_environ, **wrk, **dst;
+ 
++    char *assume_kernel = getenv("QEMU_ASSUME_KERNEL");
++
++    if (assume_kernel)
++       setenv("LD_ASSUME_KERNEL", assume_kernel, 1);
++
+     if (argc <= 1)
+         usage();
+ 
+@@ -2403,6 +2474,10 @@
      ts->heap_base = info->brk;
      /* This will be filled in on the first SYS_HEAPINFO call.  */
      ts->heap_limit = 0;
@@ -422,10 +465,10 @@ Index: qemu/linux-user/main.c
  #endif
  
      if (gdbstub_port) {
-Index: qemu/linux-user/qemu.h
+Index: trunk/linux-user/qemu.h
 ===================================================================
---- qemu.orig/linux-user/qemu.h	2008-01-02 15:48:21.000000000 +0000
-+++ qemu/linux-user/qemu.h	2008-04-09 23:05:55.000000000 +0100
+--- trunk.orig/linux-user/qemu.h	2008-04-24 20:16:41.000000000 +0100
++++ trunk/linux-user/qemu.h	2008-04-24 20:16:53.000000000 +0100
 @@ -107,6 +107,9 @@
      uint32_t heap_base;
      uint32_t heap_limit;
@@ -436,11 +479,19 @@ Index: qemu/linux-user/qemu.h
      int used; /* non zero if used */
      struct image_info *info;
      uint8_t stack[0];
-Index: qemu/linux-user/syscall.c
+Index: trunk/linux-user/syscall.c
 ===================================================================
---- qemu.orig/linux-user/syscall.c	2008-04-09 23:02:38.000000000 +0100
-+++ qemu/linux-user/syscall.c	2008-04-09 23:05:55.000000000 +0100
-@@ -71,9 +71,18 @@
+--- trunk.orig/linux-user/syscall.c	2008-04-24 20:16:50.000000000 +0100
++++ trunk/linux-user/syscall.c	2008-04-24 20:19:52.000000000 +0100
+@@ -61,6 +61,7 @@
+ #define tchars host_tchars /* same as target */
+ #define ltchars host_ltchars /* same as target */
+ 
++#include <linux/futex.h>
+ #include <linux/termios.h>
+ #include <linux/unistd.h>
+ #include <linux/utsname.h>
+@@ -71,9 +72,18 @@
  #include <linux/kd.h>
  
  #include "qemu.h"
@@ -459,7 +510,14 @@ Index: qemu/linux-user/syscall.c
  #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
      || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS)
  /* 16 bit uid wrappers emulation */
-@@ -2702,9 +2711,19 @@
+@@ -2695,16 +2705,25 @@
+     return 0;
+ }
+ #endif
+-
+ #endif /* defined(TARGET_I386) */
+ 
+ /* this stack is the equivalent of the kernel stack associated with a
     thread/process */
  #define NEW_STACK_SIZE 8192
  
@@ -479,7 +537,7 @@ Index: qemu/linux-user/syscall.c
      cpu_loop(env);
      /* never exits */
      return 0;
-@@ -2712,13 +2731,22 @@
+@@ -2712,15 +2731,27 @@
  
  /* do_fork() Must return host values and target errnos (unlike most
     do_*() functions). */
@@ -492,18 +550,53 @@ Index: qemu/linux-user/syscall.c
      TaskState *ts;
      uint8_t *new_stack;
      CPUState *new_env;
- 
++#if defined(TARGET_I386)
++     uint64_t *new_gdt_table;
++#endif
 +#ifdef USE_NPTL
 +    unsigned int nptl_flags;
-+
+ 
 +    if (flags & CLONE_PARENT_SETTID)
 +        *parent_tidptr = gettid();
 +#endif
-+
      if (flags & CLONE_VM) {
          ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE);
++        if (!ts)
++          return -ENOMEM;
          memset(ts, 0, sizeof(TaskState));
-@@ -2784,16 +2812,67 @@
+         new_stack = ts->stack;
+         ts->used = 1;
+@@ -2732,6 +2763,29 @@
+ #if defined(TARGET_I386)
+         if (!newsp)
+             newsp = env->regs[R_ESP];
++       new_gdt_table = malloc(9 * 8);
++       if (!new_gdt_table) {
++               free(new_env);
++               return -ENOMEM;
++       }
++       /* Copy main GDT table from parent, but clear TLS entries */
++       memcpy(new_gdt_table, g2h(env->gdt.base), 6 * 8);
++       memset(&new_gdt_table[6], 0, 3 * 8); 
++       new_env->gdt.base = h2g(new_gdt_table);
++       if (flags & 0x00080000 /* CLONE_SETTLS */) {
++               ret = do_set_thread_area(new_env, new_env->regs[R_ESI]);
++               if (ret) {
++                       free(new_gdt_table);
++                       free(new_env);
++                       return ret;
++               }
++       }
++       cpu_x86_load_seg(env, R_CS, new_env->regs[R_CS]);
++       cpu_x86_load_seg(env, R_DS, new_env->regs[R_DS]);
++       cpu_x86_load_seg(env, R_ES, new_env->regs[R_ES]);
++       cpu_x86_load_seg(env, R_SS, new_env->regs[R_SS]);
++       cpu_x86_load_seg(env, R_FS, new_env->regs[R_FS]);
++       cpu_x86_load_seg(env, R_GS, new_env->regs[R_GS]);
+         new_env->regs[R_ESP] = newsp;
+         new_env->regs[R_EAX] = 0;
+ #elif defined(TARGET_ARM)
+@@ -2784,16 +2838,67 @@
  #error unsupported target CPU
  #endif
          new_env->opaque = ts;
@@ -572,7 +665,85 @@ Index: qemu/linux-user/syscall.c
      }
      return ret;
  }
-@@ -3118,7 +3197,7 @@
+@@ -3052,6 +3157,68 @@
+     unlock_user_struct(target_ts, target_addr, 1);
+ }
+ 
++static long do_futex(target_ulong uaddr, int op, uint32_t val,
++                    target_ulong utime, target_ulong uaddr2,
++                    uint32_t val3)
++{
++       struct timespec host_utime;
++       unsigned long val2 = utime;
++
++       if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) {
++               target_to_host_timespec(&host_utime, utime);
++               val2 = (unsigned long)&host_utime;
++       }
++ 
++#ifdef BSWAP_NEEDED
++       switch(op) {
++       case FUTEX_CMP_REQUEUE:
++               val3 = tswap32(val3);
++       case FUTEX_REQUEUE:
++               val2 = tswap32(val2);
++       case FUTEX_WAIT:
++       case FUTEX_WAKE:
++               val = tswap32(val);
++       case FUTEX_LOCK_PI: /* This one's icky, but comes out OK */
++       case FUTEX_UNLOCK_PI:
++               break;
++       default: 
++               gemu_log("qemu: Unsupported futex op %d\n", op);
++               return -ENOSYS;
++       } 
++#if 0 /* No, it's worse than this */
++       if (op == FUTEX_WAKE_OP) {
++               /* Need to munge the secondary operation (val3) */
++               val3 = tswap32(val3);
++               int op2 = (val3 >> 28) & 7;
++               int cmp = (val3 >> 24) & 15;
++               int oparg = (val3 << 8) >> 20;
++               int cmparg = (val3 << 20) >> 20;
++               int shift = val3 & (FUTEX_OP_OPARG_SHIFT << 28);
++
++               if (shift)
++                   oparg = (oparg & 7) + 24 - (oparg & 24);
++               else oparg = 
++               if (op2 == FUTEX_OP_ADD) {
++                       gemu_log("qemu: Unsupported wrong-endian FUTEX_OP_ADD\n");
++                       return -ENOSYS;
++               }
++               if (cmparg == FUTEX_OP_CMP_LT || cmparg == FUTEX_OP_CMP_GE ||
++                   cmparg == FUTEX_OP_CMP_LE || cmparg == FUTEX_OP_CMP_GT) {
++                       gemu_log("qemu: Unsupported wrong-endian futex cmparg %d\n", cmparg);
++                       return -ENOSYS;
++               }
++               val3 = shift | (op2<<28) | (cmp<<24) | (oparg<<12) | cmparg;
++       }
++#endif
++#endif
++       return syscall(__NR_futex, g2h(uaddr), op, val, val2, g2h(uaddr2), val3);
++}
++
++int do_set_tid_address(target_ulong tidptr)
++{
++       return syscall(__NR_set_tid_address, g2h(tidptr));
++}
++
+ /* do_syscall() should always have a single exit point at the end so
+    that actions, such as logging of syscall results, can be performed.
+    All errnos that do_syscall() returns must be -TARGET_<errcode>. */
+@@ -3076,7 +3243,7 @@
+         _mcleanup();
+ #endif
+         gdb_exit(cpu_env, arg1);
+-        /* XXX: should free thread stack and CPU env */
++        /* XXX: should free thread stack, GDT and CPU env */
+         _exit(arg1);
+         ret = 0; /* avoid warning */
+         break;
+@@ -3118,7 +3285,7 @@
          ret = do_brk(arg1);
          break;
      case TARGET_NR_fork:
@@ -581,7 +752,7 @@ Index: qemu/linux-user/syscall.c
          break;
  #ifdef TARGET_NR_waitpid
      case TARGET_NR_waitpid:
-@@ -4481,7 +4560,8 @@
+@@ -4482,7 +4649,8 @@
          ret = get_errno(fsync(arg1));
          break;
      case TARGET_NR_clone:
@@ -591,7 +762,7 @@ Index: qemu/linux-user/syscall.c
          break;
  #ifdef __NR_exit_group
          /* new thread calls */
-@@ -4928,7 +5008,8 @@
+@@ -4943,7 +5111,8 @@
  #endif
  #ifdef TARGET_NR_vfork
      case TARGET_NR_vfork:
@@ -601,11 +772,34 @@ Index: qemu/linux-user/syscall.c
          break;
  #endif
  #ifdef TARGET_NR_ugetrlimit
-Index: qemu/qemu_spinlock.h
+@@ -5521,6 +5690,9 @@
+ #elif defined(TARGET_I386) && defined(TARGET_ABI32)
+       ret = do_set_thread_area(cpu_env, arg1);
+       break;
++#elif TARGET_i386
++	  ret = get_errno(do_set_thread_area(cpu_env, arg1));
++	  break;
+ #else
+       goto unimplemented_nowarn;
+ #endif
+@@ -5538,6 +5710,12 @@
+         goto unimplemented_nowarn;
+ #endif
+ 
++#ifdef TARGET_NR_futex
++    case TARGET_NR_futex:
++       ret = get_errno(do_futex(arg1, arg2, arg3, arg4, arg5, arg6));
++       break;
++#endif
++
+ #ifdef TARGET_NR_clock_gettime
+     case TARGET_NR_clock_gettime:
+     {
+Index: trunk/qemu_spinlock.h
 ===================================================================
 --- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ qemu/qemu_spinlock.h	2008-04-09 23:05:55.000000000 +0100
-@@ -0,0 +1,181 @@
++++ trunk/qemu_spinlock.h	2008-04-24 20:16:53.000000000 +0100
+@@ -0,0 +1,250 @@
 +/*
 + * Atomic operation helper include
 + *
@@ -743,6 +937,33 @@ Index: qemu/qemu_spinlock.h
 +}
 +#endif
 +
++#ifdef __hppa__
++/* Because malloc only guarantees 8-byte alignment for malloc'd data,
++   and GCC only guarantees 8-byte alignment for stack locals, we can't
++   be assured of 16-byte alignment for atomic lock data even if we
++   specify "__attribute ((aligned(16)))" in the type declaration.  So,
++   we use a struct containing an array of four ints for the atomic lock
++   type and dynamically select the 16-byte aligned int from the array
++   for the semaphore.  */
++#define __PA_LDCW_ALIGNMENT 16
++static inline void *ldcw_align (void *p) {
++    unsigned long a = (unsigned long)p;
++    a = (a + __PA_LDCW_ALIGNMENT - 1) & ~(__PA_LDCW_ALIGNMENT - 1);
++    return (void *)a;
++}
++
++static inline int testandset (spinlock_t *p)
++{
++    unsigned int ret;
++    p = ldcw_align(p);
++    __asm__ __volatile__("ldcw 0(%1),%0"
++                         : "=r" (ret)
++                         : "r" (p)
++                         : "memory" );
++    return !ret;
++}
++#endif
++
 +#ifdef __ia64
 +#include <ia64intrin.h>
 +
@@ -752,10 +973,52 @@ Index: qemu/qemu_spinlock.h
 +}
 +#endif
 +
++#ifdef __mips__
++static inline int testandset (int *p)
++{
++    int ret;
++
++    __asm__ __volatile__ (
++	"	.set push		\n"
++	"	.set noat		\n"
++	"	.set mips2		\n"
++	"1:	li	$1, 1		\n"
++	"	ll	%0, %1		\n"
++	"	sc	$1, %1		\n"
++	"	beqz	$1, 1b		\n"
++	"	.set pop		"
++	: "=r" (ret), "+R" (*p)
++	:
++	: "memory");
++
++    return ret;
++}
++#endif
++
++#if defined(__hppa__)
++
++typedef int spinlock_t[4];
++
++#define SPIN_LOCK_UNLOCKED { 1, 1, 1, 1 }
++
++static inline void resetlock (spinlock_t *p)
++{
++    (*p)[0] = (*p)[1] = (*p)[2] = (*p)[3] = 1;
++}
++
++#else
++
 +typedef int spinlock_t;
 +
 +#define SPIN_LOCK_UNLOCKED 0
 +
++static inline void resetlock (spinlock_t *p)
++{
++    *p = SPIN_LOCK_UNLOCKED;
++}
++
++#endif
++
 +#if defined(CONFIG_USER_ONLY)
 +static inline void spin_lock(spinlock_t *lock)
 +{
@@ -764,7 +1027,7 @@ Index: qemu/qemu_spinlock.h
 +
 +static inline void spin_unlock(spinlock_t *lock)
 +{
-+    *lock = 0;
++    resetlock(lock);
 +}
 +
 +static inline int spin_trylock(spinlock_t *lock)
@@ -787,10 +1050,10 @@ Index: qemu/qemu_spinlock.h
 +#endif
 +
 +#endif
-Index: qemu/target-arm/cpu.h
+Index: trunk/target-arm/cpu.h
 ===================================================================
---- qemu.orig/target-arm/cpu.h	2007-11-27 12:09:57.000000000 +0000
-+++ qemu/target-arm/cpu.h	2008-04-09 23:05:55.000000000 +0100
+--- trunk.orig/target-arm/cpu.h	2008-04-24 20:16:41.000000000 +0100
++++ trunk/target-arm/cpu.h	2008-04-24 20:16:53.000000000 +0100
 @@ -38,6 +38,7 @@
  #define EXCP_FIQ             6
  #define EXCP_BKPT            7
@@ -799,7 +1062,7 @@ Index: qemu/target-arm/cpu.h
  
  #define ARMV7M_EXCP_RESET   1
  #define ARMV7M_EXCP_NMI     2
-@@ -222,6 +223,15 @@
+@@ -218,6 +219,15 @@
  void cpu_lock(void);
  void cpu_unlock(void);
  
@@ -815,36 +1078,19 @@ Index: qemu/target-arm/cpu.h
  #define CPSR_M (0x1f)
  #define CPSR_T (1 << 5)
  #define CPSR_F (1 << 6)
-Index: qemu/target-arm/op.c
-===================================================================
---- qemu.orig/target-arm/op.c	2008-04-09 22:40:01.000000000 +0100
-+++ qemu/target-arm/op.c	2008-04-09 23:05:55.000000000 +0100
-@@ -994,6 +994,12 @@
-     cpu_loop_exit();
- }
- 
-+void OPPROTO op_kernel_trap(void)
-+{
-+    env->exception_index = EXCP_KERNEL_TRAP;
-+    cpu_loop_exit();
-+}
-+
- /* VFP support.  We follow the convention used for VFP instrunctions:
-    Single precition routines have a "s" suffix, double precision a
-    "d" suffix.  */
-Index: qemu/target-arm/translate.c
+Index: trunk/target-arm/translate.c
 ===================================================================
---- qemu.orig/target-arm/translate.c	2008-04-09 22:40:01.000000000 +0100
-+++ qemu/target-arm/translate.c	2008-04-09 23:05:55.000000000 +0100
-@@ -7496,7 +7496,14 @@
-             gen_op_exception_exit();
+--- trunk.orig/target-arm/translate.c	2008-04-24 20:16:41.000000000 +0100
++++ trunk/target-arm/translate.c	2008-04-24 20:16:53.000000000 +0100
+@@ -8606,7 +8606,14 @@
+             gen_exception(EXCP_EXCEPTION_EXIT);
          }
  #endif
 -
 +#ifdef CONFIG_USER_ONLY
 +        /* Intercept jump to the magic kernel page.  */
 +        if (dc->pc > 0xffff0000) {
-+            gen_op_kernel_trap();
++            gen_exception(EXCP_KERNEL_TRAP);
 +            dc->is_jmp = DISAS_UPDATE;
 +            break;
 +        }
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/qemu-amd64-32b-mapping-0.9.0.patch b/meta/packages/qemu/qemu-0.9.1+svn/qemu-amd64-32b-mapping-0.9.0.patch
index c7f36d811..02f093abb 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/qemu-amd64-32b-mapping-0.9.0.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/qemu-amd64-32b-mapping-0.9.0.patch
@@ -2,10 +2,10 @@
  linux-user/mmap.c |    8 ++++++--
  1 file changed, 6 insertions(+), 2 deletions(-)
 
-Index: qemu/linux-user/mmap.c
+Index: trunk/linux-user/mmap.c
 ===================================================================
---- qemu.orig/linux-user/mmap.c	2007-12-03 15:40:25.000000000 +0000
-+++ qemu/linux-user/mmap.c	2007-12-03 16:37:21.000000000 +0000
+--- trunk.orig/linux-user/mmap.c	2008-04-24 20:15:37.000000000 +0100
++++ trunk/linux-user/mmap.c	2008-04-24 20:16:16.000000000 +0100
 @@ -29,6 +29,10 @@
  
  //#define DEBUG_MMAP
@@ -17,7 +17,7 @@ Index: qemu/linux-user/mmap.c
  /* NOTE: all the constants are the HOST ones, but addresses are target. */
  int target_mprotect(abi_ulong start, abi_ulong len, int prot)
  {
-@@ -251,7 +255,7 @@ abi_long target_mmap(abi_ulong start, ab
+@@ -251,7 +255,7 @@
             especially important if qemu_host_page_size >
             qemu_real_host_page_size */
          p = mmap(g2h(mmap_start),
@@ -26,7 +26,7 @@ Index: qemu/linux-user/mmap.c
          if (p == MAP_FAILED)
              return -1;
          /* update start so that it points to the file position at 'offset' */
-@@ -406,7 +410,7 @@ abi_long target_mremap(abi_ulong old_add
+@@ -406,7 +410,7 @@
      unsigned long host_addr;
  
      /* XXX: use 5 args syscall */
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/qemu-n800-support.patch b/meta/packages/qemu/qemu-0.9.1+svn/qemu-n800-support.patch
index b1b6649ef..1224fb4cb 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/qemu-n800-support.patch
+++ b/meta/packages/qemu/qemu-0.9.1+svn/qemu-n800-support.patch
@@ -1,13809 +1,2150 @@
-diff --git a/Makefile b/Makefile
-index c36a978..cb0cf7b 100644
---- a/Makefile
-+++ b/Makefile
-@@ -51,7 +51,8 @@ OBJS+=block.o
- 
- OBJS+=irq.o
- OBJS+=i2c.o smbus.o smbus_eeprom.o max7310.o max111x.o wm8750.o
--OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o
-+OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o twl92230.o
-+OBJS+=tmp105.o
- OBJS+=scsi-disk.o cdrom.o
- OBJS+=scsi-generic.o
- OBJS+=usb.o usb-hub.o usb-linux.o usb-hid.o usb-msd.o usb-wacom.o usb-serial.o
-diff --git a/Makefile.target b/Makefile.target
-index d1deda1..48f31bc 100644
---- a/Makefile.target
-+++ b/Makefile.target
-@@ -593,7 +593,9 @@ OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
- OBJS+= pflash_cfi01.o gumstix.o
- OBJS+= spitz.o ide.o serial.o nand.o ecc.o
- OBJS+= omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o
-+OBJS+= omap2.o omap_dss.o
- OBJS+= palm.o tsc210x.o
-+OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o
- OBJS+= mst_fpga.o mainstone.o
- CPPFLAGS += -DHAS_AUDIO
- endif
-diff --git a/console.h b/console.h
-index b8a5c6d..b45974e 100644
---- a/console.h
-+++ b/console.h
-@@ -32,6 +32,12 @@ void kbd_put_keycode(int keycode);
- void kbd_mouse_event(int dx, int dy, int dz, int buttons_state);
- int kbd_mouse_is_absolute(void);
- 
-+struct mouse_transform_info_s {
-+    int x;
-+    int y;
-+    int a[7];
-+};
-+
- void do_info_mice(void);
- void do_mouse_set(int index);
- 
-diff --git a/cpu-all.h b/cpu-all.h
-index 7a7e655..c7c9611 100644
---- a/cpu-all.h
-+++ b/cpu-all.h
-@@ -810,7 +810,7 @@ extern uint8_t *phys_ram_dirty;
- /* physical memory access */
- #define TLB_INVALID_MASK   (1 << 3)
- #define IO_MEM_SHIFT       4
--#define IO_MEM_NB_ENTRIES  (1 << (TARGET_PAGE_BITS  - IO_MEM_SHIFT))
-+#define IO_MEM_NB_ENTRIES  (16 << (TARGET_PAGE_BITS  - IO_MEM_SHIFT))
- 
- #define IO_MEM_RAM         (0 << IO_MEM_SHIFT) /* hardcoded offset */
- #define IO_MEM_ROM         (1 << IO_MEM_SHIFT) /* hardcoded offset */
-diff --git a/exec.c b/exec.c
-index e9a5918..c69f742 100644
---- a/exec.c
-+++ b/exec.c
-@@ -1658,7 +1658,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
-     {
-         if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
-             /* IO memory case */
--            address = vaddr | pd;
-+            address = vaddr | (pd & ~TARGET_PAGE_MASK);
-             addend = paddr;
-         } else {
-             /* standard memory */
-@@ -1692,7 +1692,9 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
-         } else {
-             te->addr_read = -1;
-         }
--        if (prot & PAGE_EXEC) {
-+        if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
-+            te->addr_code = pd;
-+        } else if (prot & PAGE_EXEC) {
-             te->addr_code = address;
-         } else {
-             te->addr_code = -1;
-@@ -2487,7 +2489,9 @@ int cpu_register_io_memory(int io_index,
-     if (io_index <= 0) {
-         if (io_mem_nb >= IO_MEM_NB_ENTRIES)
-             return -1;
--        io_index = io_mem_nb++;
-+        do io_index = io_mem_nb++;
-+        while (((io_index << IO_MEM_SHIFT) & ~TARGET_PAGE_MASK)
-+               <= IO_MEM_NOTDIRTY);
-     } else {
-         if (io_index >= IO_MEM_NB_ENTRIES)
-             return -1;
-diff --git a/hw/arm-misc.h b/hw/arm-misc.h
-index 7914ff1..a1e0061 100644
---- a/hw/arm-misc.h
-+++ b/hw/arm-misc.h
-@@ -21,10 +21,7 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
-                       const char *kernel_filename, const char *cpu_model);
- 
- /* arm_boot.c */
--
--void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
--                     const char *kernel_cmdline, const char *initrd_filename,
--                     int board_id, target_phys_addr_t loader_start);
-+void arm_load_kernel(CPUState *env, struct arm_boot_info *info);
- 
- /* armv7m_nvic.c */
- int system_clock_scale;
-diff --git a/hw/arm_boot.c b/hw/arm_boot.c
-index 8335e69..20b1512 100644
---- a/hw/arm_boot.c
-+++ b/hw/arm_boot.c
-@@ -47,21 +47,18 @@ static void main_cpu_reset(void *opaque)
-     CPUState *env = opaque;
- 
-     cpu_reset(env);
--    if (env->kernel_filename)
--        arm_load_kernel(env, env->ram_size, env->kernel_filename,
--                        env->kernel_cmdline, env->initrd_filename,
--                        env->board_id, env->loader_start);
-+    if (env->boot_info)
-+        arm_load_kernel(env, env->boot_info);
- 
-     /* TODO:  Reset secondary CPUs.  */
- }
- 
--static void set_kernel_args(uint32_t ram_size, int initrd_size,
--                            const char *kernel_cmdline,
--                            target_phys_addr_t loader_start)
-+static void set_kernel_args(struct arm_boot_info *info,
-+                int initrd_size, void *base)
- {
-     uint32_t *p;
- 
--    p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR);
-+    p = (uint32_t *)(base + KERNEL_ARGS_ADDR);
-     /* ATAG_CORE */
-     stl_raw(p++, 5);
-     stl_raw(p++, 0x54410001);
-@@ -69,46 +66,55 @@ static void set_kernel_args(uint32_t ram_size, int initrd_size,
-     stl_raw(p++, 0x1000);
-     stl_raw(p++, 0);
-     /* ATAG_MEM */
-+    /* TODO: multiple chips */
-     stl_raw(p++, 4);
-     stl_raw(p++, 0x54410002);
--    stl_raw(p++, ram_size);
--    stl_raw(p++, loader_start);
-+    stl_raw(p++, info->ram_size);
-+    stl_raw(p++, info->loader_start);
-     if (initrd_size) {
-         /* ATAG_INITRD2 */
-         stl_raw(p++, 4);
-         stl_raw(p++, 0x54420005);
--        stl_raw(p++, loader_start + INITRD_LOAD_ADDR);
-+        stl_raw(p++, info->loader_start + INITRD_LOAD_ADDR);
-         stl_raw(p++, initrd_size);
-     }
--    if (kernel_cmdline && *kernel_cmdline) {
-+    if (info->kernel_cmdline && *info->kernel_cmdline) {
-         /* ATAG_CMDLINE */
-         int cmdline_size;
- 
--        cmdline_size = strlen(kernel_cmdline);
--        memcpy (p + 2, kernel_cmdline, cmdline_size + 1);
-+        cmdline_size = strlen(info->kernel_cmdline);
-+        memcpy(p + 2, info->kernel_cmdline, cmdline_size + 1);
-         cmdline_size = (cmdline_size >> 2) + 1;
-         stl_raw(p++, cmdline_size + 2);
-         stl_raw(p++, 0x54410009);
-         p += cmdline_size;
-     }
-+    if (info->atag_board) {
-+        /* ATAG_BOARD */
-+        int atag_board_len;
-+
-+        atag_board_len = (info->atag_board(info, p + 2) + 3) >> 2;
-+        stl_raw(p++, 2 + atag_board_len);
-+        stl_raw(p++, 0x414f4d50);
-+        p += atag_board_len;
-+    }
-     /* ATAG_END */
-     stl_raw(p++, 0);
-     stl_raw(p++, 0);
- }
- 
--static void set_kernel_args_old(uint32_t ram_size, int initrd_size,
--                                const char *kernel_cmdline,
--                                target_phys_addr_t loader_start)
-+static void set_kernel_args_old(struct arm_boot_info *info,
-+                int initrd_size, void *base)
- {
-     uint32_t *p;
-     unsigned char *s;
- 
-     /* see linux/include/asm-arm/setup.h */
--    p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR);
-+    p = (uint32_t *)(base + KERNEL_ARGS_ADDR);
-     /* page_size */
-     stl_raw(p++, 4096);
-     /* nr_pages */
--    stl_raw(p++, ram_size / 4096);
-+    stl_raw(p++, info->ram_size / 4096);
-     /* ramdisk_size */
-     stl_raw(p++, 0);
- #define FLAG_READONLY	1
-@@ -142,7 +148,7 @@ static void set_kernel_args_old(uint32_t ram_size, int initrd_size,
-     stl_raw(p++, 0);
-     /* initrd_start */
-     if (initrd_size)
--        stl_raw(p++, loader_start + INITRD_LOAD_ADDR);
-+        stl_raw(p++, info->loader_start + INITRD_LOAD_ADDR);
-     else
-         stl_raw(p++, 0);
-     /* initrd_size */
-@@ -159,17 +165,15 @@ static void set_kernel_args_old(uint32_t ram_size, int initrd_size,
-     stl_raw(p++, 0);
-     /* zero unused fields */
-     memset(p, 0, 256 + 1024 -
--           (p - ((uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR))));
--    s = phys_ram_base + KERNEL_ARGS_ADDR + 256 + 1024;
--    if (kernel_cmdline)
--        strcpy (s, kernel_cmdline);
-+           (p - ((uint32_t *)(base + KERNEL_ARGS_ADDR))));
-+    s = base + KERNEL_ARGS_ADDR + 256 + 1024;
-+    if (info->kernel_cmdline)
-+        strcpy (s, info->kernel_cmdline);
-     else
-         stb_raw(s, 0);
- }
- 
--void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
--                     const char *kernel_cmdline, const char *initrd_filename,
--                     int board_id, target_phys_addr_t loader_start)
-+void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
- {
-     int kernel_size;
-     int initrd_size;
-@@ -177,36 +181,41 @@ void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
-     int is_linux = 0;
-     uint64_t elf_entry;
-     target_ulong entry;
-+    uint32_t pd;
-+    void *loader_phys;
- 
-     /* Load the kernel.  */
--    if (!kernel_filename) {
-+    if (!info->kernel_filename) {
-         fprintf(stderr, "Kernel image must be specified\n");
-         exit(1);
-     }
- 
--    if (!env->kernel_filename) {
--        env->ram_size = ram_size;
--        env->kernel_filename = kernel_filename;
--        env->kernel_cmdline = kernel_cmdline;
--        env->initrd_filename = initrd_filename;
--        env->board_id = board_id;
--        env->loader_start = loader_start;
-+    if (!env->boot_info) {
-+        if (info->nb_cpus == 0)
-+            info->nb_cpus = 1;
-+        env->boot_info = info;
-         qemu_register_reset(main_cpu_reset, env);
-     }
-+
-+    pd = cpu_get_physical_page_desc(info->loader_start);
-+    loader_phys = phys_ram_base + (pd & TARGET_PAGE_MASK) +
-+            (info->loader_start & ~TARGET_PAGE_MASK);
-+
-     /* Assume that raw images are linux kernels, and ELF images are not.  */
--    kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL);
-+    kernel_size = load_elf(info->kernel_filename, 0, &elf_entry, NULL, NULL);
-     entry = elf_entry;
-     if (kernel_size < 0) {
--        kernel_size = load_uboot(kernel_filename, &entry, &is_linux);
-+        kernel_size = load_uboot(info->kernel_filename, &entry, &is_linux);
-     }
-     if (kernel_size < 0) {
--        kernel_size = load_image(kernel_filename,
--                                 phys_ram_base + KERNEL_LOAD_ADDR);
--        entry = loader_start + KERNEL_LOAD_ADDR;
-+        kernel_size = load_image(info->kernel_filename,
-+                                 loader_phys + KERNEL_LOAD_ADDR);
-+        entry = info->loader_start + KERNEL_LOAD_ADDR;
-         is_linux = 1;
-     }
-     if (kernel_size < 0) {
--        fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
-+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
-+                info->kernel_filename);
-         exit(1);
-     }
-     if (!is_linux) {
-@@ -214,30 +223,29 @@ void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
-         env->regs[15] = entry & 0xfffffffe;
-         env->thumb = entry & 1;
-     } else {
--        if (initrd_filename) {
--            initrd_size = load_image(initrd_filename,
--                                     phys_ram_base + INITRD_LOAD_ADDR);
-+        if (info->initrd_filename) {
-+            initrd_size = load_image(info->initrd_filename,
-+                                     loader_phys + INITRD_LOAD_ADDR);
-             if (initrd_size < 0) {
-                 fprintf(stderr, "qemu: could not load initrd '%s'\n",
--                        initrd_filename);
-+                        info->initrd_filename);
-                 exit(1);
-             }
-         } else {
-             initrd_size = 0;
-         }
--        bootloader[1] |= board_id & 0xff;
--        bootloader[2] |= (board_id >> 8) & 0xff;
--        bootloader[5] = loader_start + KERNEL_ARGS_ADDR;
-+        bootloader[1] |= info->board_id & 0xff;
-+        bootloader[2] |= (info->board_id >> 8) & 0xff;
-+        bootloader[5] = info->loader_start + KERNEL_ARGS_ADDR;
-         bootloader[6] = entry;
-         for (n = 0; n < sizeof(bootloader) / 4; n++)
--            stl_raw(phys_ram_base + (n * 4), bootloader[n]);
--        for (n = 0; n < sizeof(smpboot) / 4; n++)
--            stl_raw(phys_ram_base + ram_size + (n * 4), smpboot[n]);
-+            stl_raw(loader_phys + (n * 4), bootloader[n]);
-+        if (info->nb_cpus > 1)
-+            for (n = 0; n < sizeof(smpboot) / 4; n++)
-+                stl_raw(loader_phys + info->ram_size + (n * 4), smpboot[n]);
-         if (old_param)
--            set_kernel_args_old(ram_size, initrd_size,
--                                kernel_cmdline, loader_start);
-+            set_kernel_args_old(info, initrd_size, loader_phys);
-         else
--            set_kernel_args(ram_size, initrd_size,
--                            kernel_cmdline, loader_start);
-+            set_kernel_args(info, initrd_size, loader_phys);
-     }
- }
-diff --git a/hw/blizzard.c b/hw/blizzard.c
-new file mode 100644
-index 0000000..9046b5d
---- /dev/null
-+++ b/hw/blizzard.c
-@@ -0,0 +1,1001 @@
-+/*
-+ * Epson S1D13744/S1D13745 (Blizzard/Hailstorm/Tornado) LCD/TV controller.
-+ *
-+ * Copyright (C) 2008 Nokia Corporation
-+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation; either version 2 of
-+ * the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-+ * MA 02111-1307 USA
-+ */
-+
-+#include "qemu-common.h"
-+#include "sysemu.h"
-+#include "console.h"
-+#include "devices.h"
-+#include "vga_int.h"
-+#include "pixel_ops.h"
-+
-+typedef void (*blizzard_fn_t)(uint8_t *, const uint8_t *, unsigned int);
-+
-+struct blizzard_s {
-+    uint8_t reg;
-+    uint32_t addr;
-+    int swallow;
-+
-+    int pll;
-+    int pll_range;
-+    int pll_ctrl;
-+    uint8_t pll_mode;
-+    uint8_t clksel;
-+    int memenable;
-+    int memrefresh;
-+    uint8_t timing[3];
-+    int priority;
-+
-+    uint8_t lcd_config;
-+    int x;
-+    int y;
-+    int skipx;
-+    int skipy;
-+    uint8_t hndp;
-+    uint8_t vndp;
-+    uint8_t hsync;
-+    uint8_t vsync;
-+    uint8_t pclk;
-+    uint8_t u;
-+    uint8_t v;
-+    uint8_t yrc[2];
-+    int ix[2];
-+    int iy[2];
-+    int ox[2];
-+    int oy[2];
-+
-+    int enable;
-+    int blank;
-+    int bpp;
-+    int invalidate;
-+    int mx[2];
-+    int my[2];
-+    uint8_t mode;
-+    uint8_t effect;
-+    uint8_t iformat;
-+    uint8_t source;
-+    DisplayState *state;
-+    blizzard_fn_t *line_fn_tab[2];
-+    void *fb;
-+
-+    uint8_t hssi_config[3];
-+    uint8_t tv_config;
-+    uint8_t tv_timing[4];
-+    uint8_t vbi;
-+    uint8_t tv_x;
-+    uint8_t tv_y;
-+    uint8_t tv_test;
-+    uint8_t tv_filter_config;
-+    uint8_t tv_filter_idx;
-+    uint8_t tv_filter_coeff[0x20];
-+    uint8_t border_r;
-+    uint8_t border_g;
-+    uint8_t border_b;
-+    uint8_t gamma_config;
-+    uint8_t gamma_idx;
-+    uint8_t gamma_lut[0x100];
-+    uint8_t matrix_ena;
-+    uint8_t matrix_coeff[0x12];
-+    uint8_t matrix_r;
-+    uint8_t matrix_g;
-+    uint8_t matrix_b;
-+    uint8_t pm;
-+    uint8_t status;
-+    uint8_t rgbgpio_dir;
-+    uint8_t rgbgpio;
-+    uint8_t gpio_dir;
-+    uint8_t gpio;
-+    uint8_t gpio_edge[2];
-+    uint8_t gpio_irq;
-+    uint8_t gpio_pdown;
-+
-+    struct {
-+        int x;
-+        int y;
-+        int dx;
-+        int dy;
-+        int len;
-+        int buflen;
-+        void *buf;
-+        void *data;
-+        uint16_t *ptr;
-+        int angle;
-+        int pitch;
-+        blizzard_fn_t line_fn;
-+    } data;
-+};
-+
-+/* Bytes(!) per pixel */
-+static const int blizzard_iformat_bpp[0x10] = {
-+    0,
-+    2,	/* RGB 5:6:5*/
-+    3,	/* RGB 6:6:6 mode 1 */
-+    3,	/* RGB 8:8:8 mode 1 */
-+    0, 0,
-+    4,	/* RGB 6:6:6 mode 2 */
-+    4,	/* RGB 8:8:8 mode 2 */
-+    0,	/* YUV 4:2:2 */
-+    0,	/* YUV 4:2:0 */
-+    0, 0, 0, 0, 0, 0,
-+};
-+
-+static inline void blizzard_rgb2yuv(int r, int g, int b,
-+                int *y, int *u, int *v)
-+{
-+    *y = 0x10 + ((0x838 * r + 0x1022 * g + 0x322 * b) >> 13);
-+    *u = 0x80 + ((0xe0e * b - 0x04c1 * r - 0x94e * g) >> 13);
-+    *v = 0x80 + ((0xe0e * r - 0x0bc7 * g - 0x247 * b) >> 13);
-+}
-+
-+static void blizzard_window(struct blizzard_s *s)
-+{
-+    uint8_t *src, *dst;
-+    int bypp[2];
-+    int bypl[3];
-+    int y;
-+    blizzard_fn_t fn = s->data.line_fn;
-+
-+    if (!fn)
-+        return;
-+    if (s->mx[0] > s->data.x)
-+        s->mx[0] = s->data.x;
-+    if (s->my[0] > s->data.y)
-+        s->my[0] = s->data.y;
-+    if (s->mx[1] < s->data.x + s->data.dx)
-+        s->mx[1] = s->data.x + s->data.dx;
-+    if (s->my[1] < s->data.y + s->data.dy)
-+        s->my[1] = s->data.y + s->data.dy;
-+
-+    bypp[0] = s->bpp;
-+    bypp[1] = (s->state->depth + 7) >> 3;
-+    bypl[0] = bypp[0] * s->data.pitch;
-+    bypl[1] = bypp[1] * s->x;
-+    bypl[2] = bypp[0] * s->data.dx;
-+
-+    src = s->data.data;
-+    dst = s->fb + bypl[1] * s->data.y + bypp[1] * s->data.x;
-+    for (y = s->data.dy; y > 0; y --, src += bypl[0], dst += bypl[1])
-+        fn(dst, src, bypl[2]);
-+}
-+
-+static int blizzard_transfer_setup(struct blizzard_s *s)
-+{
-+    if (s->source > 3 || !s->bpp ||
-+                    s->ix[1] < s->ix[0] || s->iy[1] < s->iy[0])
-+        return 0;
-+
-+    s->data.angle = s->effect & 3;
-+    s->data.line_fn = s->line_fn_tab[!!s->data.angle][s->iformat];
-+    s->data.x = s->ix[0];
-+    s->data.y = s->iy[0];
-+    s->data.dx = s->ix[1] - s->ix[0] + 1;
-+    s->data.dy = s->iy[1] - s->iy[0] + 1;
-+    s->data.len = s->bpp * s->data.dx * s->data.dy;
-+    s->data.pitch = s->data.dx;
-+    if (s->data.len > s->data.buflen) {
-+        s->data.buf = realloc(s->data.buf, s->data.len);
-+        s->data.buflen = s->data.len;
-+    }
-+    s->data.ptr = s->data.buf;
-+    s->data.data = s->data.buf;
-+    s->data.len /= 2;
-+    return 1;
-+}
-+
-+static void blizzard_reset(struct blizzard_s *s)
-+{
-+    s->reg = 0;
-+    s->swallow = 0;
-+
-+    s->pll = 9;
-+    s->pll_range = 1;
-+    s->pll_ctrl = 0x14;
-+    s->pll_mode = 0x32;
-+    s->clksel = 0x00;
-+    s->memenable = 0;
-+    s->memrefresh = 0x25c;
-+    s->timing[0] = 0x3f;
-+    s->timing[1] = 0x13;
-+    s->timing[2] = 0x21;
-+    s->priority = 0;
-+
-+    s->lcd_config = 0x74;
-+    s->x = 8;
-+    s->y = 1;
-+    s->skipx = 0;
-+    s->skipy = 0;
-+    s->hndp = 3;
-+    s->vndp = 2;
-+    s->hsync = 1;
-+    s->vsync = 1;
-+    s->pclk = 0x80;
-+
-+    s->ix[0] = 0;
-+    s->ix[1] = 0;
-+    s->iy[0] = 0;
-+    s->iy[1] = 0;
-+    s->ox[0] = 0;
-+    s->ox[1] = 0;
-+    s->oy[0] = 0;
-+    s->oy[1] = 0;
-+
-+    s->yrc[0] = 0x00;
-+    s->yrc[1] = 0x30;
-+    s->u = 0;
-+    s->v = 0;
-+
-+    s->iformat = 3;
-+    s->source = 0;
-+    s->bpp = blizzard_iformat_bpp[s->iformat];
-+
-+    s->hssi_config[0] = 0x00;
-+    s->hssi_config[1] = 0x00;
-+    s->hssi_config[2] = 0x01;
-+    s->tv_config = 0x00;
-+    s->tv_timing[0] = 0x00;
-+    s->tv_timing[1] = 0x00;
-+    s->tv_timing[2] = 0x00;
-+    s->tv_timing[3] = 0x00;
-+    s->vbi = 0x10;
-+    s->tv_x = 0x14;
-+    s->tv_y = 0x03;
-+    s->tv_test = 0x00;
-+    s->tv_filter_config = 0x80;
-+    s->tv_filter_idx = 0x00;
-+    s->border_r = 0x10;
-+    s->border_g = 0x80;
-+    s->border_b = 0x80;
-+    s->gamma_config = 0x00;
-+    s->gamma_idx = 0x00;
-+    s->matrix_ena = 0x00;
-+    memset(&s->matrix_coeff, 0, sizeof(s->matrix_coeff));
-+    s->matrix_r = 0x00;
-+    s->matrix_g = 0x00;
-+    s->matrix_b = 0x00;
-+    s->pm = 0x02;
-+    s->status = 0x00;
-+    s->rgbgpio_dir = 0x00;
-+    s->gpio_dir = 0x00;
-+    s->gpio_edge[0] = 0x00;
-+    s->gpio_edge[1] = 0x00;
-+    s->gpio_irq = 0x00;
-+    s->gpio_pdown = 0xff;
-+}
-+
-+static inline void blizzard_invalidate_display(void *opaque) {
-+    struct blizzard_s *s = (struct blizzard_s *) opaque;
-+
-+    s->invalidate = 1;
-+}
-+
-+static uint16_t blizzard_reg_read(void *opaque, uint8_t reg)
-+{
-+    struct blizzard_s *s = (struct blizzard_s *) opaque;
-+
-+    switch (reg) {
-+    case 0x00:	/* Revision Code */
-+        return 0xa5;
-+
-+    case 0x02:	/* Configuration Readback */
-+        return 0x83;	/* Macrovision OK, CNF[2:0] = 3 */
-+
-+    case 0x04:	/* PLL M-Divider */
-+        return (s->pll - 1) | (1 << 7);
-+    case 0x06:	/* PLL Lock Range Control */
-+        return s->pll_range;
-+    case 0x08:	/* PLL Lock Synthesis Control 0 */
-+        return s->pll_ctrl & 0xff;
-+    case 0x0a:	/* PLL Lock Synthesis Control 1 */
-+        return s->pll_ctrl >> 8;
-+    case 0x0c:	/* PLL Mode Control 0 */
-+        return s->pll_mode;
-+
-+    case 0x0e:	/* Clock-Source Select */
-+        return s->clksel;
-+
-+    case 0x10:	/* Memory Controller Activate */
-+    case 0x14:	/* Memory Controller Bank 0 Status Flag */
-+        return s->memenable;
-+
-+    case 0x18:	/* Auto-Refresh Interval Setting 0 */
-+        return s->memrefresh & 0xff;
-+    case 0x1a:	/* Auto-Refresh Interval Setting 1 */
-+        return s->memrefresh >> 8;
-+
-+    case 0x1c:	/* Power-On Sequence Timing Control */
-+        return s->timing[0];
-+    case 0x1e:	/* Timing Control 0 */
-+        return s->timing[1];
-+    case 0x20:	/* Timing Control 1 */
-+        return s->timing[2];
-+
-+    case 0x24:	/* Arbitration Priority Control */
-+        return s->priority;
-+
-+    case 0x28:	/* LCD Panel Configuration */
-+        return s->lcd_config;
-+
-+    case 0x2a:	/* LCD Horizontal Display Width */
-+        return s->x >> 3;
-+    case 0x2c:	/* LCD Horizontal Non-display Period */
-+        return s->hndp;
-+    case 0x2e:	/* LCD Vertical Display Height 0 */
-+        return s->y & 0xff;
-+    case 0x30:	/* LCD Vertical Display Height 1 */
-+        return s->y >> 8;
-+    case 0x32:	/* LCD Vertical Non-display Period */
-+        return s->vndp;
-+    case 0x34:	/* LCD HS Pulse-width */
-+        return s->hsync;
-+    case 0x36:	/* LCd HS Pulse Start Position */
-+        return s->skipx >> 3;
-+    case 0x38:	/* LCD VS Pulse-width */
-+        return s->vsync;
-+    case 0x3a:	/* LCD VS Pulse Start Position */
-+        return s->skipy;
-+
-+    case 0x3c:	/* PCLK Polarity */
-+        return s->pclk;
-+
-+    case 0x3e:	/* High-speed Serial Interface Tx Configuration Port 0 */
-+        return s->hssi_config[0];
-+    case 0x40:	/* High-speed Serial Interface Tx Configuration Port 1 */
-+        return s->hssi_config[1];
-+    case 0x42:	/* High-speed Serial Interface Tx Mode */
-+        return s->hssi_config[2];
-+    case 0x44:	/* TV Display Configuration */
-+        return s->tv_config;
-+    case 0x46 ... 0x4c:	/* TV Vertical Blanking Interval Data bits */
-+        return s->tv_timing[(reg - 0x46) >> 1];
-+    case 0x4e:	/* VBI: Closed Caption / XDS Control / Status */
-+        return s->vbi;
-+    case 0x50:	/* TV Horizontal Start Position */
-+        return s->tv_x;
-+    case 0x52:	/* TV Vertical Start Position */
-+        return s->tv_y;
-+    case 0x54:	/* TV Test Pattern Setting */
-+        return s->tv_test;
-+    case 0x56:	/* TV Filter Setting */
-+        return s->tv_filter_config;
-+    case 0x58:	/* TV Filter Coefficient Index */
-+        return s->tv_filter_idx;
-+    case 0x5a:	/* TV Filter Coefficient Data */
-+        if (s->tv_filter_idx < 0x20)
-+            return s->tv_filter_coeff[s->tv_filter_idx ++];
-+        return 0;
-+
-+    case 0x60:	/* Input YUV/RGB Translate Mode 0 */
-+        return s->yrc[0];
-+    case 0x62:	/* Input YUV/RGB Translate Mode 1 */
-+        return s->yrc[1];
-+    case 0x64:	/* U Data Fix */
-+        return s->u;
-+    case 0x66:	/* V Data Fix */
-+        return s->v;
-+
-+    case 0x68:	/* Display Mode */
-+        return s->mode;
-+
-+    case 0x6a:	/* Special Effects */
-+        return s->effect;
-+
-+    case 0x6c:	/* Input Window X Start Position 0 */
-+        return s->ix[0] & 0xff;
-+    case 0x6e:	/* Input Window X Start Position 1 */
-+        return s->ix[0] >> 3;
-+    case 0x70:	/* Input Window Y Start Position 0 */
-+        return s->ix[0] & 0xff;
-+    case 0x72:	/* Input Window Y Start Position 1 */
-+        return s->ix[0] >> 3;
-+    case 0x74:	/* Input Window X End Position 0 */
-+        return s->ix[1] & 0xff;
-+    case 0x76:	/* Input Window X End Position 1 */
-+        return s->ix[1] >> 3;
-+    case 0x78:	/* Input Window Y End Position 0 */
-+        return s->ix[1] & 0xff;
-+    case 0x7a:	/* Input Window Y End Position 1 */
-+        return s->ix[1] >> 3;
-+    case 0x7c:	/* Output Window X Start Position 0 */
-+        return s->ox[0] & 0xff;
-+    case 0x7e:	/* Output Window X Start Position 1 */
-+        return s->ox[0] >> 3;
-+    case 0x80:	/* Output Window Y Start Position 0 */
-+        return s->oy[0] & 0xff;
-+    case 0x82:	/* Output Window Y Start Position 1 */
-+        return s->oy[0] >> 3;
-+    case 0x84:	/* Output Window X End Position 0 */
-+        return s->ox[1] & 0xff;
-+    case 0x86:	/* Output Window X End Position 1 */
-+        return s->ox[1] >> 3;
-+    case 0x88:	/* Output Window Y End Position 0 */
-+        return s->oy[1] & 0xff;
-+    case 0x8a:	/* Output Window Y End Position 1 */
-+        return s->oy[1] >> 3;
-+
-+    case 0x8c:	/* Input Data Format */
-+        return s->iformat;
-+    case 0x8e:	/* Data Source Select */
-+        return s->source;
-+    case 0x90:	/* Display Memory Data Port */
-+        return 0;
-+
-+    case 0xa8:	/* Border Color 0 */
-+        return s->border_r;
-+    case 0xaa:	/* Border Color 1 */
-+        return s->border_g;
-+    case 0xac:	/* Border Color 2 */
-+        return s->border_b;
-+
-+    case 0xb4:	/* Gamma Correction Enable */
-+        return s->gamma_config;
-+    case 0xb6:	/* Gamma Correction Table Index */
-+        return s->gamma_idx;
-+    case 0xb8:	/* Gamma Correction Table Data */
-+        return s->gamma_lut[s->gamma_idx ++];
-+
-+    case 0xba:	/* 3x3 Matrix Enable */
-+        return s->matrix_ena;
-+    case 0xbc ... 0xde:	/* Coefficient Registers */
-+        return s->matrix_coeff[(reg - 0xbc) >> 1];
-+    case 0xe0:	/* 3x3 Matrix Red Offset */
-+        return s->matrix_r;
-+    case 0xe2:	/* 3x3 Matrix Green Offset */
-+        return s->matrix_g;
-+    case 0xe4:	/* 3x3 Matrix Blue Offset */
-+        return s->matrix_b;
-+
-+    case 0xe6:	/* Power-save */
-+        return s->pm;
-+    case 0xe8:	/* Non-display Period Control / Status */
-+        return s->status | (1 << 5);
-+    case 0xea:	/* RGB Interface Control */
-+        return s->rgbgpio_dir;
-+    case 0xec:	/* RGB Interface Status */
-+        return s->rgbgpio;
-+    case 0xee:	/* General-purpose IO Pins Configuration */
-+        return s->gpio_dir;
-+    case 0xf0:	/* General-purpose IO Pins Status / Control */
-+        return s->gpio;
-+    case 0xf2:	/* GPIO Positive Edge Interrupt Trigger */
-+        return s->gpio_edge[0];
-+    case 0xf4:	/* GPIO Negative Edge Interrupt Trigger */
-+        return s->gpio_edge[1];
-+    case 0xf6:	/* GPIO Interrupt Status */
-+        return s->gpio_irq;
-+    case 0xf8:	/* GPIO Pull-down Control */
-+        return s->gpio_pdown;
-+
-+    default:
-+        fprintf(stderr, "%s: unknown register %02x\n", __FUNCTION__, reg);
-+        return 0;
-+    }
-+}
-+
-+static void blizzard_reg_write(void *opaque, uint8_t reg, uint16_t value)
-+{
-+    struct blizzard_s *s = (struct blizzard_s *) opaque;
-+
-+    switch (reg) {
-+    case 0x04:	/* PLL M-Divider */
-+        s->pll = (value & 0x3f) + 1;
-+        break;
-+    case 0x06:	/* PLL Lock Range Control */
-+        s->pll_range = value & 3;
-+        break;
-+    case 0x08:	/* PLL Lock Synthesis Control 0 */
-+        s->pll_ctrl &= 0xf00;
-+        s->pll_ctrl |= (value << 0) & 0x0ff;
-+        break;
-+    case 0x0a:	/* PLL Lock Synthesis Control 1 */
-+        s->pll_ctrl &= 0x0ff;
-+        s->pll_ctrl |= (value << 8) & 0xf00;
-+        break;
-+    case 0x0c:	/* PLL Mode Control 0 */
-+        s->pll_mode = value & 0x77;
-+        if ((value & 3) == 0 || (value & 3) == 3)
-+            fprintf(stderr, "%s: wrong PLL Control bits (%i)\n",
-+                    __FUNCTION__, value & 3);
-+        break;
-+
-+    case 0x0e:	/* Clock-Source Select */
-+        s->clksel = value & 0xff;
-+        break;
-+
-+    case 0x10:	/* Memory Controller Activate */
-+        s->memenable = value & 1;
-+        break;
-+    case 0x14:	/* Memory Controller Bank 0 Status Flag */
-+        break;
-+
-+    case 0x18:	/* Auto-Refresh Interval Setting 0 */
-+        s->memrefresh &= 0xf00;
-+        s->memrefresh |= (value << 0) & 0x0ff;
-+        break;
-+    case 0x1a:	/* Auto-Refresh Interval Setting 1 */
-+        s->memrefresh &= 0x0ff;
-+        s->memrefresh |= (value << 8) & 0xf00;
-+        break;
-+
-+    case 0x1c:	/* Power-On Sequence Timing Control */
-+        s->timing[0] = value & 0x7f;
-+        break;
-+    case 0x1e:	/* Timing Control 0 */
-+        s->timing[1] = value & 0x17;
-+        break;
-+    case 0x20:	/* Timing Control 1 */
-+        s->timing[2] = value & 0x35;
-+        break;
-+
-+    case 0x24:	/* Arbitration Priority Control */
-+        s->priority = value & 1;
-+        break;
-+
-+    case 0x28:	/* LCD Panel Configuration */
-+        s->lcd_config = value & 0xff;
-+        if (value & (1 << 7))
-+            fprintf(stderr, "%s: data swap not supported!\n", __FUNCTION__);
-+        break;
-+
-+    case 0x2a:	/* LCD Horizontal Display Width */
-+        s->x = value << 3;
-+        break;
-+    case 0x2c:	/* LCD Horizontal Non-display Period */
-+        s->hndp = value & 0xff;
-+        break;
-+    case 0x2e:	/* LCD Vertical Display Height 0 */
-+        s->y &= 0x300;
-+        s->y |= (value << 0) & 0x0ff;
-+        break;
-+    case 0x30:	/* LCD Vertical Display Height 1 */
-+        s->y &= 0x0ff;
-+        s->y |= (value << 8) & 0x300;
-+        break;
-+    case 0x32:	/* LCD Vertical Non-display Period */
-+        s->vndp = value & 0xff;
-+        break;
-+    case 0x34:	/* LCD HS Pulse-width */
-+        s->hsync = value & 0xff;
-+        break;
-+    case 0x36:	/* LCD HS Pulse Start Position */
-+        s->skipx = value & 0xff;
-+        break;
-+    case 0x38:	/* LCD VS Pulse-width */
-+        s->vsync = value & 0xbf;
-+        break;
-+    case 0x3a:	/* LCD VS Pulse Start Position */
-+        s->skipy = value & 0xff;
-+        break;
-+
-+    case 0x3c:	/* PCLK Polarity */
-+        s->pclk = value & 0x82;
-+        /* Affects calculation of s->hndp, s->hsync and s->skipx.  */
-+        break;
-+
-+    case 0x3e:	/* High-speed Serial Interface Tx Configuration Port 0 */
-+        s->hssi_config[0] = value;
-+        break;
-+    case 0x40:	/* High-speed Serial Interface Tx Configuration Port 1 */
-+        s->hssi_config[1] = value;
-+        if (((value >> 4) & 3) == 3)
-+            fprintf(stderr, "%s: Illegal active-data-links value\n",
-+                            __FUNCTION__);
-+        break;
-+    case 0x42:	/* High-speed Serial Interface Tx Mode */
-+        s->hssi_config[2] = value & 0xbd;
-+        break;
-+
-+    case 0x44:	/* TV Display Configuration */
-+        s->tv_config = value & 0xfe;
-+        break;
-+    case 0x46 ... 0x4c:	/* TV Vertical Blanking Interval Data bits 0 */
-+        s->tv_timing[(reg - 0x46) >> 1] = value;
-+        break;
-+    case 0x4e:	/* VBI: Closed Caption / XDS Control / Status */
-+        s->vbi = value;
-+        break;
-+    case 0x50:	/* TV Horizontal Start Position */
-+        s->tv_x = value;
-+        break;
-+    case 0x52:	/* TV Vertical Start Position */
-+        s->tv_y = value & 0x7f;
-+        break;
-+    case 0x54:	/* TV Test Pattern Setting */
-+        s->tv_test = value;
-+        break;
-+    case 0x56:	/* TV Filter Setting */
-+        s->tv_filter_config = value & 0xbf;
-+        break;
-+    case 0x58:	/* TV Filter Coefficient Index */
-+        s->tv_filter_idx = value & 0x1f;
-+        break;
-+    case 0x5a:	/* TV Filter Coefficient Data */
-+        if (s->tv_filter_idx < 0x20)
-+            s->tv_filter_coeff[s->tv_filter_idx ++] = value;
-+        break;
-+
-+    case 0x60:	/* Input YUV/RGB Translate Mode 0 */
-+        s->yrc[0] = value & 0xb0;
-+        break;
-+    case 0x62:	/* Input YUV/RGB Translate Mode 1 */
-+        s->yrc[1] = value & 0x30;
-+        break;
-+    case 0x64:	/* U Data Fix */
-+        s->u = value & 0xff;
-+        break;
-+    case 0x66:	/* V Data Fix */
-+        s->v = value & 0xff;
-+        break;
-+
-+    case 0x68:	/* Display Mode */
-+        if ((s->mode ^ value) & 3)
-+            s->invalidate = 1;
-+        s->mode = value & 0xb7;
-+        s->enable = value & 1;
-+        s->blank = (value >> 1) & 1;
-+        if (value & (1 << 4))
-+            fprintf(stderr, "%s: Macrovision enable attempt!\n", __FUNCTION__);
-+        break;
-+
-+    case 0x6a:	/* Special Effects */
-+        s->effect = value & 0xfb;
-+        break;
-+
-+    case 0x6c:	/* Input Window X Start Position 0 */
-+        s->ix[0] &= 0x300;
-+        s->ix[0] |= (value << 0) & 0x0ff;
-+        break;
-+    case 0x6e:	/* Input Window X Start Position 1 */
-+        s->ix[0] &= 0x0ff;
-+        s->ix[0] |= (value << 8) & 0x300;
-+        break;
-+    case 0x70:	/* Input Window Y Start Position 0 */
-+        s->iy[0] &= 0x300;
-+        s->iy[0] |= (value << 0) & 0x0ff;
-+        break;
-+    case 0x72:	/* Input Window Y Start Position 1 */
-+        s->iy[0] &= 0x0ff;
-+        s->iy[0] |= (value << 8) & 0x300;
-+        break;
-+    case 0x74:	/* Input Window X End Position 0 */
-+        s->ix[1] &= 0x300;
-+        s->ix[1] |= (value << 0) & 0x0ff;
-+        break;
-+    case 0x76:	/* Input Window X End Position 1 */
-+        s->ix[1] &= 0x0ff;
-+        s->ix[1] |= (value << 8) & 0x300;
-+        break;
-+    case 0x78:	/* Input Window Y End Position 0 */
-+        s->iy[1] &= 0x300;
-+        s->iy[1] |= (value << 0) & 0x0ff;
-+        break;
-+    case 0x7a:	/* Input Window Y End Position 1 */
-+        s->iy[1] &= 0x0ff;
-+        s->iy[1] |= (value << 8) & 0x300;
-+        break;
-+    case 0x7c:	/* Output Window X Start Position 0 */
-+        s->ox[0] &= 0x300;
-+        s->ox[0] |= (value << 0) & 0x0ff;
-+        break;
-+    case 0x7e:	/* Output Window X Start Position 1 */
-+        s->ox[0] &= 0x0ff;
-+        s->ox[0] |= (value << 8) & 0x300;
-+        break;
-+    case 0x80:	/* Output Window Y Start Position 0 */
-+        s->oy[0] &= 0x300;
-+        s->oy[0] |= (value << 0) & 0x0ff;
-+        break;
-+    case 0x82:	/* Output Window Y Start Position 1 */
-+        s->oy[0] &= 0x0ff;
-+        s->oy[0] |= (value << 8) & 0x300;
-+        break;
-+    case 0x84:	/* Output Window X End Position 0 */
-+        s->ox[1] &= 0x300;
-+        s->ox[1] |= (value << 0) & 0x0ff;
-+        break;
-+    case 0x86:	/* Output Window X End Position 1 */
-+        s->ox[1] &= 0x0ff;
-+        s->ox[1] |= (value << 8) & 0x300;
-+        break;
-+    case 0x88:	/* Output Window Y End Position 0 */
-+        s->oy[1] &= 0x300;
-+        s->oy[1] |= (value << 0) & 0x0ff;
-+        break;
-+    case 0x8a:	/* Output Window Y End Position 1 */
-+        s->oy[1] &= 0x0ff;
-+        s->oy[1] |= (value << 8) & 0x300;
-+        break;
-+
-+    case 0x8c:	/* Input Data Format */
-+        s->iformat = value & 0xf;
-+        s->bpp = blizzard_iformat_bpp[s->iformat];
-+        if (!s->bpp)
-+            fprintf(stderr, "%s: Illegal or unsupported input format %x\n",
-+                            __FUNCTION__, s->iformat);
-+        break;
-+    case 0x8e:	/* Data Source Select */
-+        s->source = value & 7;
-+        /* Currently all windows will be "destructive overlays".  */
-+        if ((!(s->effect & (1 << 3)) && (s->ix[0] != s->ox[0] ||
-+                                        s->iy[0] != s->oy[0] ||
-+                                        s->ix[1] != s->ox[1] ||
-+                                        s->iy[1] != s->oy[1])) ||
-+                        !((s->ix[1] - s->ix[0]) & (s->iy[1] - s->iy[0]) &
-+                          (s->ox[1] - s->ox[0]) & (s->oy[1] - s->oy[0]) & 1))
-+            fprintf(stderr, "%s: Illegal input/output window positions\n",
-+                            __FUNCTION__);
-+
-+        blizzard_transfer_setup(s);
-+        break;
-+
-+    case 0x90:	/* Display Memory Data Port */
-+        if (!s->data.len && !blizzard_transfer_setup(s))
-+            break;
-+
-+        *s->data.ptr ++ = value;
-+        if (-- s->data.len == 0)
-+            blizzard_window(s);
-+        break;
-+
-+    case 0xa8:	/* Border Color 0 */
-+        s->border_r = value;
-+        break;
-+    case 0xaa:	/* Border Color 1 */
-+        s->border_g = value;
-+        break;
-+    case 0xac:	/* Border Color 2 */
-+        s->border_b = value;
-+        break;
-+
-+    case 0xb4:	/* Gamma Correction Enable */
-+        s->gamma_config = value & 0x87;
-+        break;
-+    case 0xb6:	/* Gamma Correction Table Index */
-+        s->gamma_idx = value;
-+        break;
-+    case 0xb8:	/* Gamma Correction Table Data */
-+        s->gamma_lut[s->gamma_idx ++] = value;
-+        break;
-+
-+    case 0xba:	/* 3x3 Matrix Enable */
-+        s->matrix_ena = value & 1;
-+        break;
-+    case 0xbc ... 0xde:	/* Coefficient Registers */
-+        s->matrix_coeff[(reg - 0xbc) >> 1] = value & ((reg & 2) ? 0x80 : 0xff);
-+        break;
-+    case 0xe0:	/* 3x3 Matrix Red Offset */
-+        s->matrix_r = value;
-+        break;
-+    case 0xe2:	/* 3x3 Matrix Green Offset */
-+        s->matrix_g = value;
-+        break;
-+    case 0xe4:	/* 3x3 Matrix Blue Offset */
-+        s->matrix_b = value;
-+        break;
-+
-+    case 0xe6:	/* Power-save */
-+        s->pm = value & 0x83;
-+        if (value & s->mode & 1)
-+            fprintf(stderr, "%s: The display must be disabled before entering "
-+                            "Standby Mode\n", __FUNCTION__);
-+        break;
-+    case 0xe8:	/* Non-display Period Control / Status */
-+        s->status = value & 0x1b;
-+        break;
-+    case 0xea:	/* RGB Interface Control */
-+        s->rgbgpio_dir = value & 0x8f;
-+        break;
-+    case 0xec:	/* RGB Interface Status */
-+        s->rgbgpio = value & 0xcf;
-+        break;
-+    case 0xee:	/* General-purpose IO Pins Configuration */
-+        s->gpio_dir = value;
-+        break;
-+    case 0xf0:	/* General-purpose IO Pins Status / Control */
-+        s->gpio = value;
-+        break;
-+    case 0xf2:	/* GPIO Positive Edge Interrupt Trigger */
-+        s->gpio_edge[0] = value;
-+        break;
-+    case 0xf4:	/* GPIO Negative Edge Interrupt Trigger */
-+        s->gpio_edge[1] = value;
-+        break;
-+    case 0xf6:	/* GPIO Interrupt Status */
-+        s->gpio_irq &= value;
-+        break;
-+    case 0xf8:	/* GPIO Pull-down Control */
-+        s->gpio_pdown = value;
-+        break;
-+
-+    default:
-+        fprintf(stderr, "%s: unknown register %02x\n", __FUNCTION__, reg);
-+        break;
-+    }
-+}
-+
-+uint16_t s1d13745_read(void *opaque, int dc)
-+{
-+    struct blizzard_s *s = (struct blizzard_s *) opaque;
-+    uint16_t value = blizzard_reg_read(s, s->reg);
-+
-+    if (s->swallow -- > 0)
-+        return 0;
-+    if (dc)
-+        s->reg ++;
-+
-+    return value;
-+}
-+
-+void s1d13745_write(void *opaque, int dc, uint16_t value)
-+{
-+    struct blizzard_s *s = (struct blizzard_s *) opaque;
-+
-+    if (s->swallow -- > 0)
-+        return;
-+    if (dc) {
-+        blizzard_reg_write(s, s->reg, value);
-+
-+        if (s->reg != 0x90 && s->reg != 0x5a && s->reg != 0xb8)
-+            s->reg += 2;
-+    } else
-+        s->reg = value & 0xff;
-+}
-+
-+void s1d13745_write_block(void *opaque, int dc,
-+                void *buf, size_t len, int pitch)
-+{
-+    struct blizzard_s *s = (struct blizzard_s *) opaque;
-+
-+    while (len > 0) {
-+        if (s->reg == 0x90 && dc &&
-+                        (s->data.len || blizzard_transfer_setup(s)) &&
-+                        len >= (s->data.len << 1)) {
-+            len -= s->data.len << 1;
-+            s->data.len = 0;
-+            s->data.data = buf;
-+            if (pitch)
-+                s->data.pitch = pitch;
-+            blizzard_window(s);
-+            s->data.data = s->data.buf;
-+            continue;
-+        }
-+
-+        s1d13745_write(opaque, dc, *(uint16_t *) buf);
-+        len -= 2;
-+        buf += 2;
-+    }
-+
-+    return;
-+}
-+
-+static void blizzard_update_display(void *opaque)
-+{
-+    struct blizzard_s *s = (struct blizzard_s *) opaque;
-+    int y, bypp, bypl, bwidth;
-+    uint8_t *src, *dst;
-+
-+    if (!s->enable)
-+        return;
-+
-+    if (s->x != s->state->width || s->y != s->state->height) {
-+        s->invalidate = 1;
-+        dpy_resize(s->state, s->x, s->y);
-+    }
-+
-+    if (s->invalidate) {
-+        s->invalidate = 0;
-+
-+        if (s->blank) {
-+            bypp = (s->state->depth + 7) >> 3;
-+            memset(s->state->data, 0, bypp * s->x * s->y);
-+            return;
-+        }
-+
-+        s->mx[0] = 0;
-+        s->mx[1] = s->x;
-+        s->my[0] = 0;
-+        s->my[1] = s->y;
-+    }
-+
-+    if (s->mx[1] <= s->mx[0])
-+        return;
-+
-+    bypp = (s->state->depth + 7) >> 3;
-+    bypl = bypp * s->x;
-+    bwidth = bypp * (s->mx[1] - s->mx[0]);
-+    y = s->my[0];
-+    src = s->fb + bypl * y + bypp * s->mx[0];
-+    dst = s->state->data + bypl * y + bypp * s->mx[0];
-+    for (; y < s->my[1]; y ++, src += bypl, dst += bypl)
-+        memcpy(dst, src, bwidth);
-+
-+    dpy_update(s->state, s->mx[0], s->my[0],
-+                    s->mx[1] - s->mx[0], y - s->my[0]);
-+
-+    s->mx[0] = s->x;
-+    s->mx[1] = 0;
-+    s->my[0] = s->y;
-+    s->my[1] = 0;
-+}
-+
-+static void blizzard_screen_dump(void *opaque, const char *filename) {
-+    struct blizzard_s *s = (struct blizzard_s *) opaque;
-+
-+    blizzard_update_display(opaque);
-+    if (s && s->state->data)
-+        ppm_save(filename, s->state->data, s->x, s->y, s->state->linesize);
-+}
-+
-+#define DEPTH 8
-+#include "blizzard_template.h"
-+#define DEPTH 15
-+#include "blizzard_template.h"
-+#define DEPTH 16
-+#include "blizzard_template.h"
-+#define DEPTH 24
-+#include "blizzard_template.h"
-+#define DEPTH 32
-+#include "blizzard_template.h"
-+
-+void *s1d13745_init(qemu_irq gpio_int, DisplayState *ds)
-+{
-+    struct blizzard_s *s = (struct blizzard_s *) qemu_mallocz(sizeof(*s));
-+
-+    s->state = ds;
-+    s->fb = qemu_malloc(0x180000);
-+
-+    switch (s->state->depth) {
-+    case 0:
-+        s->line_fn_tab[0] = s->line_fn_tab[1] =
-+                qemu_mallocz(sizeof(blizzard_fn_t) * 0x10);
-+        break;
-+    case 8:
-+        s->line_fn_tab[0] = blizzard_draw_fn_8;
-+        s->line_fn_tab[1] = blizzard_draw_fn_r_8;
-+        break;
-+    case 15:
-+        s->line_fn_tab[0] = blizzard_draw_fn_15;
-+        s->line_fn_tab[1] = blizzard_draw_fn_r_15;
-+        break;
-+    case 16:
-+        s->line_fn_tab[0] = blizzard_draw_fn_16;
-+        s->line_fn_tab[1] = blizzard_draw_fn_r_16;
-+        break;
-+    case 24:
-+        s->line_fn_tab[0] = blizzard_draw_fn_24;
-+        s->line_fn_tab[1] = blizzard_draw_fn_r_24;
-+        break;
-+    case 32:
-+        s->line_fn_tab[0] = blizzard_draw_fn_32;
-+        s->line_fn_tab[1] = blizzard_draw_fn_r_32;
-+        break;
-+    default:
-+        fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__);
-+        exit(1);
-+    }
-+
-+    blizzard_reset(s);
-+
-+    graphic_console_init(s->state, blizzard_update_display,
-+                    blizzard_invalidate_display, blizzard_screen_dump,
-+                    NULL, s);
-+
-+    return s;
-+}
-diff --git a/hw/blizzard_template.h b/hw/blizzard_template.h
-new file mode 100644
-index 0000000..8c6451d
---- /dev/null
-+++ b/hw/blizzard_template.h
-@@ -0,0 +1,138 @@
-+/*
-+ * QEMU Epson S1D13744/S1D13745 templates
-+ *
-+ * Copyright (C) 2008 Nokia Corporation
-+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation; either version 2 of
-+ * the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-+ * MA 02111-1307 USA
-+ */
-+
-+#define SKIP_PIXEL(to)		to += deststep
-+#if DEPTH == 8
-+# define PIXEL_TYPE		uint8_t
-+# define COPY_PIXEL(to, from)	*to = from; SKIP_PIXEL(to)
-+# define COPY_PIXEL1(to, from)	*to ++ = from
-+#elif DEPTH == 15 || DEPTH == 16
-+# define PIXEL_TYPE		uint16_t
-+# define COPY_PIXEL(to, from)	*to = from; SKIP_PIXEL(to)
-+# define COPY_PIXEL1(to, from)	*to ++ = from
-+#elif DEPTH == 24
-+# define PIXEL_TYPE		uint8_t
-+# define COPY_PIXEL(to, from)	\
-+    to[0] = from; to[1] = (from) >> 8; to[2] = (from) >> 16; SKIP_PIXEL(to)
-+# define COPY_PIXEL1(to, from)	\
-+    *to ++ = from; *to ++ = (from) >> 8; *to ++ = (from) >> 16
-+#elif DEPTH == 32
-+# define PIXEL_TYPE		uint32_t
-+# define COPY_PIXEL(to, from)	*to = from; SKIP_PIXEL(to)
-+# define COPY_PIXEL1(to, from)	*to ++ = from
-+#else
-+# error unknown bit depth
-+#endif
-+
-+#ifdef WORDS_BIGENDIAN
-+# define SWAP_WORDS	1
-+#endif
-+
-+static void glue(blizzard_draw_line16_, DEPTH)(PIXEL_TYPE *dest,
-+                const uint16_t *src, unsigned int width)
-+{
-+#if !defined(SWAP_WORDS) && DEPTH == 16
-+    memcpy(dest, src, width << 1);
-+#else
-+    uint16_t data;
-+    unsigned int r, g, b;
-+    const uint16_t *end = (void *) src + width;
-+    while (src < end) {
-+        data = lduw_raw(src ++);
-+        b = (data & 0x1f) << 3;
-+        data >>= 5;
-+        g = (data & 0x3f) << 2;
-+        data >>= 6;
-+        r = (data & 0x1f) << 3;
-+        data >>= 5;
-+        COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r, g, b));
-+    }
-+#endif
-+}
-+
-+static void glue(blizzard_draw_line24mode1_, DEPTH)(PIXEL_TYPE *dest,
-+                const uint8_t *src, unsigned int width)
-+{
-+    /* TODO: check if SDL 24-bit planes are not in the same format and
-+     * if so, use memcpy */
-+    unsigned int r[2], g[2], b[2];
-+    const uint8_t *end = src + width;
-+    while (src < end) {
-+        g[0] = *src ++;
-+        r[0] = *src ++;
-+        r[1] = *src ++;
-+        b[0] = *src ++;
-+        COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r[0], g[0], b[0]));
-+        b[1] = *src ++;
-+        g[1] = *src ++;
-+        COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r[1], g[1], b[1]));
-+    }
-+}
-+
-+static void glue(blizzard_draw_line24mode2_, DEPTH)(PIXEL_TYPE *dest,
-+                const uint8_t *src, unsigned int width)
-+{
-+    unsigned int r, g, b;
-+    const uint8_t *end = src + width;
-+    while (src < end) {
-+        r = *src ++;
-+        src ++;
-+        b = *src ++;
-+        g = *src ++;
-+        COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r, g, b));
-+    }
-+}
-+
-+/* No rotation */
-+static blizzard_fn_t glue(blizzard_draw_fn_, DEPTH)[0x10] = {
-+    NULL,
-+    /* RGB 5:6:5*/
-+    (blizzard_fn_t) glue(blizzard_draw_line16_, DEPTH),
-+    /* RGB 6:6:6 mode 1 */
-+    (blizzard_fn_t) glue(blizzard_draw_line24mode1_, DEPTH),
-+    /* RGB 8:8:8 mode 1 */
-+    (blizzard_fn_t) glue(blizzard_draw_line24mode1_, DEPTH),
-+    NULL, NULL,
-+    /* RGB 6:6:6 mode 2 */
-+    (blizzard_fn_t) glue(blizzard_draw_line24mode2_, DEPTH),
-+    /* RGB 8:8:8 mode 2 */
-+    (blizzard_fn_t) glue(blizzard_draw_line24mode2_, DEPTH),
-+    /* YUV 4:2:2 */
-+    NULL,
-+    /* YUV 4:2:0 */
-+    NULL,
-+    NULL, NULL, NULL, NULL, NULL, NULL,
-+};
-+
-+/* 90deg, 180deg and 270deg rotation */
-+static blizzard_fn_t glue(blizzard_draw_fn_r_, DEPTH)[0x10] = {
-+    /* TODO */
-+    [0 ... 0xf] = NULL,
-+};
-+
-+#undef DEPTH
-+#undef SKIP_PIXEL
-+#undef COPY_PIXEL
-+#undef COPY_PIXEL1
-+#undef PIXEL_TYPE
-+
-+#undef SWAP_WORDS
-diff --git a/hw/boards.h b/hw/boards.h
-index affcaa6..408d1e8 100644
---- a/hw/boards.h
-+++ b/hw/boards.h
-@@ -80,6 +80,9 @@ extern QEMUMachine terrierpda_machine;
- /* palm.c */
- extern QEMUMachine palmte_machine;
- 
-+/* nseries.c */
-+extern QEMUMachine n800_machine;
-+
- /* gumstix.c */
- extern QEMUMachine connex_machine;
- extern QEMUMachine verdex_machine;
-diff --git a/hw/cbus.c b/hw/cbus.c
-new file mode 100644
-index 0000000..001b007
---- /dev/null
-+++ b/hw/cbus.c
-@@ -0,0 +1,565 @@
-+/*
-+ * CBUS three-pin bus and the Retu / Betty / Tahvo / Vilma / Avilma /
-+ * Hinku / Vinku / Ahne / Pihi chips used in various Nokia platforms.
-+ *
-+ * Copyright (C) 2008 Nokia Corporation
-+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation; either version 2 of
-+ * the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-+ * MA 02111-1307 USA
-+ */
-+
-+#include "qemu-common.h"
-+#include "irq.h"
-+#include "devices.h"
-+#include "sysemu.h"
-+
-+//#define DEBUG
-+
-+struct cbus_slave_s;
-+struct cbus_priv_s {
-+    struct cbus_s cbus;
-+
-+    int sel;
-+    int dat;
-+    int clk;
-+    int bit;
-+    int dir;
-+    uint16_t val;
-+    qemu_irq dat_out;
-+
-+    int addr;
-+    int reg;
-+    int rw;
-+    enum {
-+        cbus_address,
-+        cbus_value,
-+    } cycle;
-+
-+    struct cbus_slave_s *slave[8];
-+};
-+
-+struct cbus_slave_s {
-+    void *opaque;
-+    void (*io)(void *opaque, int rw, int reg, uint16_t *val);
-+    int addr;
-+};
-+
-+static void cbus_io(struct cbus_priv_s *s)
-+{
-+    if (s->slave[s->addr])
-+        s->slave[s->addr]->io(s->slave[s->addr]->opaque,
-+                        s->rw, s->reg, &s->val);
-+    else
-+        cpu_abort(cpu_single_env, "%s: bad slave address %i\n",
-+                        __FUNCTION__, s->addr);
-+}
-+
-+static void cbus_cycle(struct cbus_priv_s *s)
-+{
-+    switch (s->cycle) {
-+    case cbus_address:
-+        s->addr = (s->val >> 6) & 7;
-+        s->rw =   (s->val >> 5) & 1;
-+        s->reg =  (s->val >> 0) & 0x1f;
-+
-+        s->cycle = cbus_value;
-+        s->bit = 15;
-+        s->dir = !s->rw;
-+        s->val = 0;
-+
-+        if (s->rw)
-+            cbus_io(s);
-+        break;
-+
-+    case cbus_value:
-+        if (!s->rw)
-+            cbus_io(s);
-+
-+        s->cycle = cbus_address;
-+        s->bit = 8;
-+        s->dir = 1;
-+        s->val = 0;
-+        break;
-+    }
-+}
-+
-+static void cbus_clk(void *opaque, int line, int level)
-+{
-+    struct cbus_priv_s *s = (struct cbus_priv_s *) opaque;
-+
-+    if (!s->sel && level && !s->clk) {
-+        if (s->dir)
-+            s->val |= s->dat << (s->bit --);
-+        else
-+            qemu_set_irq(s->dat_out, (s->val >> (s->bit --)) & 1);
-+
-+        if (s->bit < 0)
-+            cbus_cycle(s);
-+    }
-+
-+    s->clk = level;
-+}
-+
-+static void cbus_dat(void *opaque, int line, int level)
-+{
-+    struct cbus_priv_s *s = (struct cbus_priv_s *) opaque;
-+
-+    s->dat = level;
-+}
-+
-+static void cbus_sel(void *opaque, int line, int level)
-+{
-+    struct cbus_priv_s *s = (struct cbus_priv_s *) opaque;
-+
-+    if (!level) {
-+        s->dir = 1;
-+        s->bit = 8;
-+        s->val = 0;
-+    }
-+
-+    s->sel = level;
-+}
-+
-+struct cbus_s *cbus_init(qemu_irq dat)
-+{
-+    struct cbus_priv_s *s = (struct cbus_priv_s *) qemu_mallocz(sizeof(*s));
-+
-+    s->dat_out = dat;
-+    s->cbus.clk = qemu_allocate_irqs(cbus_clk, s, 1)[0];
-+    s->cbus.dat = qemu_allocate_irqs(cbus_dat, s, 1)[0];
-+    s->cbus.sel = qemu_allocate_irqs(cbus_sel, s, 1)[0];
-+
-+    s->sel = 1;
-+    s->clk = 0;
-+    s->dat = 0;
-+
-+    return &s->cbus;
-+}
-+
-+void cbus_attach(struct cbus_s *bus, void *slave_opaque)
-+{
-+    struct cbus_slave_s *slave = (struct cbus_slave_s *) slave_opaque;
-+    struct cbus_priv_s *s = (struct cbus_priv_s *) bus;
-+
-+    s->slave[slave->addr] = slave;
-+}
-+
-+/* Retu/Vilma */
-+struct cbus_retu_s {
-+    uint16_t irqst;
-+    uint16_t irqen;
-+    uint16_t cc[2];
-+    int channel;
-+    uint16_t result[16];
-+    uint16_t sample;
-+
-+    struct {
-+        uint16_t cal;
-+    } rtc;
-+
-+    int is_vilma;
-+    qemu_irq irq;
-+    struct cbus_slave_s cbus;
-+};
-+
-+static void retu_interrupt_update(struct cbus_retu_s *s)
-+{
-+    qemu_set_irq(s->irq, s->irqst & ~s->irqen);
-+}
-+
-+#define RETU_REG_ASICR		0x00	/* (RO) ASIC ID & revision */
-+#define RETU_REG_IDR		0x01	/* (T)  Interrupt ID */
-+#define RETU_REG_IMR		0x02	/* (RW) Interrupt mask */
-+#define RETU_REG_RTCDSR		0x03	/* (RW) RTC seconds register */
-+#define RETU_REG_RTCHMR		0x04	/* (RO) RTC hours and minutes reg */
-+#define RETU_REG_RTCHMAR	0x05	/* (RW) RTC hours and minutes set reg */
-+#define RETU_REG_RTCCALR	0x06	/* (RW) RTC calibration register */
-+#define RETU_REG_ADCR		0x08	/* (RW) ADC result register */
-+#define RETU_REG_ADCSCR		0x09	/* (RW) ADC sample control register */
-+#define RETU_REG_AFCR		0x0a	/* (RW) AFC register */
-+#define RETU_REG_ANTIFR		0x0b	/* (RW) AntiF register */
-+#define RETU_REG_CALIBR		0x0c	/* (RW) CalibR register*/
-+#define RETU_REG_CCR1		0x0d	/* (RW) Common control register 1 */
-+#define RETU_REG_CCR2		0x0e	/* (RW) Common control register 2 */
-+#define RETU_REG_RCTRL_CLR	0x0f	/* (T)  Regulator clear register */
-+#define RETU_REG_RCTRL_SET	0x10	/* (T)  Regulator set register */
-+#define RETU_REG_TXCR		0x11	/* (RW) TxC register */
-+#define RETU_REG_STATUS		0x16	/* (RO) Status register */
-+#define RETU_REG_WATCHDOG	0x17	/* (RW) Watchdog register */
-+#define RETU_REG_AUDTXR		0x18	/* (RW) Audio Codec Tx register */
-+#define RETU_REG_AUDPAR		0x19	/* (RW) AudioPA register */
-+#define RETU_REG_AUDRXR1	0x1a	/* (RW) Audio receive register 1 */
-+#define RETU_REG_AUDRXR2	0x1b	/* (RW) Autio receive register 2 */
-+#define RETU_REG_SGR1		0x1c	/* (RW) */
-+#define RETU_REG_SCR1		0x1d	/* (RW) */
-+#define RETU_REG_SGR2		0x1e	/* (RW) */
-+#define RETU_REG_SCR2		0x1f	/* (RW) */
-+
-+/* Retu Interrupt sources */
-+enum {
-+    retu_int_pwr	= 0,	/* Power */
-+    retu_int_char	= 1,	/* Charger */
-+    retu_int_rtcs	= 2,	/* Seconds */
-+    retu_int_rtcm	= 3,	/* Minutes */
-+    retu_int_rtcd	= 4,	/* Days */
-+    retu_int_rtca	= 5,	/* Alarm */
-+    retu_int_hook	= 6,	/* Hook */
-+    retu_int_head	= 7,	/* Headset */
-+    retu_int_adcs	= 8,	/* ADC sample */
-+};
-+
-+/* Retu ADC channel wiring */
-+enum {
-+    retu_adc_bsi	= 1,	/* BSI */
-+    retu_adc_batt_temp	= 2,	/* Battery temperature */
-+    retu_adc_chg_volt	= 3,	/* Charger voltage */
-+    retu_adc_head_det	= 4,	/* Headset detection */
-+    retu_adc_hook_det	= 5,	/* Hook detection */
-+    retu_adc_rf_gp	= 6,	/* RF GP */
-+    retu_adc_tx_det	= 7,	/* Wideband Tx detection */
-+    retu_adc_batt_volt	= 8,	/* Battery voltage */
-+    retu_adc_sens	= 10,	/* Light sensor */
-+    retu_adc_sens_temp	= 11,	/* Light sensor temperature */
-+    retu_adc_bbatt_volt	= 12,	/* Backup battery voltage */
-+    retu_adc_self_temp	= 13,	/* RETU temperature */
-+};
-+
-+static inline uint16_t retu_read(struct cbus_retu_s *s, int reg)
-+{
-+#ifdef DEBUG
-+    printf("RETU read at %02x\n", reg);
-+#endif
-+
-+    switch (reg) {
-+    case RETU_REG_ASICR:
-+        return 0x0015 | (s->is_vilma << 7);
-+
-+    case RETU_REG_IDR:
-+        return s->irqst;
-+
-+    case RETU_REG_IMR:
-+        return s->irqen;
-+
-+    case RETU_REG_RTCDSR:
-+    case RETU_REG_RTCHMR:
-+    case RETU_REG_RTCHMAR:
-+        /* TODO */
-+        return 0x0000;
-+
-+    case RETU_REG_RTCCALR:
-+        return s->rtc.cal;
-+
-+    case RETU_REG_ADCR:
-+        return (s->channel << 10) | s->result[s->channel];
-+    case RETU_REG_ADCSCR:
-+        return s->sample;
-+
-+    case RETU_REG_AFCR:
-+    case RETU_REG_ANTIFR:
-+    case RETU_REG_CALIBR:
-+        /* TODO */
-+        return 0x0000;
-+
-+    case RETU_REG_CCR1:
-+        return s->cc[0];
-+    case RETU_REG_CCR2:
-+        return s->cc[1];
-+
-+    case RETU_REG_RCTRL_CLR:
-+    case RETU_REG_RCTRL_SET:
-+    case RETU_REG_TXCR:
-+    case RETU_REG_STATUS:
-+    case RETU_REG_WATCHDOG:
-+    case RETU_REG_AUDTXR:
-+    case RETU_REG_AUDPAR:
-+    case RETU_REG_AUDRXR1:
-+    case RETU_REG_AUDRXR2:
-+    case RETU_REG_SGR1:
-+    case RETU_REG_SCR1:
-+    case RETU_REG_SGR2:
-+    case RETU_REG_SCR2:
-+        /* TODO */
-+        return 0x0000;
-+
-+    default:
-+        cpu_abort(cpu_single_env, "%s: bad register %02x\n",
-+                        __FUNCTION__, reg);
-+    }
-+}
-+
-+static inline void retu_write(struct cbus_retu_s *s, int reg, uint16_t val)
-+{
-+#ifdef DEBUG
-+    printf("RETU write of %04x at %02x\n", val, reg);
-+#endif
-+
-+    switch (reg) {
-+    case RETU_REG_IDR:
-+        s->irqst ^= val;
-+        retu_interrupt_update(s);
-+        break;
-+
-+    case RETU_REG_IMR:
-+        s->irqen = val;
-+        retu_interrupt_update(s);
-+        break;
-+
-+    case RETU_REG_RTCDSR:
-+    case RETU_REG_RTCHMAR:
-+        /* TODO */
-+        break;
-+
-+    case RETU_REG_RTCCALR:
-+        s->rtc.cal = val;
-+        break;
-+
-+    case RETU_REG_ADCR:
-+        s->channel = (val >> 10) & 0xf;
-+        s->irqst |= 1 << retu_int_adcs;
-+        retu_interrupt_update(s);
-+        break;
-+    case RETU_REG_ADCSCR:
-+        s->sample &= ~val;
-+        break;
-+
-+    case RETU_REG_AFCR:
-+    case RETU_REG_ANTIFR:
-+    case RETU_REG_CALIBR:
-+
-+    case RETU_REG_CCR1:
-+        s->cc[0] = val;
-+        break;
-+    case RETU_REG_CCR2:
-+        s->cc[1] = val;
-+
-+        break;
-+    case RETU_REG_RCTRL_CLR:
-+    case RETU_REG_RCTRL_SET:
-+    case RETU_REG_STATUS:
-+        /* TODO */
-+        break;
-+
-+    case RETU_REG_WATCHDOG:
-+        if (val == 0 && (s->cc[0] & 2))
-+            qemu_system_shutdown_request();
-+        break;
-+
-+    case RETU_REG_TXCR:
-+    case RETU_REG_AUDTXR:
-+    case RETU_REG_AUDPAR:
-+    case RETU_REG_AUDRXR1:
-+    case RETU_REG_AUDRXR2:
-+    case RETU_REG_SGR1:
-+    case RETU_REG_SCR1:
-+    case RETU_REG_SGR2:
-+    case RETU_REG_SCR2:
-+        /* TODO */
-+        break;
-+
-+    default:
-+        cpu_abort(cpu_single_env, "%s: bad register %02x\n",
-+                        __FUNCTION__, reg);
-+    }
-+}
-+
-+static void retu_io(void *opaque, int rw, int reg, uint16_t *val)
-+{
-+    struct cbus_retu_s *s = (struct cbus_retu_s *) opaque;
-+
-+    if (rw)
-+        *val = retu_read(s, reg);
-+    else
-+        retu_write(s, reg, *val);
-+}
-+
-+void *retu_init(qemu_irq irq, int vilma)
-+{
-+    struct cbus_retu_s *s = (struct cbus_retu_s *) qemu_mallocz(sizeof(*s));
-+
-+    s->irq = irq;
-+    s->irqen = 0xffff;
-+    s->irqst = 0x0000;
-+    s->is_vilma = !!vilma;
-+    s->rtc.cal = 0x01;
-+    s->result[retu_adc_bsi] = 0x100;
-+    s->result[retu_adc_batt_temp] = 0x100;
-+    s->result[retu_adc_chg_volt] = 0x200;
-+    s->result[retu_adc_batt_volt] = 0x240;
-+    s->result[retu_adc_sens] = 0x100;
-+    s->result[retu_adc_sens_temp] = 0x100;
-+    s->result[retu_adc_bbatt_volt] = 0x200;
-+    s->result[retu_adc_self_temp] = 0x100;
-+
-+    s->cbus.opaque = s;
-+    s->cbus.io = retu_io;
-+    s->cbus.addr = 1;
-+
-+    return &s->cbus;
-+}
-+
-+/* Tahvo/Betty */
-+struct cbus_tahvo_s {
-+    uint16_t irqst;
-+    uint16_t irqen;
-+    uint8_t charger;
-+    uint8_t backlight;
-+    uint16_t usbr;
-+    uint16_t power;
-+
-+    int is_betty;
-+    qemu_irq irq;
-+    struct cbus_slave_s cbus;
-+};
-+
-+static void tahvo_interrupt_update(struct cbus_tahvo_s *s)
-+{
-+    qemu_set_irq(s->irq, s->irqst & ~s->irqen);
-+}
-+
-+#define TAHVO_REG_ASICR		0x00	/* (RO) ASIC ID & revision */
-+#define TAHVO_REG_IDR		0x01	/* (T)  Interrupt ID */
-+#define TAHVO_REG_IDSR		0x02	/* (RO) Interrupt status */
-+#define TAHVO_REG_IMR		0x03	/* (RW) Interrupt mask */
-+#define TAHVO_REG_CHAPWMR	0x04	/* (RW) Charger PWM */
-+#define TAHVO_REG_LEDPWMR	0x05	/* (RW) LED PWM */
-+#define TAHVO_REG_USBR		0x06	/* (RW) USB control */
-+#define TAHVO_REG_RCR		0x07	/* (RW) Some kind of power management */
-+#define TAHVO_REG_CCR1		0x08	/* (RW) Common control register 1 */
-+#define TAHVO_REG_CCR2		0x09	/* (RW) Common control register 2 */
-+#define TAHVO_REG_TESTR1	0x0a	/* (RW) Test register 1 */
-+#define TAHVO_REG_TESTR2	0x0b	/* (RW) Test register 2 */
-+#define TAHVO_REG_NOPR		0x0c	/* (RW) Number of periods */
-+#define TAHVO_REG_FRR		0x0d	/* (RO) FR */
-+
-+static inline uint16_t tahvo_read(struct cbus_tahvo_s *s, int reg)
-+{
-+#ifdef DEBUG
-+    printf("TAHVO read at %02x\n", reg);
-+#endif
-+
-+    switch (reg) {
-+    case TAHVO_REG_ASICR:
-+        return 0x0021 | (s->is_betty ? 0x0b00 : 0x0300);
-+
-+    case TAHVO_REG_IDR:
-+    case TAHVO_REG_IDSR:	/* XXX: what does this do?  */
-+        return s->irqst;
-+
-+    case TAHVO_REG_IMR:
-+        return s->irqen;
-+
-+    case TAHVO_REG_CHAPWMR:
-+        return s->charger;
-+
-+    case TAHVO_REG_LEDPWMR:
-+        return s->backlight;
-+
-+    case TAHVO_REG_USBR:
-+        return s->usbr;
-+
-+    case TAHVO_REG_RCR:
-+        return s->power;
-+
-+    case TAHVO_REG_CCR1:
-+    case TAHVO_REG_CCR2:
-+    case TAHVO_REG_TESTR1:
-+    case TAHVO_REG_TESTR2:
-+    case TAHVO_REG_NOPR:
-+    case TAHVO_REG_FRR:
-+        return 0x0000;
-+
-+    default:
-+        cpu_abort(cpu_single_env, "%s: bad register %02x\n",
-+                        __FUNCTION__, reg);
-+    }
-+}
-+
-+static inline void tahvo_write(struct cbus_tahvo_s *s, int reg, uint16_t val)
-+{
-+#ifdef DEBUG
-+    printf("TAHVO write of %04x at %02x\n", val, reg);
-+#endif
-+
-+    switch (reg) {
-+    case TAHVO_REG_IDR:
-+        s->irqst ^= val;
-+        tahvo_interrupt_update(s);
-+        break;
-+
-+    case TAHVO_REG_IMR:
-+        s->irqen = val;
-+        tahvo_interrupt_update(s);
-+        break;
-+
-+    case TAHVO_REG_CHAPWMR:
-+        s->charger = val;
-+        break;
-+
-+    case TAHVO_REG_LEDPWMR:
-+        if (s->backlight != (val & 0x7f)) {
-+            s->backlight = val & 0x7f;
-+            printf("%s: LCD backlight now at %i / 127\n",
-+                            __FUNCTION__, s->backlight);
-+        }
-+        break;
-+
-+    case TAHVO_REG_USBR:
-+        s->usbr = val;
-+        break;
-+
-+    case TAHVO_REG_RCR:
-+        s->power = val;
-+        break;
-+
-+    case TAHVO_REG_CCR1:
-+    case TAHVO_REG_CCR2:
-+    case TAHVO_REG_TESTR1:
-+    case TAHVO_REG_TESTR2:
-+    case TAHVO_REG_NOPR:
-+    case TAHVO_REG_FRR:
-+        break;
-+
-+    default:
-+        cpu_abort(cpu_single_env, "%s: bad register %02x\n",
-+                        __FUNCTION__, reg);
-+    }
-+}
-+
-+static void tahvo_io(void *opaque, int rw, int reg, uint16_t *val)
-+{
-+    struct cbus_tahvo_s *s = (struct cbus_tahvo_s *) opaque;
-+
-+    if (rw)
-+        *val = tahvo_read(s, reg);
-+    else
-+        tahvo_write(s, reg, *val);
-+}
-+
-+void *tahvo_init(qemu_irq irq, int betty)
-+{
-+    struct cbus_tahvo_s *s = (struct cbus_tahvo_s *) qemu_mallocz(sizeof(*s));
-+
-+    s->irq = irq;
-+    s->irqen = 0xffff;
-+    s->irqst = 0x0000;
-+    s->is_betty = !!betty;
-+
-+    s->cbus.opaque = s;
-+    s->cbus.io = tahvo_io;
-+    s->cbus.addr = 2;
-+
-+    return &s->cbus;
-+}
-diff --git a/hw/devices.h b/hw/devices.h
-index 07c673b..6f1d27b 100644
---- a/hw/devices.h
-+++ b/hw/devices.h
-@@ -16,7 +16,38 @@ uint32_t ads7846_read(void *opaque);
- void ads7846_write(void *opaque, uint32_t value);
- struct ads7846_state_s *ads7846_init(qemu_irq penirq);
- 
-+/* tsc210x.c */
-+struct uwire_slave_s;
-+struct mouse_transform_info_s;
-+struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio);
-+struct uwire_slave_s *tsc2301_init(qemu_irq penirq, qemu_irq kbirq,
-+                qemu_irq dav, AudioState *audio);
-+struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip);
-+uint32_t tsc210x_txrx(void *opaque, uint32_t value);
-+void tsc210x_set_transform(struct uwire_slave_s *chip,
-+                struct mouse_transform_info_s *info);
-+void tsc210x_key_event(struct uwire_slave_s *chip, int key, int down);
-+
- /* stellaris_input.c */
- void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode);
- 
-+/* blizzard.c */
-+void *s1d13745_init(qemu_irq gpio_int, DisplayState *ds);
-+void s1d13745_write(void *opaque, int dc, uint16_t value);
-+void s1d13745_write_block(void *opaque, int dc,
-+                void *buf, size_t len, int pitch);
-+uint16_t s1d13745_read(void *opaque, int dc);
-+
-+/* cbus.c */
-+struct cbus_s {
-+    qemu_irq clk;
-+    qemu_irq dat;
-+    qemu_irq sel;
-+};
-+struct cbus_s *cbus_init(qemu_irq dat_out);
-+void cbus_attach(struct cbus_s *bus, void *slave_opaque);
-+
-+void *retu_init(qemu_irq irq, int vilma);
-+void *tahvo_init(qemu_irq irq, int betty);
-+
- #endif
-diff --git a/hw/flash.h b/hw/flash.h
-index 42d25fe..c000d33 100644
---- a/hw/flash.h
-+++ b/hw/flash.h
-@@ -34,6 +34,11 @@ uint8_t nand_getio(struct nand_flash_s *s);
- #define NAND_MFR_HYNIX		0xad
- #define NAND_MFR_MICRON		0x2c
- 
-+/* onenand.c */
-+void onenand_base_update(void *opaque, target_phys_addr_t new);
-+void onenand_base_unmap(void *opaque);
-+void *onenand_init(uint32_t id, int regshift, qemu_irq irq);
-+
- /* ecc.c */
- struct ecc_state_s {
-     uint8_t cp;		/* Column parity */
-diff --git a/hw/i2c.h b/hw/i2c.h
-index 2897036..fae46b7 100644
---- a/hw/i2c.h
-+++ b/hw/i2c.h
-@@ -71,4 +71,14 @@ uint32_t wm8750_adc_dat(void *opaque);
- /* ssd0303.c */
- void ssd0303_init(DisplayState *ds, i2c_bus *bus, int address);
- 
-+/* twl92230.c */
-+i2c_slave *twl92230_init(i2c_bus *bus, qemu_irq irq);
-+qemu_irq *twl92230_gpio_in_get(i2c_slave *i2c);
-+void twl92230_gpio_out_set(i2c_slave *i2c, int line, qemu_irq handler);
-+
-+/* tmp105.c */
-+struct i2c_slave *tmp105_init(i2c_bus *bus, qemu_irq alarm);
-+void tmp105_reset(i2c_slave *i2c);
-+void tmp105_set(i2c_slave *i2c, int temp);
-+
- #endif
-diff --git a/hw/integratorcp.c b/hw/integratorcp.c
-index 549cc25..f6e6364 100644
---- a/hw/integratorcp.c
-+++ b/hw/integratorcp.c
-@@ -469,6 +469,11 @@ static void icp_control_init(uint32_t base)
- 
- /* Board init.  */
- 
-+static struct arm_boot_info integrator_binfo = {
-+    .loader_start = 0x0,
-+    .board_id = 0x113,
-+};
-+
- static void integratorcp_init(int ram_size, int vga_ram_size,
-                      const char *boot_device, DisplayState *ds,
-                      const char *kernel_filename, const char *kernel_cmdline,
-@@ -527,8 +532,11 @@ static void integratorcp_init(int ram_size, int vga_ram_size,
-     }
-     pl110_init(ds, 0xc0000000, pic[22], 0);
- 
--    arm_load_kernel(env, ram_size, kernel_filename, kernel_cmdline,
--                    initrd_filename, 0x113, 0x0);
-+    integrator_binfo.ram_size = ram_size;
-+    integrator_binfo.kernel_filename = kernel_filename;
-+    integrator_binfo.kernel_cmdline = kernel_cmdline;
-+    integrator_binfo.initrd_filename = initrd_filename;
-+    arm_load_kernel(env, &integrator_binfo);
- }
- 
- QEMUMachine integratorcp_machine = {
-diff --git a/hw/mainstone.c b/hw/mainstone.c
-index 5856791..9564fc3 100644
---- a/hw/mainstone.c
-+++ b/hw/mainstone.c
-@@ -59,12 +59,17 @@ static struct keymap map[0xE0] = {
- 
- enum mainstone_model_e { mainstone };
- 
-+static struct arm_boot_info mainstone_binfo = {
-+    .loader_start = PXA2XX_SDRAM_BASE,
-+    .ram_size = 0x04000000,
-+};
-+
- static void mainstone_common_init(int ram_size, int vga_ram_size,
-                 DisplayState *ds, const char *kernel_filename,
-                 const char *kernel_cmdline, const char *initrd_filename,
-                 const char *cpu_model, enum mainstone_model_e model, int arm_id)
- {
--    uint32_t mainstone_ram   = 0x04000000;
-+    uint32_t mainstone_ram   = mainstone_binfo.ram_size;
-     uint32_t mainstone_rom   = 0x00800000;
-     uint32_t mainstone_flash = 0x02000000;
-     uint32_t sector_len = 256 * 1024;
-@@ -90,7 +95,7 @@ static void mainstone_common_init(int ram_size, int vga_ram_size,
-                     qemu_ram_alloc(mainstone_rom) | IO_MEM_ROM);
- 
-     /* Setup initial (reset) machine state */
--    cpu->env->regs[15] = PXA2XX_SDRAM_BASE;
-+    cpu->env->regs[15] = mainstone_binfo.loader_start;
- 
-     /* There are two 32MiB flash devices on the board */
-     for (i = 0; i < 2; i ++) {
-@@ -121,8 +126,11 @@ static void mainstone_common_init(int ram_size, int vga_ram_size,
- 
-     smc91c111_init(&nd_table[0], MST_ETH_PHYS, mst_irq[ETHERNET_IRQ]);
- 
--    arm_load_kernel(cpu->env, mainstone_ram, kernel_filename, kernel_cmdline,
--                    initrd_filename, arm_id, PXA2XX_SDRAM_BASE);
-+    mainstone_binfo.kernel_filename = kernel_filename;
-+    mainstone_binfo.kernel_cmdline = kernel_cmdline;
-+    mainstone_binfo.initrd_filename = initrd_filename;
-+    mainstone_binfo.board_id = arm_id;
-+    arm_load_kernel(cpu->env, &mainstone_binfo);
- }
- 
- static void mainstone_init(int ram_size, int vga_ram_size,
-diff --git a/hw/max7310.c b/hw/max7310.c
-index 75e56c7..397950a 100644
---- a/hw/max7310.c
-+++ b/hw/max7310.c
-@@ -134,8 +134,8 @@ static void max7310_event(i2c_slave *i2c, enum i2c_event event)
-         s->i2c_command_byte = 1;
-         break;
-     case I2C_FINISH:
--        if (s->len == 1)
- #ifdef VERBOSE
-+        if (s->len == 1)
-             printf("%s: message too short (%i bytes)\n", __FUNCTION__, s->len);
- #endif
-         break;
-diff --git a/hw/nseries.c b/hw/nseries.c
-new file mode 100644
-index 0000000..0425d46
---- /dev/null
-+++ b/hw/nseries.c
-@@ -0,0 +1,870 @@
-+/*
-+ * Nokia N-series internet tablets.
-+ *
-+ * Copyright (C) 2007 Nokia Corporation
-+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation; either version 2 of
-+ * the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-+ * MA 02111-1307 USA
-+ */
-+
-+#include "qemu-common.h"
-+#include "sysemu.h"
-+#include "omap.h"
-+#include "arm-misc.h"
-+#include "irq.h"
-+#include "console.h"
-+#include "boards.h"
-+#include "i2c.h"
-+#include "devices.h"
-+#include "flash.h"
-+#include "hw.h"
-+
-+/* Nokia N800 support */
-+struct n800_s {
-+    struct omap_mpu_state_s *cpu;
-+
-+    struct rfbi_chip_s blizzard;
-+    struct uwire_slave_s *ts;
-+    i2c_bus *i2c;
-+
-+    int keymap[0x80];
-+};
-+
-+#define N800_MMC2_WP_GPIO		8
-+#define N800_CAM_TURN_GPIO		12
-+#define N800_BLIZZARD_POWERDOWN_GPIO	15
-+#define N800_MMC1_WP_GPIO		23
-+#define N800_ONENAND_GPIO		26
-+#define N800_BT_WKUP_GPIO		61
-+#define N800_STI_GPIO			62
-+#define N800_CBUS_SEL_GPIO		64
-+#define N800_CBUS_CLK_GPIO		65
-+#define N800_CBUS_DAT_GPIO		66
-+#define N800_WLAN_IRQ_GPIO		87
-+#define N800_BT_RESET_GPIO		92
-+#define N800_TEA5761_CS_GPIO		93
-+#define N800_UNKNOWN_GPIO		94
-+#define N800_CAM_ACT_GPIO		95
-+#define N800_MMC_CS_GPIO		96
-+#define N800_WLAN_PWR_GPIO		97
-+#define N800_BT_HOST_WKUP_GPIO		98
-+#define N800_TSC_TS_GPIO		103
-+#define N800_HEADPHONE_GPIO		107
-+#define N800_RETU_GPIO			108
-+#define N800_TSC_KP_IRQ_GPIO		109
-+#define N800_BAT_COVER_GPIO		110
-+#define N800_TAHVO_GPIO			111
-+#define N800_TSC_RESET_GPIO		119
-+#define N800_TMP105_GPIO		125
-+
-+#define XLDR_LL_UART			1
-+
-+#define N800_TMP105_ADDR		0x48
-+#define N800_MENELAUS_ADDR		0x72
-+
-+static void n800_mmc_cs_cb(void *opaque, int line, int level)
-+{
-+    /* TODO: this seems to actually be connected to the menelaus, to
-+     * which also both MMC slots connect.  */
-+    omap_mmc_enable((struct omap_mmc_s *) opaque, !level);
-+
-+    printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1);
-+}
-+
-+static void n800_gpio_setup(struct n800_s *s)
-+{
-+    qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->cpu->mmc, 1);
-+    omap2_gpio_out_set(s->cpu->gpif, N800_MMC_CS_GPIO, mmc_cs[0]);
-+
-+    qemu_irq_lower(omap2_gpio_in_get(s->cpu->gpif, N800_BAT_COVER_GPIO)[0]);
-+}
-+
-+static void n800_nand_setup(struct n800_s *s)
-+{
-+    /* Either ec40xx or ec48xx are OK for the ID */
-+    omap_gpmc_attach(s->cpu->gpmc, 0, 0, onenand_base_update,
-+                    onenand_base_unmap,
-+                    onenand_init(0xec4800, 1,
-+                            omap2_gpio_in_get(s->cpu->gpif,
-+                                    N800_ONENAND_GPIO)[0]));
-+}
-+
-+static void n800_i2c_setup(struct n800_s *s)
-+{
-+    qemu_irq tmp_irq = omap2_gpio_in_get(s->cpu->gpif, N800_TMP105_GPIO)[0];
-+
-+    /* Attach the CPU on one end of our I2C bus.  */
-+    s->i2c = omap_i2c_bus(s->cpu->i2c[0]);
-+
-+    /* Attach a menelaus PM chip */
-+    i2c_set_slave_address(
-+                    twl92230_init(s->i2c,
-+                            s->cpu->irq[0][OMAP_INT_24XX_SYS_NIRQ]),
-+                    N800_MENELAUS_ADDR);
-+
-+    /* Attach a TMP105 PM chip (A0 wired to ground) */
-+    i2c_set_slave_address(tmp105_init(s->i2c, tmp_irq), N800_TMP105_ADDR);
-+}
-+
-+/* Touchscreen and keypad controller */
-+static void n800_key_event(void *opaque, int keycode)
-+{
-+    struct n800_s *s = (struct n800_s *) opaque;
-+    int code = s->keymap[keycode & 0x7f];
-+
-+    if (code == -1)
-+        return;
-+
-+    tsc210x_key_event(s->ts, code, !(keycode & 0x80));
-+}
-+
-+static const int n800_keys[16] = {
-+    -1,
-+    72,	/* Up */
-+    63,	/* Home (F5) */
-+    -1,
-+    75,	/* Left */
-+    28,	/* Enter */
-+    77,	/* Right */
-+    -1,
-+    1,	/* Cycle (ESC) */
-+    80,	/* Down */
-+    62,	/* Menu (F4) */
-+    -1,
-+    66,	/* Zoom- (F8) */
-+    64,	/* FS (F6) */
-+    65,	/* Zoom+ (F7) */
-+    -1,
-+};
-+
-+static struct mouse_transform_info_s n800_pointercal = {
-+    .x = 800,
-+    .y = 480,
-+    .a = { 14560, -68, -3455208, -39, -9621, 35152972, 65536 },
-+};
-+
-+static void n800_tsc_setup(struct n800_s *s)
-+{
-+    int i;
-+
-+    /* XXX: are the three pins inverted inside the chip between the
-+     * tsc and the cpu (N4111)?  */
-+    qemu_irq penirq = 0;	/* NC */
-+    qemu_irq kbirq = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_KP_IRQ_GPIO)[0];
-+    qemu_irq dav = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_TS_GPIO)[0];
-+
-+    s->ts = tsc2301_init(penirq, kbirq, dav, 0);
-+
-+    for (i = 0; i < 0x80; i ++)
-+        s->keymap[i] = -1;
-+    for (i = 0; i < 0x10; i ++)
-+        if (n800_keys[i] >= 0)
-+            s->keymap[n800_keys[i]] = i;
-+
-+    qemu_add_kbd_event_handler(n800_key_event, s);
-+
-+    tsc210x_set_transform(s->ts, &n800_pointercal);
-+}
-+
-+/* LCD MIPI DBI-C controller (URAL) */
-+struct mipid_s {
-+    int resp[4];
-+    int param[4];
-+    int p;
-+    int pm;
-+    int cmd;
-+
-+    int sleep;
-+    int booster;
-+    int te;
-+    int selfcheck;
-+    int partial;
-+    int normal;
-+    int vscr;
-+    int invert;
-+    int onoff;
-+    int gamma;
-+    uint32_t id;
-+};
-+
-+static void mipid_reset(struct mipid_s *s)
-+{
-+    if (!s->sleep)
-+        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
-+
-+    s->pm = 0;
-+    s->cmd = 0;
-+
-+    s->sleep = 1;
-+    s->booster = 0;
-+    s->selfcheck =
-+            (1 << 7) |	/* Register loading OK.  */
-+            (1 << 5) |	/* The chip is attached.  */
-+            (1 << 4);	/* Display glass still in one piece.  */
-+    s->te = 0;
-+    s->partial = 0;
-+    s->normal = 1;
-+    s->vscr = 0;
-+    s->invert = 0;
-+    s->onoff = 1;
-+    s->gamma = 0;
-+}
-+
-+static uint32_t mipid_txrx(void *opaque, uint32_t cmd)
-+{
-+    struct mipid_s *s = (struct mipid_s *) opaque;
-+    uint8_t ret;
-+
-+    if (s->p >= sizeof(s->resp) / sizeof(*s->resp))
-+        ret = 0;
-+    else
-+        ret = s->resp[s->p ++];
-+    if (s->pm --> 0)
-+        s->param[s->pm] = cmd;
-+    else
-+        s->cmd = cmd;
-+
-+    switch (s->cmd) {
-+    case 0x00:	/* NOP */
-+        break;
-+
-+    case 0x01:	/* SWRESET */
-+        mipid_reset(s);
-+        break;
-+
-+    case 0x02:	/* BSTROFF */
-+        s->booster = 0;
-+        break;
-+    case 0x03:	/* BSTRON */
-+        s->booster = 1;
-+        break;
-+
-+    case 0x04:	/* RDDID */
-+        s->p = 0;
-+        s->resp[0] = (s->id >> 16) & 0xff;
-+        s->resp[1] = (s->id >>  8) & 0xff;
-+        s->resp[2] = (s->id >>  0) & 0xff;
-+        break;
-+
-+    case 0x06:	/* RD_RED */
-+    case 0x07:	/* RD_GREEN */
-+        /* XXX the bootloader sometimes issues RD_BLUE meaning RDDID so
-+         * for the bootloader one needs to change this.  */
-+    case 0x08:	/* RD_BLUE */
-+        s->p = 0;
-+        /* TODO: return first pixel components */
-+        s->resp[0] = 0x01;
-+        break;
-+
-+    case 0x09:	/* RDDST */
-+        s->p = 0;
-+        s->resp[0] = s->booster << 7;
-+        s->resp[1] = (5 << 4) | (s->partial << 2) |
-+                (s->sleep << 1) | s->normal;
-+        s->resp[2] = (s->vscr << 7) | (s->invert << 5) |
-+                (s->onoff << 2) | (s->te << 1) | (s->gamma >> 2);
-+        s->resp[3] = s->gamma << 6;
-+        break;
-+
-+    case 0x0a:	/* RDDPM */
-+        s->p = 0;
-+        s->resp[0] = (s->onoff << 2) | (s->normal << 3) | (s->sleep << 4) |
-+                (s->partial << 5) | (s->sleep << 6) | (s->booster << 7);
-+        break;
-+    case 0x0b:	/* RDDMADCTR */
-+        s->p = 0;
-+        s->resp[0] = 0;
-+        break;
-+    case 0x0c:	/* RDDCOLMOD */
-+        s->p = 0;
-+        s->resp[0] = 5;	/* 65K colours */
-+        break;
-+    case 0x0d:	/* RDDIM */
-+        s->p = 0;
-+        s->resp[0] = (s->invert << 5) | (s->vscr << 7) | s->gamma;
-+        break;
-+    case 0x0e:	/* RDDSM */
-+        s->p = 0;
-+        s->resp[0] = s->te << 7;
-+        break;
-+    case 0x0f:	/* RDDSDR */
-+        s->p = 0;
-+        s->resp[0] = s->selfcheck;
-+        break;
-+
-+    case 0x10:	/* SLPIN */
-+        s->sleep = 1;
-+        break;
-+    case 0x11:	/* SLPOUT */
-+        s->sleep = 0;
-+        s->selfcheck ^= 1 << 6;	/* POFF self-diagnosis Ok */
-+        break;
-+
-+    case 0x12:	/* PTLON */
-+        s->partial = 1;
-+        s->normal = 0;
-+        s->vscr = 0;
-+        break;
-+    case 0x13:	/* NORON */
-+        s->partial = 0;
-+        s->normal = 1;
-+        s->vscr = 0;
-+        break;
-+
-+    case 0x20:	/* INVOFF */
-+        s->invert = 0;
-+        break;
-+    case 0x21:	/* INVON */
-+        s->invert = 1;
-+        break;
-+
-+    case 0x22:	/* APOFF */
-+    case 0x23:	/* APON */
-+        goto bad_cmd;
-+
-+    case 0x25:	/* WRCNTR */
-+        if (s->pm < 0)
-+            s->pm = 1;
-+        goto bad_cmd;
-+
-+    case 0x26:	/* GAMSET */
-+        if (!s->pm)
-+            s->gamma = ffs(s->param[0] & 0xf) - 1;
-+        else if (s->pm < 0)
-+            s->pm = 1;
-+        break;
-+
-+    case 0x28:	/* DISPOFF */
-+        s->onoff = 0;
-+        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
-+        break;
-+    case 0x29:	/* DISPON */
-+        s->onoff = 1;
-+        fprintf(stderr, "%s: Display on\n", __FUNCTION__);
-+        break;
-+
-+    case 0x2a:	/* CASET */
-+    case 0x2b:	/* RASET */
-+    case 0x2c:	/* RAMWR */
-+    case 0x2d:	/* RGBSET */
-+    case 0x2e:	/* RAMRD */
-+    case 0x30:	/* PTLAR */
-+    case 0x33:	/* SCRLAR */
-+        goto bad_cmd;
-+
-+    case 0x34:	/* TEOFF */
-+        s->te = 0;
-+        break;
-+    case 0x35:	/* TEON */
-+        if (!s->pm)
-+            s->te = 1;
-+        else if (s->pm < 0)
-+            s->pm = 1;
-+        break;
-+
-+    case 0x36:	/* MADCTR */
-+        goto bad_cmd;
-+
-+    case 0x37:	/* VSCSAD */
-+        s->partial = 0;
-+        s->normal = 0;
-+        s->vscr = 1;
-+        break;
-+
-+    case 0x38:	/* IDMOFF */
-+    case 0x39:	/* IDMON */
-+    case 0x3a:	/* COLMOD */
-+        goto bad_cmd;
-+
-+    case 0xb0:	/* CLKINT / DISCTL */
-+    case 0xb1:	/* CLKEXT */
-+        if (s->pm < 0)
-+            s->pm = 2;
-+        break;
-+
-+    case 0xb4:	/* FRMSEL */
-+        break;
-+
-+    case 0xb5:	/* FRM8SEL */
-+    case 0xb6:	/* TMPRNG / INIESC */
-+    case 0xb7:	/* TMPHIS / NOP2 */
-+    case 0xb8:	/* TMPREAD / MADCTL */
-+    case 0xba:	/* DISTCTR */
-+    case 0xbb:	/* EPVOL */
-+        goto bad_cmd;
-+
-+    case 0xbd:	/* Unknown */
-+        s->p = 0;
-+        s->resp[0] = 0;
-+        s->resp[1] = 1;
-+        break;
-+
-+    case 0xc2:	/* IFMOD */
-+        if (s->pm < 0)
-+            s->pm = 2;
-+        break;
-+
-+    case 0xc6:	/* PWRCTL */
-+    case 0xc7:	/* PPWRCTL */
-+    case 0xd0:	/* EPWROUT */
-+    case 0xd1:	/* EPWRIN */
-+    case 0xd4:	/* RDEV */
-+    case 0xd5:	/* RDRR */
-+        goto bad_cmd;
-+
-+    case 0xda:	/* RDID1 */
-+        s->p = 0;
-+        s->resp[0] = (s->id >> 16) & 0xff;
-+        break;
-+    case 0xdb:	/* RDID2 */
-+        s->p = 0;
-+        s->resp[0] = (s->id >>  8) & 0xff;
-+        break;
-+    case 0xdc:	/* RDID3 */
-+        s->p = 0;
-+        s->resp[0] = (s->id >>  0) & 0xff;
-+        break;
-+
-+    default:
-+    bad_cmd:
-+        fprintf(stderr, "%s: unknown command %02x\n", __FUNCTION__, s->cmd);
-+        break;
-+    }
-+
-+    return ret;
-+}
-+
-+static void *mipid_init(void)
-+{
-+    struct mipid_s *s = (struct mipid_s *) qemu_mallocz(sizeof(*s));
-+
-+    s->id = 0x838f03;
-+    mipid_reset(s);
-+
-+    return s;
-+}
-+
-+static void n800_spi_setup(struct n800_s *s)
-+{
-+    void *tsc2301 = s->ts->opaque;
-+    void *mipid = mipid_init();
-+
-+    omap_mcspi_attach(s->cpu->mcspi[0], tsc210x_txrx, tsc2301, 0);
-+    omap_mcspi_attach(s->cpu->mcspi[0], mipid_txrx, mipid, 1);
-+}
-+
-+/* This task is normally performed by the bootloader.  If we're loading
-+ * a kernel directly, we need to enable the Blizzard ourselves.  */
-+static void n800_dss_init(struct rfbi_chip_s *chip)
-+{
-+    chip->write(chip->opaque, 0, 0x2a);		/* LCD Width register */
-+    chip->write(chip->opaque, 1, 0x64);
-+    chip->write(chip->opaque, 0, 0x2c);		/* LCD HNDP register */
-+    chip->write(chip->opaque, 1, 0x1e);
-+    chip->write(chip->opaque, 0, 0x2e);		/* LCD Height 0 register */
-+    chip->write(chip->opaque, 1, 0xe0);
-+    chip->write(chip->opaque, 0, 0x30);		/* LCD Height 1 register */
-+    chip->write(chip->opaque, 1, 0x01);
-+    chip->write(chip->opaque, 0, 0x32);		/* LCD VNDP register */
-+    chip->write(chip->opaque, 1, 0x06);
-+    chip->write(chip->opaque, 0, 0x68);		/* Display Mode register */
-+    chip->write(chip->opaque, 1, 1);		/* Enable bit */
-+}
-+
-+static void n800_dss_setup(struct n800_s *s, DisplayState *ds)
-+{
-+    s->blizzard.opaque = s1d13745_init(0, ds);
-+    s->blizzard.block = s1d13745_write_block;
-+    s->blizzard.write = s1d13745_write;
-+    s->blizzard.read = s1d13745_read;
-+
-+    omap_rfbi_attach(s->cpu->dss, 0, &s->blizzard);
-+}
-+
-+static void n800_cbus_setup(struct n800_s *s)
-+{
-+    qemu_irq dat_out = omap2_gpio_in_get(s->cpu->gpif, N800_CBUS_DAT_GPIO)[0];
-+    qemu_irq retu_irq = omap2_gpio_in_get(s->cpu->gpif, N800_RETU_GPIO)[0];
-+    qemu_irq tahvo_irq = omap2_gpio_in_get(s->cpu->gpif, N800_TAHVO_GPIO)[0];
-+
-+    struct cbus_s *cbus = cbus_init(dat_out);
-+
-+    omap2_gpio_out_set(s->cpu->gpif, N800_CBUS_CLK_GPIO, cbus->clk);
-+    omap2_gpio_out_set(s->cpu->gpif, N800_CBUS_DAT_GPIO, cbus->dat);
-+    omap2_gpio_out_set(s->cpu->gpif, N800_CBUS_SEL_GPIO, cbus->sel);
-+
-+    cbus_attach(cbus, retu_init(retu_irq, 1));
-+    cbus_attach(cbus, tahvo_init(tahvo_irq, 1));
-+}
-+
-+/* This task is normally performed by the bootloader.  If we're loading
-+ * a kernel directly, we need to set up GPMC mappings ourselves.  */
-+static void n800_gpmc_init(struct n800_s *s)
-+{
-+    uint32_t config7 =
-+            (0xf << 8) |	/* MASKADDRESS */
-+            (1 << 6) |		/* CSVALID */
-+            (4 << 0);		/* BASEADDRESS */
-+
-+    cpu_physical_memory_write(0x6800a078,		/* GPMC_CONFIG7_0 */
-+                    (void *) &config7, sizeof(config7));
-+}
-+
-+#if 0
-+static uint32_t n800_pinout[104] = {
-+    0x080f00d8, 0x00d40808, 0x03080808, 0x080800d0,
-+    0x00dc0808, 0x0b0f0f00, 0x080800b4, 0x00c00808,
-+    0x08080808, 0x180800c4, 0x00b80000, 0x08080808,
-+    0x080800bc, 0x00cc0808, 0x08081818, 0x18180128,
-+    0x01241800, 0x18181818, 0x000000f0, 0x01300000,
-+    0x00001b0b, 0x1b0f0138, 0x00e0181b, 0x1b031b0b,
-+    0x180f0078, 0x00740018, 0x0f0f0f1a, 0x00000080,
-+    0x007c0000, 0x00000000, 0x00000088, 0x00840000,
-+    0x00000000, 0x00000094, 0x00980300, 0x0f180003,
-+    0x0000008c, 0x00900f0f, 0x0f0f1b00, 0x0f00009c,
-+    0x01140000, 0x1b1b0f18, 0x0818013c, 0x01400008,
-+    0x00001818, 0x000b0110, 0x010c1800, 0x0b030b0f,
-+    0x181800f4, 0x00f81818, 0x00000018, 0x000000fc,
-+    0x00401808, 0x00000000, 0x0f1b0030, 0x003c0008,
-+    0x00000000, 0x00000038, 0x00340000, 0x00000000,
-+    0x1a080070, 0x00641a1a, 0x08080808, 0x08080060,
-+    0x005c0808, 0x08080808, 0x08080058, 0x00540808,
-+    0x08080808, 0x0808006c, 0x00680808, 0x08080808,
-+    0x000000a8, 0x00b00000, 0x08080808, 0x000000a0,
-+    0x00a40000, 0x00000000, 0x08ff0050, 0x004c0808,
-+    0xffffffff, 0xffff0048, 0x0044ffff, 0xffffffff,
-+    0x000000ac, 0x01040800, 0x08080b0f, 0x18180100,
-+    0x01081818, 0x0b0b1808, 0x1a0300e4, 0x012c0b1a,
-+    0x02020018, 0x0b000134, 0x011c0800, 0x0b1b1b00,
-+    0x0f0000c8, 0x00ec181b, 0x000f0f02, 0x00180118,
-+    0x01200000, 0x0f0b1b1b, 0x0f0200e8, 0x0000020b,
-+};
-+#endif
-+
-+/* Setup sequence done by the bootloader */
-+static void n800_boot_init(void *opaque)
-+{
-+    struct n800_s *s = (struct n800_s *) opaque;
-+    uint32_t buf;
-+
-+    /* PRCM setup */
-+#define omap_writel(addr, val)	\
-+    buf = (val);			\
-+    cpu_physical_memory_write(addr, (void *) &buf, sizeof(buf))
-+
-+    omap_writel(0x48008060, 0x41);		/* PRCM_CLKSRC_CTRL */
-+    omap_writel(0x48008070, 1);			/* PRCM_CLKOUT_CTRL */
-+    omap_writel(0x48008078, 0);			/* PRCM_CLKEMUL_CTRL */
-+    omap_writel(0x48008090, 0);			/* PRCM_VOLTSETUP */
-+    omap_writel(0x48008094, 0);			/* PRCM_CLKSSETUP */
-+    omap_writel(0x48008098, 0);			/* PRCM_POLCTRL */
-+    omap_writel(0x48008140, 2);			/* CM_CLKSEL_MPU */
-+    omap_writel(0x48008148, 0);			/* CM_CLKSTCTRL_MPU */
-+    omap_writel(0x48008158, 1);			/* RM_RSTST_MPU */
-+    omap_writel(0x480081c8, 0x15);		/* PM_WKDEP_MPU */
-+    omap_writel(0x480081d4, 0x1d4);		/* PM_EVGENCTRL_MPU */
-+    omap_writel(0x480081d8, 0);			/* PM_EVEGENONTIM_MPU */
-+    omap_writel(0x480081dc, 0);			/* PM_EVEGENOFFTIM_MPU */
-+    omap_writel(0x480081e0, 0xc);		/* PM_PWSTCTRL_MPU */
-+    omap_writel(0x48008200, 0x047e7ff7);	/* CM_FCLKEN1_CORE */
-+    omap_writel(0x48008204, 0x00000004);	/* CM_FCLKEN2_CORE */
-+    omap_writel(0x48008210, 0x047e7ff1);	/* CM_ICLKEN1_CORE */
-+    omap_writel(0x48008214, 0x00000004);	/* CM_ICLKEN2_CORE */
-+    omap_writel(0x4800821c, 0x00000000);	/* CM_ICLKEN4_CORE */
-+    omap_writel(0x48008230, 0);			/* CM_AUTOIDLE1_CORE */
-+    omap_writel(0x48008234, 0);			/* CM_AUTOIDLE2_CORE */
-+    omap_writel(0x48008238, 7);			/* CM_AUTOIDLE3_CORE */
-+    omap_writel(0x4800823c, 0);			/* CM_AUTOIDLE4_CORE */
-+    omap_writel(0x48008240, 0x04360626);	/* CM_CLKSEL1_CORE */
-+    omap_writel(0x48008244, 0x00000014);	/* CM_CLKSEL2_CORE */
-+    omap_writel(0x48008248, 0);			/* CM_CLKSTCTRL_CORE */
-+    omap_writel(0x48008300, 0x00000000);	/* CM_FCLKEN_GFX */
-+    omap_writel(0x48008310, 0x00000000);	/* CM_ICLKEN_GFX */
-+    omap_writel(0x48008340, 0x00000001);	/* CM_CLKSEL_GFX */
-+    omap_writel(0x48008400, 0x00000004);	/* CM_FCLKEN_WKUP */
-+    omap_writel(0x48008410, 0x00000004);	/* CM_ICLKEN_WKUP */
-+    omap_writel(0x48008440, 0x00000000);	/* CM_CLKSEL_WKUP */
-+    omap_writel(0x48008500, 0x000000cf);	/* CM_CLKEN_PLL */
-+    omap_writel(0x48008530, 0x0000000c);	/* CM_AUTOIDLE_PLL */
-+    omap_writel(0x48008540,			/* CM_CLKSEL1_PLL */
-+                    (0x78 << 12) | (6 << 8));
-+    omap_writel(0x48008544, 2);			/* CM_CLKSEL2_PLL */
-+
-+    /* GPMC setup */
-+    n800_gpmc_init(s);
-+
-+    /* Video setup */
-+    n800_dss_init(&s->blizzard);
-+
-+    /* CPU setup */
-+    s->cpu->env->regs[15] = s->cpu->env->boot_info->loader_start;
-+}
-+
-+#define OMAP_TAG_NOKIA_BT	0x4e01
-+#define OMAP_TAG_WLAN_CX3110X	0x4e02
-+#define OMAP_TAG_CBUS		0x4e03
-+#define OMAP_TAG_EM_ASIC_BB5	0x4e04
-+
-+static int n800_atag_setup(struct arm_boot_info *info, void *p)
-+{
-+    uint8_t *b;
-+    uint16_t *w;
-+    uint32_t *l;
-+
-+    w = p;
-+
-+    stw_raw(w ++, OMAP_TAG_UART);		/* u16 tag */
-+    stw_raw(w ++, 4);				/* u16 len */
-+    stw_raw(w ++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
-+    w ++;
-+
-+    stw_raw(w ++, OMAP_TAG_EM_ASIC_BB5);	/* u16 tag */
-+    stw_raw(w ++, 4);				/* u16 len */
-+    stw_raw(w ++, N800_RETU_GPIO);		/* s16 retu_irq_gpio */
-+    stw_raw(w ++, N800_TAHVO_GPIO);		/* s16 tahvo_irq_gpio */
-+
-+    stw_raw(w ++, OMAP_TAG_CBUS);		/* u16 tag */
-+    stw_raw(w ++, 8);				/* u16 len */
-+    stw_raw(w ++, N800_CBUS_CLK_GPIO);		/* s16 clk_gpio */
-+    stw_raw(w ++, N800_CBUS_DAT_GPIO);		/* s16 dat_gpio */
-+    stw_raw(w ++, N800_CBUS_SEL_GPIO);		/* s16 sel_gpio */
-+    w ++;
-+
-+    stw_raw(w ++, OMAP_TAG_GPIO_SWITCH);	/* u16 tag */
-+    stw_raw(w ++, 20);				/* u16 len */
-+    strcpy((void *) w, "bat_cover");		/* char name[12] */
-+    w += 6;
-+    stw_raw(w ++, N800_BAT_COVER_GPIO);		/* u16 gpio */
-+    stw_raw(w ++, 0x01);
-+    stw_raw(w ++, 0);
-+    stw_raw(w ++, 0);
-+
-+    stw_raw(w ++, OMAP_TAG_GPIO_SWITCH);	/* u16 tag */
-+    stw_raw(w ++, 20);				/* u16 len */
-+    strcpy((void *) w, "cam_act");		/* char name[12] */
-+    w += 6;
-+    stw_raw(w ++, N800_CAM_ACT_GPIO);		/* u16 gpio */
-+    stw_raw(w ++, 0x20);
-+    stw_raw(w ++, 0);
-+    stw_raw(w ++, 0);
-+
-+    stw_raw(w ++, OMAP_TAG_GPIO_SWITCH);	/* u16 tag */
-+    stw_raw(w ++, 20);				/* u16 len */
-+    strcpy((void *) w, "cam_turn");		/* char name[12] */
-+    w += 6;
-+    stw_raw(w ++, N800_CAM_TURN_GPIO);		/* u16 gpio */
-+    stw_raw(w ++, 0x21);
-+    stw_raw(w ++, 0);
-+    stw_raw(w ++, 0);
-+
-+    stw_raw(w ++, OMAP_TAG_GPIO_SWITCH);	/* u16 tag */
-+    stw_raw(w ++, 20);				/* u16 len */
-+    strcpy((void *) w, "headphone");		/* char name[12] */
-+    w += 6;
-+    stw_raw(w ++, N800_HEADPHONE_GPIO);		/* u16 gpio */
-+    stw_raw(w ++, 0x11);
-+    stw_raw(w ++, 0);
-+    stw_raw(w ++, 0);
-+
-+    stw_raw(w ++, OMAP_TAG_NOKIA_BT);		/* u16 tag */
-+    stw_raw(w ++, 12);				/* u16 len */
-+    b = (void *) w;
-+    stb_raw(b ++, 0x01);			/* u8 chip_type	(CSR) */
-+    stb_raw(b ++, N800_BT_WKUP_GPIO);		/* u8 bt_wakeup_gpio */
-+    stb_raw(b ++, N800_BT_HOST_WKUP_GPIO);	/* u8 host_wakeup_gpio */
-+    stb_raw(b ++, N800_BT_RESET_GPIO);		/* u8 reset_gpio */
-+    stb_raw(b ++, 1);				/* u8 bt_uart */
-+    memset(b, 0, 6);				/* u8 bd_addr[6] */
-+    b += 6;
-+    stb_raw(b ++, 0x02);			/* u8 bt_sysclk (38.4) */
-+    w = (void *) b;
-+
-+    stw_raw(w ++, OMAP_TAG_WLAN_CX3110X);	/* u16 tag */
-+    stw_raw(w ++, 8);				/* u16 len */
-+    stw_raw(w ++, 0x25);			/* u8 chip_type */
-+    stw_raw(w ++, N800_WLAN_PWR_GPIO);		/* s16 power_gpio */
-+    stw_raw(w ++, N800_WLAN_IRQ_GPIO);		/* s16 irq_gpio */
-+    stw_raw(w ++, -1);				/* s16 spi_cs_gpio */
-+
-+    stw_raw(w ++, OMAP_TAG_MMC);		/* u16 tag */
-+    stw_raw(w ++, 16);				/* u16 len */
-+    stw_raw(w ++, 0xf);				/* unsigned flags */
-+    stw_raw(w ++, -1);				/* s16 power_pin */
-+    stw_raw(w ++, -1);				/* s16 switch_pin */
-+    stw_raw(w ++, -1);				/* s16 wp_pin */
-+    stw_raw(w ++, 0);				/* unsigned flags */
-+    stw_raw(w ++, 0);				/* s16 power_pin */
-+    stw_raw(w ++, 0);				/* s16 switch_pin */
-+    stw_raw(w ++, 0);				/* s16 wp_pin */
-+
-+    stw_raw(w ++, OMAP_TAG_TEA5761);		/* u16 tag */
-+    stw_raw(w ++, 4);				/* u16 len */
-+    stw_raw(w ++, N800_TEA5761_CS_GPIO);	/* u16 enable_gpio */
-+    w ++;
-+
-+    stw_raw(w ++, OMAP_TAG_PARTITION);		/* u16 tag */
-+    stw_raw(w ++, 28);				/* u16 len */
-+    strcpy((void *) w, "bootloader");		/* char name[16] */
-+    l = (void *) (w + 8);
-+    stl_raw(l ++, 0x00020000);			/* unsigned int size */
-+    stl_raw(l ++, 0x00000000);			/* unsigned int offset */
-+    stl_raw(l ++, 0x3);				/* unsigned int mask_flags */
-+    w = (void *) l;
-+
-+    stw_raw(w ++, OMAP_TAG_PARTITION);		/* u16 tag */
-+    stw_raw(w ++, 28);				/* u16 len */
-+    strcpy((void *) w, "config");		/* char name[16] */
-+    l = (void *) (w + 8);
-+    stl_raw(l ++, 0x00060000);			/* unsigned int size */
-+    stl_raw(l ++, 0x00020000);			/* unsigned int offset */
-+    stl_raw(l ++, 0x0);				/* unsigned int mask_flags */
-+    w = (void *) l;
-+
-+    stw_raw(w ++, OMAP_TAG_PARTITION);		/* u16 tag */
-+    stw_raw(w ++, 28);				/* u16 len */
-+    strcpy((void *) w, "kernel");		/* char name[16] */
-+    l = (void *) (w + 8);
-+    stl_raw(l ++, 0x00200000);			/* unsigned int size */
-+    stl_raw(l ++, 0x00080000);			/* unsigned int offset */
-+    stl_raw(l ++, 0x0);				/* unsigned int mask_flags */
-+    w = (void *) l;
-+
-+    stw_raw(w ++, OMAP_TAG_PARTITION);		/* u16 tag */
-+    stw_raw(w ++, 28);				/* u16 len */
-+    strcpy((void *) w, "initfs");		/* char name[16] */
-+    l = (void *) (w + 8);
-+    stl_raw(l ++, 0x00200000);			/* unsigned int size */
-+    stl_raw(l ++, 0x00280000);			/* unsigned int offset */
-+    stl_raw(l ++, 0x3);				/* unsigned int mask_flags */
-+    w = (void *) l;
-+
-+    stw_raw(w ++, OMAP_TAG_PARTITION);		/* u16 tag */
-+    stw_raw(w ++, 28);				/* u16 len */
-+    strcpy((void *) w, "rootfs");		/* char name[16] */
-+    l = (void *) (w + 8);
-+    stl_raw(l ++, 0x0fb80000);			/* unsigned int size */
-+    stl_raw(l ++, 0x00480000);			/* unsigned int offset */
-+    stl_raw(l ++, 0x3);				/* unsigned int mask_flags */
-+    w = (void *) l;
-+
-+    stw_raw(w ++, OMAP_TAG_BOOT_REASON);	/* u16 tag */
-+    stw_raw(w ++, 12);				/* u16 len */
-+#if 0
-+    strcpy((void *) w, "por");			/* char reason_str[12] */
-+    strcpy((void *) w, "charger");		/* char reason_str[12] */
-+    strcpy((void *) w, "32wd_to");		/* char reason_str[12] */
-+    strcpy((void *) w, "sw_rst");		/* char reason_str[12] */
-+    strcpy((void *) w, "mbus");			/* char reason_str[12] */
-+    strcpy((void *) w, "unknown");		/* char reason_str[12] */
-+    strcpy((void *) w, "swdg_to");		/* char reason_str[12] */
-+    strcpy((void *) w, "sec_vio");		/* char reason_str[12] */
-+    strcpy((void *) w, "pwr_key");		/* char reason_str[12] */
-+    strcpy((void *) w, "rtc_alarm");		/* char reason_str[12] */
-+#else
-+    strcpy((void *) w, "pwr_key");		/* char reason_str[12] */
-+#endif
-+    w += 6;
-+
-+    stw_raw(w ++, OMAP_TAG_VERSION_STR);	/* u16 tag */
-+    stw_raw(w ++, 24);				/* u16 len */
-+    strcpy((void *) w, "product");		/* char component[12] */
-+    w += 6;
-+    strcpy((void *) w, "RX-34");		/* char version[12] */
-+    w += 6;
-+
-+    stw_raw(w ++, OMAP_TAG_VERSION_STR);	/* u16 tag */
-+    stw_raw(w ++, 24);				/* u16 len */
-+    strcpy((void *) w, "hw-build");		/* char component[12] */
-+    w += 6;
-+    strcpy((void *) w, "QEMU");			/* char version[12] */
-+    w += 6;
-+
-+    stw_raw(w ++, OMAP_TAG_VERSION_STR);	/* u16 tag */
-+    stw_raw(w ++, 24);				/* u16 len */
-+    strcpy((void *) w, "nolo");			/* char component[12] */
-+    w += 6;
-+    strcpy((void *) w, "1.1.6-qemu");		/* char version[12] */
-+    w += 6;
-+
-+    stw_raw(w ++, OMAP_TAG_LCD);		/* u16 tag */
-+    stw_raw(w ++, 36);				/* u16 len */
-+    strcpy((void *) w, "QEMU LCD panel");	/* char panel_name[16] */
-+    w += 8;
-+    strcpy((void *) w, "blizzard");		/* char ctrl_name[16] */
-+    w += 8;
-+    stw_raw(w ++, 5);				/* TODO s16 nreset_gpio */
-+    stw_raw(w ++, 16);				/* u8 data_lines */
-+
-+    return (void *) w - p;
-+}
-+
-+static struct arm_boot_info n800_binfo = {
-+    .loader_start = OMAP2_Q2_BASE,
-+    /* Actually two chips of 0x4000000 bytes each */
-+    .ram_size = 0x08000000,
-+    .board_id = 0x4f7,
-+    .atag_board = n800_atag_setup,
-+};
-+
-+static void n800_init(int ram_size, int vga_ram_size,
-+                const char *boot_device, DisplayState *ds,
-+                const char *kernel_filename, const char *kernel_cmdline,
-+                const char *initrd_filename, const char *cpu_model)
-+{
-+    struct n800_s *s = (struct n800_s *) qemu_mallocz(sizeof(*s));
-+    int sdram_size = n800_binfo.ram_size;
-+    int onenandram_size = 0x00010000;
-+
-+    if (ram_size < sdram_size + onenandram_size + OMAP242X_SRAM_SIZE) {
-+        fprintf(stderr, "This architecture uses %i bytes of memory\n",
-+                        sdram_size + onenandram_size + OMAP242X_SRAM_SIZE);
-+        exit(1);
-+    }
-+
-+    s->cpu = omap2420_mpu_init(sdram_size, NULL, cpu_model);
-+
-+    n800_gpio_setup(s);
-+    n800_nand_setup(s);
-+    n800_i2c_setup(s);
-+    n800_tsc_setup(s);
-+    n800_spi_setup(s);
-+    n800_dss_setup(s, ds);
-+    n800_cbus_setup(s);
-+
-+    /* Setup initial (reset) machine state */
-+
-+    /* Start at the OneNAND bootloader.  */
-+    s->cpu->env->regs[15] = 0;
-+
-+    if (kernel_filename) {
-+        /* Or at the linux loader.  */
-+        n800_binfo.kernel_filename = kernel_filename;
-+        n800_binfo.kernel_cmdline = kernel_cmdline;
-+        n800_binfo.initrd_filename = initrd_filename;
-+        arm_load_kernel(s->cpu->env, &n800_binfo);
-+
-+        qemu_register_reset(n800_boot_init, s);
-+        n800_boot_init(s);
-+    }
-+
-+    dpy_resize(ds, 800, 480);
-+}
-+
-+QEMUMachine n800_machine = {
-+    "n800",
-+    "Nokia N800 aka. RX-34 tablet (OMAP2420)",
-+    n800_init,
-+};
-diff --git a/hw/omap.h b/hw/omap.h
-index ecfd54d..de838c9 100644
---- a/hw/omap.h
-+++ b/hw/omap.h
-@@ -22,6 +22,7 @@
- # define hw_omap_h		"omap.h"
- 
- # define OMAP_EMIFS_BASE	0x00000000
-+# define OMAP2_Q0_BASE		0x00000000
- # define OMAP_CS0_BASE		0x00000000
- # define OMAP_CS1_BASE		0x04000000
- # define OMAP_CS2_BASE		0x08000000
-@@ -29,18 +30,26 @@
- # define OMAP_EMIFF_BASE	0x10000000
- # define OMAP_IMIF_BASE		0x20000000
- # define OMAP_LOCALBUS_BASE	0x30000000
-+# define OMAP2_Q1_BASE		0x40000000
-+# define OMAP2_L4_BASE		0x48000000
-+# define OMAP2_SRAM_BASE	0x40200000
-+# define OMAP2_L3_BASE		0x68000000
-+# define OMAP2_Q2_BASE		0x80000000
-+# define OMAP2_Q3_BASE		0xc0000000
- # define OMAP_MPUI_BASE		0xe1000000
- 
- # define OMAP730_SRAM_SIZE	0x00032000
- # define OMAP15XX_SRAM_SIZE	0x00030000
- # define OMAP16XX_SRAM_SIZE	0x00004000
- # define OMAP1611_SRAM_SIZE	0x0003e800
-+# define OMAP242X_SRAM_SIZE	0x000a0000
-+# define OMAP243X_SRAM_SIZE	0x00010000
- # define OMAP_CS0_SIZE		0x04000000
- # define OMAP_CS1_SIZE		0x04000000
- # define OMAP_CS2_SIZE		0x04000000
- # define OMAP_CS3_SIZE		0x04000000
- 
--/* omap1_clk.c */
-+/* omap_clk.c */
- struct omap_mpu_state_s;
- typedef struct clk *omap_clk;
- omap_clk omap_findclk(struct omap_mpu_state_s *mpu, const char *name);
-@@ -55,14 +64,41 @@ int64_t omap_clk_getrate(omap_clk clk);
- void omap_clk_reparent(omap_clk clk, omap_clk parent);
- 
- /* omap[123].c */
-+struct omap_l4_s;
-+struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num);
-+
-+struct omap_target_agent_s;
-+struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus, int cs);
-+target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
-+                int iotype);
-+
- struct omap_intr_handler_s;
- struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
--                unsigned long size, unsigned char nbanks,
-+                unsigned long size, unsigned char nbanks, qemu_irq **pins,
-                 qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk clk);
--
--struct omap_target_agent_s;
--static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta,
--                int region, int iotype) { return 0; }
-+struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base,
-+                int size, int nbanks, qemu_irq **pins,
-+                qemu_irq parent_irq, qemu_irq parent_fiq,
-+                omap_clk fclk, omap_clk iclk);
-+void omap_inth_reset(struct omap_intr_handler_s *s);
-+
-+struct omap_prcm_s;
-+struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
-+                qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
-+                struct omap_mpu_state_s *mpu);
-+
-+struct omap_sysctl_s;
-+struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
-+                omap_clk iclk, struct omap_mpu_state_s *mpu);
-+
-+struct omap_sdrc_s;
-+struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base);
-+
-+struct omap_gpmc_s;
-+struct omap_gpmc_s *omap_gpmc_init(target_phys_addr_t base, qemu_irq irq);
-+void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, int iomemtype,
-+                void (*base_upd)(void *opaque, target_phys_addr_t new),
-+                void (*unmap)(void *opaque), void *opaque);
- 
- /*
-  * Common IRQ numbers for level 1 interrupt handler
-@@ -295,10 +331,20 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta,
-  * OMAP-24xx common IRQ numbers
-  */
- # define OMAP_INT_24XX_SYS_NIRQ		7
-+# define OMAP_INT_24XX_L3_IRQ		10
-+# define OMAP_INT_24XX_PRCM_MPU_IRQ	11
- # define OMAP_INT_24XX_SDMA_IRQ0	12
- # define OMAP_INT_24XX_SDMA_IRQ1	13
- # define OMAP_INT_24XX_SDMA_IRQ2	14
- # define OMAP_INT_24XX_SDMA_IRQ3	15
-+# define OMAP_INT_243X_MCBSP2_IRQ	16
-+# define OMAP_INT_243X_MCBSP3_IRQ	17
-+# define OMAP_INT_243X_MCBSP4_IRQ	18
-+# define OMAP_INT_243X_MCBSP5_IRQ	19
-+# define OMAP_INT_24XX_GPMC_IRQ		20
-+# define OMAP_INT_24XX_GUFFAW_IRQ	21
-+# define OMAP_INT_24XX_IVA_IRQ		22
-+# define OMAP_INT_24XX_EAC_IRQ		23
- # define OMAP_INT_24XX_CAM_IRQ		24
- # define OMAP_INT_24XX_DSS_IRQ		25
- # define OMAP_INT_24XX_MAIL_U0_MPU	26
-@@ -308,8 +354,10 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta,
- # define OMAP_INT_24XX_GPIO_BANK2	30
- # define OMAP_INT_24XX_GPIO_BANK3	31
- # define OMAP_INT_24XX_GPIO_BANK4	32
--# define OMAP_INT_24XX_GPIO_BANK5	33
-+# define OMAP_INT_243X_GPIO_BANK5	33
- # define OMAP_INT_24XX_MAIL_U3_MPU	34
-+# define OMAP_INT_24XX_WDT3		35
-+# define OMAP_INT_24XX_WDT4		36
- # define OMAP_INT_24XX_GPTIMER1		37
- # define OMAP_INT_24XX_GPTIMER2		38
- # define OMAP_INT_24XX_GPTIMER3		39
-@@ -322,10 +370,24 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta,
- # define OMAP_INT_24XX_GPTIMER10	46
- # define OMAP_INT_24XX_GPTIMER11	47
- # define OMAP_INT_24XX_GPTIMER12	48
-+# define OMAP_INT_24XX_PKA_IRQ		50
-+# define OMAP_INT_24XX_SHA1MD5_IRQ	51
-+# define OMAP_INT_24XX_RNG_IRQ		52
-+# define OMAP_INT_24XX_MG_IRQ		53
-+# define OMAP_INT_24XX_I2C1_IRQ		56
-+# define OMAP_INT_24XX_I2C2_IRQ		57
- # define OMAP_INT_24XX_MCBSP1_IRQ_TX	59
- # define OMAP_INT_24XX_MCBSP1_IRQ_RX	60
- # define OMAP_INT_24XX_MCBSP2_IRQ_TX	62
- # define OMAP_INT_24XX_MCBSP2_IRQ_RX	63
-+# define OMAP_INT_243X_MCBSP1_IRQ	64
-+# define OMAP_INT_24XX_MCSPI1_IRQ	65
-+# define OMAP_INT_24XX_MCSPI2_IRQ	66
-+# define OMAP_INT_24XX_SSI1_IRQ0	67
-+# define OMAP_INT_24XX_SSI1_IRQ1	68
-+# define OMAP_INT_24XX_SSI2_IRQ0	69
-+# define OMAP_INT_24XX_SSI2_IRQ1	70
-+# define OMAP_INT_24XX_SSI_GDD_IRQ	71
- # define OMAP_INT_24XX_UART1_IRQ	72
- # define OMAP_INT_24XX_UART2_IRQ	73
- # define OMAP_INT_24XX_UART3_IRQ	74
-@@ -335,10 +397,15 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta,
- # define OMAP_INT_24XX_USB_IRQ_HGEN	78
- # define OMAP_INT_24XX_USB_IRQ_HSOF	79
- # define OMAP_INT_24XX_USB_IRQ_OTG	80
-+# define OMAP_INT_24XX_VLYNQ_IRQ	81
- # define OMAP_INT_24XX_MMC_IRQ		83
-+# define OMAP_INT_24XX_MS_IRQ		84
-+# define OMAP_INT_24XX_FAC_IRQ		85
-+# define OMAP_INT_24XX_MCSPI3_IRQ	91
- # define OMAP_INT_243X_HS_USB_MC	92
- # define OMAP_INT_243X_HS_USB_DMA	93
- # define OMAP_INT_243X_CARKIT		94
-+# define OMAP_INT_34XX_GPTIMER12	95
- 
- /* omap_dma.c */
- enum omap_dma_model {
-@@ -352,6 +419,9 @@ struct omap_dma_s;
- struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
-                 qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk,
-                 enum omap_dma_model model);
-+struct omap_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
-+                struct omap_mpu_state_s *mpu, int fifo,
-+                int chans, omap_clk iclk, omap_clk fclk);
- void omap_dma_reset(struct omap_dma_s *s);
- 
- struct dma_irq_map {
-@@ -367,7 +437,7 @@ enum omap_dma_port {
-     tipb,
-     local,	/* omap16xx: ocp_t2 */
-     tipb_mpui,
--    omap_dma_port_last,
-+    __omap_dma_port_last,
- };
- 
- typedef enum {
-@@ -488,11 +558,83 @@ struct omap_dma_lcd_channel_s {
- # define OMAP_DMA_MMC2_RX		55
- # define OMAP_DMA_CRYPTO_DES_OUT	56
- 
-+/*
-+ * DMA request numbers for the OMAP2
-+ */
-+# define OMAP24XX_DMA_NO_DEVICE		0
-+# define OMAP24XX_DMA_XTI_DMA		1	/* Not in OMAP2420 */
-+# define OMAP24XX_DMA_EXT_DMAREQ0	2
-+# define OMAP24XX_DMA_EXT_DMAREQ1	3
-+# define OMAP24XX_DMA_GPMC		4
-+# define OMAP24XX_DMA_GFX		5	/* Not in OMAP2420 */
-+# define OMAP24XX_DMA_DSS		6
-+# define OMAP24XX_DMA_VLYNQ_TX		7	/* Not in OMAP2420 */
-+# define OMAP24XX_DMA_CWT		8	/* Not in OMAP2420 */
-+# define OMAP24XX_DMA_AES_TX		9	/* Not in OMAP2420 */
-+# define OMAP24XX_DMA_AES_RX		10	/* Not in OMAP2420 */
-+# define OMAP24XX_DMA_DES_TX		11	/* Not in OMAP2420 */
-+# define OMAP24XX_DMA_DES_RX		12	/* Not in OMAP2420 */
-+# define OMAP24XX_DMA_SHA1MD5_RX	13	/* Not in OMAP2420 */
-+# define OMAP24XX_DMA_EXT_DMAREQ2	14
-+# define OMAP24XX_DMA_EXT_DMAREQ3	15
-+# define OMAP24XX_DMA_EXT_DMAREQ4	16
-+# define OMAP24XX_DMA_EAC_AC_RD		17
-+# define OMAP24XX_DMA_EAC_AC_WR		18
-+# define OMAP24XX_DMA_EAC_MD_UL_RD	19
-+# define OMAP24XX_DMA_EAC_MD_UL_WR	20
-+# define OMAP24XX_DMA_EAC_MD_DL_RD	21
-+# define OMAP24XX_DMA_EAC_MD_DL_WR	22
-+# define OMAP24XX_DMA_EAC_BT_UL_RD	23
-+# define OMAP24XX_DMA_EAC_BT_UL_WR	24
-+# define OMAP24XX_DMA_EAC_BT_DL_RD	25
-+# define OMAP24XX_DMA_EAC_BT_DL_WR	26
-+# define OMAP24XX_DMA_I2C1_TX		27
-+# define OMAP24XX_DMA_I2C1_RX		28
-+# define OMAP24XX_DMA_I2C2_TX		29
-+# define OMAP24XX_DMA_I2C2_RX		30
-+# define OMAP24XX_DMA_MCBSP1_TX		31
-+# define OMAP24XX_DMA_MCBSP1_RX		32
-+# define OMAP24XX_DMA_MCBSP2_TX		33
-+# define OMAP24XX_DMA_MCBSP2_RX		34
-+# define OMAP24XX_DMA_SPI1_TX0		35
-+# define OMAP24XX_DMA_SPI1_RX0		36
-+# define OMAP24XX_DMA_SPI1_TX1		37
-+# define OMAP24XX_DMA_SPI1_RX1		38
-+# define OMAP24XX_DMA_SPI1_TX2		39
-+# define OMAP24XX_DMA_SPI1_RX2		40
-+# define OMAP24XX_DMA_SPI1_TX3		41
-+# define OMAP24XX_DMA_SPI1_RX3		42
-+# define OMAP24XX_DMA_SPI2_TX0		43
-+# define OMAP24XX_DMA_SPI2_RX0		44
-+# define OMAP24XX_DMA_SPI2_TX1		45
-+# define OMAP24XX_DMA_SPI2_RX1		46
-+
-+# define OMAP24XX_DMA_UART1_TX		49
-+# define OMAP24XX_DMA_UART1_RX		50
-+# define OMAP24XX_DMA_UART2_TX		51
-+# define OMAP24XX_DMA_UART2_RX		52
-+# define OMAP24XX_DMA_UART3_TX		53
-+# define OMAP24XX_DMA_UART3_RX		54
-+# define OMAP24XX_DMA_USB_W2FC_TX0	55
-+# define OMAP24XX_DMA_USB_W2FC_RX0	56
-+# define OMAP24XX_DMA_USB_W2FC_TX1	57
-+# define OMAP24XX_DMA_USB_W2FC_RX1	58
-+# define OMAP24XX_DMA_USB_W2FC_TX2	59
-+# define OMAP24XX_DMA_USB_W2FC_RX2	60
-+# define OMAP24XX_DMA_MMC1_TX		61
-+# define OMAP24XX_DMA_MMC1_RX		62
-+# define OMAP24XX_DMA_MS		63	/* Not in OMAP2420 */
-+# define OMAP24XX_DMA_EXT_DMAREQ5	64
-+
- /* omap[123].c */
- struct omap_mpu_timer_s;
- struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base,
-                 qemu_irq irq, omap_clk clk);
- 
-+struct omap_gp_timer_s;
-+struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
-+                qemu_irq irq, omap_clk fclk, omap_clk iclk);
-+
- struct omap_watchdog_timer_s;
- struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t base,
-                 qemu_irq irq, omap_clk clk);
-@@ -501,13 +643,21 @@ struct omap_32khz_timer_s;
- struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t base,
-                 qemu_irq irq, omap_clk clk);
- 
-+void omap_synctimer_init(struct omap_target_agent_s *ta,
-+                struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk);
-+
- struct omap_tipb_bridge_s;
- struct omap_tipb_bridge_s *omap_tipb_bridge_init(target_phys_addr_t base,
-                 qemu_irq abort_irq, omap_clk clk);
- 
- struct omap_uart_s;
- struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
--                qemu_irq irq, omap_clk clk, CharDriverState *chr);
-+                qemu_irq irq, omap_clk fclk, omap_clk iclk,
-+                qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr);
-+struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta,
-+                qemu_irq irq, omap_clk fclk, omap_clk iclk,
-+                qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr);
-+void omap_uart_reset(struct omap_uart_s *s);
- 
- struct omap_mpuio_s;
- struct omap_mpuio_s *omap_mpuio_init(target_phys_addr_t base,
-@@ -523,6 +673,12 @@ struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
- qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s);
- void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler);
- 
-+struct omap_gpif_s;
-+struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
-+                qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules);
-+qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start);
-+void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler);
-+
- struct uwire_slave_s {
-     uint16_t (*receive)(void *opaque);
-     void (*send)(void *opaque, uint16_t data);
-@@ -534,6 +690,13 @@ struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
- void omap_uwire_attach(struct omap_uwire_s *s,
-                 struct uwire_slave_s *slave, int chipselect);
- 
-+struct omap_mcspi_s;
-+struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum,
-+                qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk);
-+void omap_mcspi_attach(struct omap_mcspi_s *s,
-+                uint32_t (*txrx)(void *opaque, uint32_t), void *opaque,
-+                int chipselect);
-+
- struct omap_rtc_s;
- struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
-                 qemu_irq *irq, omap_clk clk);
-@@ -570,6 +733,9 @@ void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave);
- struct omap_lpg_s;
- struct omap_lpg_s *omap_lpg_init(target_phys_addr_t base, omap_clk clk);
- 
-+void omap_tap_init(struct omap_target_agent_s *ta,
-+                struct omap_mpu_state_s *mpu);
-+
- /* omap_lcdc.c */
- struct omap_lcd_panel_s;
- void omap_lcdc_reset(struct omap_lcd_panel_s *s);
-@@ -577,13 +743,33 @@ struct omap_lcd_panel_s *omap_lcdc_init(target_phys_addr_t base, qemu_irq irq,
-                 struct omap_dma_lcd_channel_s *dma, DisplayState *ds,
-                 ram_addr_t imif_base, ram_addr_t emiff_base, omap_clk clk);
- 
-+/* omap_dss.c */
-+struct rfbi_chip_s {
-+    void *opaque;
-+    void (*write)(void *opaque, int dc, uint16_t value);
-+    void (*block)(void *opaque, int dc, void *buf, size_t len, int pitch);
-+    uint16_t (*read)(void *opaque, int dc);
-+};
-+struct omap_dss_s;
-+void omap_dss_reset(struct omap_dss_s *s);
-+struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
-+                target_phys_addr_t l3_base, DisplayState *ds,
-+                qemu_irq irq, qemu_irq drq,
-+                omap_clk fck1, omap_clk fck2, omap_clk ck54m,
-+                omap_clk ick1, omap_clk ick2);
-+void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip);
-+
- /* omap_mmc.c */
- struct omap_mmc_s;
- struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
-                 BlockDriverState *bd,
-                 qemu_irq irq, qemu_irq dma[], omap_clk clk);
-+struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
-+                BlockDriverState *bd, qemu_irq irq, qemu_irq dma[],
-+                omap_clk fclk, omap_clk iclk);
- void omap_mmc_reset(struct omap_mmc_s *s);
- void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover);
-+void omap_mmc_enable(struct omap_mmc_s *s, int enable);
- 
- /* omap_i2c.c */
- struct omap_i2c_s;
-@@ -596,14 +782,37 @@ i2c_bus *omap_i2c_bus(struct omap_i2c_s *s);
- 
- # define cpu_is_omap310(cpu)		(cpu->mpu_model == omap310)
- # define cpu_is_omap1510(cpu)		(cpu->mpu_model == omap1510)
-+# define cpu_is_omap1610(cpu)		(cpu->mpu_model == omap1610)
-+# define cpu_is_omap1710(cpu)		(cpu->mpu_model == omap1710)
-+# define cpu_is_omap2410(cpu)		(cpu->mpu_model == omap2410)
-+# define cpu_is_omap2420(cpu)		(cpu->mpu_model == omap2420)
-+# define cpu_is_omap2430(cpu)		(cpu->mpu_model == omap2430)
-+# define cpu_is_omap3430(cpu)		(cpu->mpu_model == omap3430)
-+
- # define cpu_is_omap15xx(cpu)		\
-         (cpu_is_omap310(cpu) || cpu_is_omap1510(cpu))
--# define cpu_class_omap1(cpu)		1
-+# define cpu_is_omap16xx(cpu)		\
-+        (cpu_is_omap1610(cpu) || cpu_is_omap1710(cpu))
-+# define cpu_is_omap24xx(cpu)		\
-+        (cpu_is_omap2410(cpu) || cpu_is_omap2420(cpu) || cpu_is_omap2430(cpu))
-+
-+# define cpu_class_omap1(cpu)		\
-+        (cpu_is_omap15xx(cpu) || cpu_is_omap16xx(cpu))
-+# define cpu_class_omap2(cpu)		cpu_is_omap24xx(cpu)
-+# define cpu_class_omap3(cpu)		cpu_is_omap3430(cpu)
- 
- struct omap_mpu_state_s {
--    enum omap1_mpu_model {
-+    enum omap_mpu_model {
-         omap310,
-         omap1510,
-+        omap1610,
-+        omap1710,
-+        omap2410,
-+        omap2420,
-+        omap2422,
-+        omap2423,
-+        omap2430,
-+        omap3430,
-     } mpu_model;
- 
-     CPUState *env;
-@@ -620,7 +829,7 @@ struct omap_mpu_state_s {
-                         target_phys_addr_t offset, uint32_t value);
-         int (*addr_valid)(struct omap_mpu_state_s *s,
-                         target_phys_addr_t addr);
--    } port[omap_dma_port_last];
-+    } port[__omap_dma_port_last];
- 
-     unsigned long sdram_size;
-     unsigned long sram_size;
-@@ -656,7 +865,7 @@ struct omap_mpu_state_s {
-         omap_clk clk;
-     } pwt;
- 
--    struct omap_i2c_s *i2c;
-+    struct omap_i2c_s *i2c[2];
- 
-     struct omap_rtc_s *rtc;
- 
-@@ -722,7 +931,38 @@ struct omap_mpu_state_s {
-         uint16_t dsp_idlect2;
-         uint16_t dsp_rstct2;
-     } clkm;
--} *omap310_mpu_init(unsigned long sdram_size,
-+
-+    /* OMAP2-only peripherals */
-+    struct omap_l4_s *l4;
-+
-+    struct omap_gp_timer_s *gptimer[12];
-+
-+    target_phys_addr_t tap_base;
-+
-+    struct omap_synctimer_s {
-+        target_phys_addr_t base;
-+        uint32_t val;
-+        uint16_t readh;
-+    } synctimer;
-+
-+    struct omap_prcm_s *prcm;
-+    struct omap_sdrc_s *sdrc;
-+    struct omap_gpmc_s *gpmc;
-+    struct omap_sysctl_s *sysc;
-+
-+    struct omap_gpif_s *gpif;
-+
-+    struct omap_mcspi_s *mcspi[2];
-+
-+    struct omap_dss_s *dss;
-+};
-+
-+/* omap1.c */
-+struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
-+                DisplayState *ds, const char *core);
-+
-+/* omap2.c */
-+struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
-                 DisplayState *ds, const char *core);
- 
- # if TARGET_PHYS_ADDR_BITS == 32
-@@ -743,24 +983,46 @@ uint32_t omap_badwidth_read32(void *opaque, target_phys_addr_t addr);
- void omap_badwidth_write32(void *opaque, target_phys_addr_t addr,
-                 uint32_t value);
- 
-+void omap_mpu_wakeup(void *opaque, int irq, int req);
-+
- # define OMAP_BAD_REG(paddr)		\
--        printf("%s: Bad register " OMAP_FMT_plx "\n", __FUNCTION__, paddr)
-+        fprintf(stderr, "%s: Bad register " OMAP_FMT_plx "\n",	\
-+                        __FUNCTION__, paddr)
- # define OMAP_RO_REG(paddr)		\
--        printf("%s: Read-only register " OMAP_FMT_plx "\n",	\
-+        fprintf(stderr, "%s: Read-only register " OMAP_FMT_plx "\n",	\
-                         __FUNCTION__, paddr)
- 
-+/* OMAP-specific Linux bootloader tags for the ATAG_BOARD area
-+   (Board-specifc tags are not here)  */
-+#define OMAP_TAG_CLOCK		0x4f01
-+#define OMAP_TAG_MMC		0x4f02
-+#define OMAP_TAG_SERIAL_CONSOLE	0x4f03
-+#define OMAP_TAG_USB		0x4f04
-+#define OMAP_TAG_LCD		0x4f05
-+#define OMAP_TAG_GPIO_SWITCH	0x4f06
-+#define OMAP_TAG_UART		0x4f07
-+#define OMAP_TAG_FBMEM		0x4f08
-+#define OMAP_TAG_STI_CONSOLE	0x4f09
-+#define OMAP_TAG_CAMERA_SENSOR	0x4f0a
-+#define OMAP_TAG_PARTITION	0x4f0b
-+#define OMAP_TAG_TEA5761	0x4f10
-+#define OMAP_TAG_TMP105		0x4f11
-+#define OMAP_TAG_BOOT_REASON	0x4f80
-+#define OMAP_TAG_FLASH_PART_STR	0x4f81
-+#define OMAP_TAG_VERSION_STR	0x4f82
-+
- # define TCMI_VERBOSE			1
- //# define MEM_VERBOSE			1
- 
- # ifdef TCMI_VERBOSE
- #  define OMAP_8B_REG(paddr)		\
--        printf("%s: 8-bit register " OMAP_FMT_plx "\n",	\
-+        fprintf(stderr, "%s: 8-bit register " OMAP_FMT_plx "\n",	\
-                         __FUNCTION__, paddr)
- #  define OMAP_16B_REG(paddr)		\
--        printf("%s: 16-bit register " OMAP_FMT_plx "\n",	\
-+        fprintf(stderr, "%s: 16-bit register " OMAP_FMT_plx "\n",	\
-                         __FUNCTION__, paddr)
- #  define OMAP_32B_REG(paddr)		\
--        printf("%s: 32-bit register " OMAP_FMT_plx "\n",	\
-+        fprintf(stderr, "%s: 32-bit register " OMAP_FMT_plx "\n",	\
-                         __FUNCTION__, paddr)
- # else
- #  define OMAP_8B_REG(paddr)
-@@ -863,10 +1125,4 @@ inline static int debug_register_io_memory(int io_index,
- #  define cpu_register_io_memory	debug_register_io_memory
- # endif
- 
--/* Not really omap specific, but is the only thing that uses the
--   uwire interface.  */
--/* tsc210x.c */
--struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio);
--struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip);
--
- #endif /* hw_omap_h */
-diff --git a/hw/omap1.c b/hw/omap1.c
-index 3888e80..d81cbce 100644
---- a/hw/omap1.c
-+++ b/hw/omap1.c
-@@ -23,10 +23,11 @@
- #include "omap.h"
- #include "sysemu.h"
- #include "qemu-timer.h"
-+#include "qemu-char.h"
- /* We use pc-style serial ports.  */
- #include "pc.h"
- 
--/* Should signal the TCMI */
-+/* Should signal the TCMI/GPMC */
- uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr)
- {
-     uint8_t ret;
-@@ -86,6 +87,7 @@ struct omap_intr_handler_bank_s {
-     uint32_t mask;
-     uint32_t fiq;
-     uint32_t sens_edge;
-+    uint32_t swi;
-     unsigned char priority[32];
- };
- 
-@@ -94,11 +96,14 @@ struct omap_intr_handler_s {
-     qemu_irq parent_intr[2];
-     target_phys_addr_t base;
-     unsigned char nbanks;
-+    int level_only;
- 
-     /* state */
-     uint32_t new_agr[2];
-     int sir_intr[2];
--    struct omap_intr_handler_bank_s banks[];
-+    int autoidle;
-+    uint32_t mask;
-+    struct omap_intr_handler_bank_s bank[];
- };
- 
- static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq)
-@@ -113,11 +118,11 @@ static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq)
-      * If all interrupts have the same priority, the default order is IRQ_N,
-      * IRQ_N-1,...,IRQ_0. */
-     for (j = 0; j < s->nbanks; ++j) {
--        level = s->banks[j].irqs & ~s->banks[j].mask &
--                (is_fiq ? s->banks[j].fiq : ~s->banks[j].fiq);
-+        level = s->bank[j].irqs & ~s->bank[j].mask &
-+                (is_fiq ? s->bank[j].fiq : ~s->bank[j].fiq);
-         for (f = ffs(level), i = f - 1, level >>= f - 1; f; i += f,
-                         level >>= f) {
--            p = s->banks[j].priority[i];
-+            p = s->bank[j].priority[i];
-             if (p <= p_intr) {
-                 p_intr = p;
-                 sir_intr = 32 * j + i;
-@@ -134,10 +139,10 @@ static inline void omap_inth_update(struct omap_intr_handler_s *s, int is_fiq)
-     uint32_t has_intr = 0;
- 
-     for (i = 0; i < s->nbanks; ++i)
--        has_intr |= s->banks[i].irqs & ~s->banks[i].mask &
--                (is_fiq ? s->banks[i].fiq : ~s->banks[i].fiq);
-+        has_intr |= s->bank[i].irqs & ~s->bank[i].mask &
-+                (is_fiq ? s->bank[i].fiq : ~s->bank[i].fiq);
- 
--    if (s->new_agr[is_fiq] && has_intr) {
-+    if (s->new_agr[is_fiq] & has_intr & s->mask) {
-         s->new_agr[is_fiq] = 0;
-         omap_inth_sir_update(s, is_fiq);
-         qemu_set_irq(s->parent_intr[is_fiq], 1);
-@@ -152,13 +157,13 @@ static void omap_set_intr(void *opaque, int irq, int req)
-     struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
-     uint32_t rise;
- 
--    struct omap_intr_handler_bank_s *bank = &ih->banks[irq >> 5];
-+    struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
-     int n = irq & 31;
- 
-     if (req) {
-         rise = ~bank->irqs & (1 << n);
-         if (~bank->sens_edge & (1 << n))
--            rise &= ~bank->inputs & (1 << n);
-+            rise &= ~bank->inputs;
- 
-         bank->inputs |= (1 << n);
-         if (rise) {
-@@ -173,13 +178,33 @@ static void omap_set_intr(void *opaque, int irq, int req)
-     }
- }
- 
-+/* Simplified version with no edge detection */
-+static void omap_set_intr_noedge(void *opaque, int irq, int req)
-+{
-+    struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
-+    uint32_t rise;
-+
-+    struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
-+    int n = irq & 31;
-+
-+    if (req) {
-+        rise = ~bank->inputs & (1 << n);
-+        if (rise) {
-+            bank->irqs |= bank->inputs |= rise;
-+            omap_inth_update(ih, 0);
-+            omap_inth_update(ih, 1);
-+        }
-+    } else
-+        bank->irqs = (bank->inputs &= ~(1 << n)) | bank->swi;
-+}
-+
- static uint32_t omap_inth_read(void *opaque, target_phys_addr_t addr)
- {
-     struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
-     int i, offset = addr - s->base;
-     int bank_no = offset >> 8;
-     int line_no;
--    struct omap_intr_handler_bank_s *bank = &s->banks[bank_no];
-+    struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
-     offset &= 0xff;
- 
-     switch (offset) {
-@@ -194,7 +219,7 @@ static uint32_t omap_inth_read(void *opaque, target_phys_addr_t addr)
-         if (bank_no != 0)
-             break;
-         line_no = s->sir_intr[(offset - 0x10) >> 2];
--        bank = &s->banks[line_no >> 5];
-+        bank = &s->bank[line_no >> 5];
-         i = line_no & 31;
-         if (((bank->sens_edge >> i) & 1) == INT_FALLING_EDGE)
-             bank->irqs &= ~(1 << i);
-@@ -256,7 +281,7 @@ static void omap_inth_write(void *opaque, target_phys_addr_t addr,
-     struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
-     int i, offset = addr - s->base;
-     int bank_no = offset >> 8;
--    struct omap_intr_handler_bank_s *bank = &s->banks[bank_no];
-+    struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
-     offset &= 0xff;
- 
-     switch (offset) {
-@@ -360,25 +385,31 @@ void omap_inth_reset(struct omap_intr_handler_s *s)
-     int i;
- 
-     for (i = 0; i < s->nbanks; ++i){
--        s->banks[i].irqs = 0x00000000;
--        s->banks[i].mask = 0xffffffff;
--        s->banks[i].sens_edge = 0x00000000;
--        s->banks[i].fiq = 0x00000000;
--        s->banks[i].inputs = 0x00000000;
--        memset(s->banks[i].priority, 0, sizeof(s->banks[i].priority));
-+        s->bank[i].irqs = 0x00000000;
-+        s->bank[i].mask = 0xffffffff;
-+        s->bank[i].sens_edge = 0x00000000;
-+        s->bank[i].fiq = 0x00000000;
-+        s->bank[i].inputs = 0x00000000;
-+        s->bank[i].swi = 0x00000000;
-+        memset(s->bank[i].priority, 0, sizeof(s->bank[i].priority));
-+
-+        if (s->level_only)
-+            s->bank[i].sens_edge = 0xffffffff;
-     }
- 
-     s->new_agr[0] = ~0;
-     s->new_agr[1] = ~0;
-     s->sir_intr[0] = 0;
-     s->sir_intr[1] = 0;
-+    s->autoidle = 0;
-+    s->mask = ~0;
- 
-     qemu_set_irq(s->parent_intr[0], 0);
-     qemu_set_irq(s->parent_intr[1], 0);
- }
- 
- struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
--                unsigned long size, unsigned char nbanks,
-+                unsigned long size, unsigned char nbanks, qemu_irq **pins,
-                 qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk clk)
- {
-     int iomemtype;
-@@ -391,6 +422,8 @@ struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
-     s->base = base;
-     s->nbanks = nbanks;
-     s->pins = qemu_allocate_irqs(omap_set_intr, s, nbanks * 32);
-+    if (pins)
-+        *pins = s->pins;
- 
-     omap_inth_reset(s);
- 
-@@ -401,6 +434,227 @@ struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
-     return s;
- }
- 
-+static uint32_t omap2_inth_read(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
-+    int offset = addr - s->base;
-+    int bank_no, line_no;
-+    struct omap_intr_handler_bank_s *bank = 0;
-+
-+    if ((offset & 0xf80) == 0x80) {
-+        bank_no = (offset & 0x60) >> 5;
-+        if (bank_no < s->nbanks) {
-+            offset &= ~0x60;
-+            bank = &s->bank[bank_no];
-+        }
-+    }
-+
-+    switch (offset) {
-+    case 0x00:	/* INTC_REVISION */
-+        return 0x21;
-+
-+    case 0x10:	/* INTC_SYSCONFIG */
-+        return (s->autoidle >> 2) & 1;
-+
-+    case 0x14:	/* INTC_SYSSTATUS */
-+        return 1;						/* RESETDONE */
-+
-+    case 0x40:	/* INTC_SIR_IRQ */
-+        return s->sir_intr[0];
-+
-+    case 0x44:	/* INTC_SIR_FIQ */
-+        return s->sir_intr[1];
-+
-+    case 0x48:	/* INTC_CONTROL */
-+        return (!s->mask) << 2;					/* GLOBALMASK */
-+
-+    case 0x4c:	/* INTC_PROTECTION */
-+        return 0;
-+
-+    case 0x50:	/* INTC_IDLE */
-+        return s->autoidle & 3;
-+
-+    /* Per-bank registers */
-+    case 0x80:	/* INTC_ITR */
-+        return bank->inputs;
-+
-+    case 0x84:	/* INTC_MIR */
-+        return bank->mask;
-+
-+    case 0x88:	/* INTC_MIR_CLEAR */
-+    case 0x8c:	/* INTC_MIR_SET */
-+        return 0;
-+
-+    case 0x90:	/* INTC_ISR_SET */
-+        return bank->swi;
-+
-+    case 0x94:	/* INTC_ISR_CLEAR */
-+        return 0;
-+
-+    case 0x98:	/* INTC_PENDING_IRQ */
-+        return bank->irqs & ~bank->mask & ~bank->fiq;
-+
-+    case 0x9c:	/* INTC_PENDING_FIQ */
-+        return bank->irqs & ~bank->mask & bank->fiq;
-+
-+    /* Per-line registers */
-+    case 0x100 ... 0x300:	/* INTC_ILR */
-+        bank_no = (offset - 0x100) >> 7;
-+        if (bank_no > s->nbanks)
-+            break;
-+        bank = &s->bank[bank_no];
-+        line_no = (offset & 0x7f) >> 2;
-+        return (bank->priority[line_no] << 2) |
-+                ((bank->fiq >> line_no) & 1);
-+    }
-+    OMAP_BAD_REG(addr);
-+    return 0;
-+}
-+
-+static void omap2_inth_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
-+    int offset = addr - s->base;
-+    int bank_no, line_no;
-+    struct omap_intr_handler_bank_s *bank = 0;
-+
-+    if ((offset & 0xf80) == 0x80) {
-+        bank_no = (offset & 0x60) >> 5;
-+        if (bank_no < s->nbanks) {
-+            offset &= ~0x60;
-+            bank = &s->bank[bank_no];
-+        }
-+    }
-+
-+    switch (offset) {
-+    case 0x10:	/* INTC_SYSCONFIG */
-+        s->autoidle &= 4;
-+        s->autoidle |= (value & 1) << 2;
-+        if (value & 2)						/* SOFTRESET */
-+            omap_inth_reset(s);
-+        return;
-+
-+    case 0x48:	/* INTC_CONTROL */
-+        s->mask = (value & 4) ? 0 : ~0;				/* GLOBALMASK */
-+        if (value & 2) {					/* NEWFIQAGR */
-+            qemu_set_irq(s->parent_intr[1], 0);
-+            s->new_agr[1] = ~0;
-+            omap_inth_update(s, 1);
-+        }
-+        if (value & 1) {					/* NEWIRQAGR */
-+            qemu_set_irq(s->parent_intr[0], 0);
-+            s->new_agr[0] = ~0;
-+            omap_inth_update(s, 0);
-+        }
-+        return;
-+
-+    case 0x4c:	/* INTC_PROTECTION */
-+        /* TODO: Make a bitmap (or sizeof(char)map) of access privileges
-+         * for every register, see Chapter 3 and 4 for privileged mode.  */
-+        if (value & 1)
-+            fprintf(stderr, "%s: protection mode enable attempt\n",
-+                            __FUNCTION__);
-+        return;
-+
-+    case 0x50:	/* INTC_IDLE */
-+        s->autoidle &= ~3;
-+        s->autoidle |= value & 3;
-+        return;
-+
-+    /* Per-bank registers */
-+    case 0x84:	/* INTC_MIR */
-+        bank->mask = value;
-+        omap_inth_update(s, 0);
-+        omap_inth_update(s, 1);
-+        return;
-+
-+    case 0x88:	/* INTC_MIR_CLEAR */
-+        bank->mask &= ~value;
-+        omap_inth_update(s, 0);
-+        omap_inth_update(s, 1);
-+        return;
-+
-+    case 0x8c:	/* INTC_MIR_SET */
-+        bank->mask |= value;
-+        return;
-+
-+    case 0x90:	/* INTC_ISR_SET */
-+        bank->irqs |= bank->swi |= value;
-+        omap_inth_update(s, 0);
-+        omap_inth_update(s, 1);
-+        return;
-+
-+    case 0x94:	/* INTC_ISR_CLEAR */
-+        bank->swi &= ~value;
-+        bank->irqs = bank->swi & bank->inputs;
-+        return;
-+
-+    /* Per-line registers */
-+    case 0x100 ... 0x300:	/* INTC_ILR */
-+        bank_no = (offset - 0x100) >> 7;
-+        if (bank_no > s->nbanks)
-+            break;
-+        bank = &s->bank[bank_no];
-+        line_no = (offset & 0x7f) >> 2;
-+        bank->priority[line_no] = (value >> 2) & 0x3f;
-+        bank->fiq &= ~(1 << line_no);
-+        bank->fiq |= (value & 1) << line_no;
-+        return;
-+
-+    case 0x00:	/* INTC_REVISION */
-+    case 0x14:	/* INTC_SYSSTATUS */
-+    case 0x40:	/* INTC_SIR_IRQ */
-+    case 0x44:	/* INTC_SIR_FIQ */
-+    case 0x80:	/* INTC_ITR */
-+    case 0x98:	/* INTC_PENDING_IRQ */
-+    case 0x9c:	/* INTC_PENDING_FIQ */
-+        OMAP_RO_REG(addr);
-+        return;
-+    }
-+    OMAP_BAD_REG(addr);
-+}
-+
-+static CPUReadMemoryFunc *omap2_inth_readfn[] = {
-+    omap_badwidth_read32,
-+    omap_badwidth_read32,
-+    omap2_inth_read,
-+};
-+
-+static CPUWriteMemoryFunc *omap2_inth_writefn[] = {
-+    omap2_inth_write,
-+    omap2_inth_write,
-+    omap2_inth_write,
-+};
-+
-+struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base,
-+                int size, int nbanks, qemu_irq **pins,
-+                qemu_irq parent_irq, qemu_irq parent_fiq,
-+                omap_clk fclk, omap_clk iclk)
-+{
-+    int iomemtype;
-+    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *)
-+            qemu_mallocz(sizeof(struct omap_intr_handler_s) +
-+                            sizeof(struct omap_intr_handler_bank_s) * nbanks);
-+
-+    s->parent_intr[0] = parent_irq;
-+    s->parent_intr[1] = parent_fiq;
-+    s->base = base;
-+    s->nbanks = nbanks;
-+    s->level_only = 1;
-+    s->pins = qemu_allocate_irqs(omap_set_intr_noedge, s, nbanks * 32);
-+    if (pins)
-+        *pins = s->pins;
-+
-+    omap_inth_reset(s);
-+
-+    iomemtype = cpu_register_io_memory(0, omap2_inth_readfn,
-+                    omap2_inth_writefn, s);
-+    cpu_register_physical_memory(s->base, size, iomemtype);
-+
-+    return s;
-+}
-+
- /* MPU OS timers */
- struct omap_mpu_timer_s {
-     qemu_irq irq;
-@@ -1289,6 +1543,8 @@ static uint32_t omap_id_read(void *opaque, target_phys_addr_t addr)
-             return 0x03310315;
-         case omap1510:
-             return 0x03310115;
-+        default:
-+            cpu_abort(cpu_single_env, "%s: bad mpu model\n", __FUNCTION__);
-         }
-         break;
- 
-@@ -1298,6 +1554,8 @@ static uint32_t omap_id_read(void *opaque, target_phys_addr_t addr)
-             return 0xfb57402f;
-         case omap1510:
-             return 0xfb47002f;
-+        default:
-+            cpu_abort(cpu_single_env, "%s: bad mpu model\n", __FUNCTION__);
-         }
-         break;
-     }
-@@ -1722,19 +1980,116 @@ static void omap_dpll_init(struct dpll_ctl_s *s, target_phys_addr_t base,
- /* UARTs */
- struct omap_uart_s {
-     SerialState *serial; /* TODO */
-+    struct omap_target_agent_s *ta;
-+    target_phys_addr_t base;
-+
-+    uint8_t eblr;
-+    uint8_t syscontrol;
-+    uint8_t wkup;
-+    uint8_t cfps;
- };
- 
--static void omap_uart_reset(struct omap_uart_s *s)
-+void omap_uart_reset(struct omap_uart_s *s)
- {
-+    s->eblr = 0x00;
-+    s->syscontrol = 0;
-+    s->wkup = 0x3f;
-+    s->cfps = 0x69;
- }
- 
- struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
--                qemu_irq irq, omap_clk clk, CharDriverState *chr)
-+                qemu_irq irq, omap_clk fclk, omap_clk iclk,
-+                qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr)
- {
-     struct omap_uart_s *s = (struct omap_uart_s *)
-             qemu_mallocz(sizeof(struct omap_uart_s));
--    if (chr)
--        s->serial = serial_mm_init(base, 2, irq, chr, 1);
-+
-+    s->serial = serial_mm_init(base, 2, irq, chr ?: qemu_chr_open("null"), 1);
-+
-+    return s;
-+}
-+
-+static uint32_t omap_uart_read(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_uart_s *s = (struct omap_uart_s *) opaque;
-+    int offset = addr - s->base;
-+
-+    switch (offset) {
-+    case 0x48:	/* EBLR */
-+        return s->eblr;
-+    case 0x50:	/* MVR */
-+        return 0x30;
-+    case 0x54:	/* SYSC */
-+        return s->syscontrol;
-+    case 0x58:	/* SYSS */
-+        return 1;
-+    case 0x5c:	/* WER */
-+        return s->wkup;
-+    case 0x60:	/* CFPS */
-+        return s->cfps;
-+    }
-+
-+    OMAP_BAD_REG(addr);
-+    return 0;
-+}
-+
-+static void omap_uart_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct omap_uart_s *s = (struct omap_uart_s *) opaque;
-+    int offset = addr - s->base;
-+
-+    switch (offset) {
-+    case 0x48:	/* EBLR */
-+        s->eblr = value & 0xff;
-+        break;
-+    case 0x50:	/* MVR */
-+    case 0x58:	/* SYSS */
-+        OMAP_RO_REG(addr);
-+        break;
-+    case 0x54:	/* SYSC */
-+        s->syscontrol = value & 0x1d;
-+        if (value & 2)
-+            omap_uart_reset(s);
-+        break;
-+    case 0x5c:	/* WER */
-+        s->wkup = value & 0x7f;
-+        break;
-+    case 0x60:	/* CFPS */
-+        s->cfps = value & 0xff;
-+        break;
-+    default:
-+        OMAP_BAD_REG(addr);
-+    }
-+}
-+
-+static CPUReadMemoryFunc *omap_uart_readfn[] = {
-+    omap_uart_read,
-+    omap_uart_read,
-+    omap_badwidth_read8,
-+};
-+
-+static CPUWriteMemoryFunc *omap_uart_writefn[] = {
-+    omap_uart_write,
-+    omap_uart_write,
-+    omap_badwidth_write8,
-+};
-+
-+struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta,
-+                qemu_irq irq, omap_clk fclk, omap_clk iclk,
-+                qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr)
-+{
-+    target_phys_addr_t base = omap_l4_attach(ta, 0, 0);
-+    struct omap_uart_s *s = omap_uart_init(base, irq,
-+                    fclk, iclk, txdma, rxdma, chr);
-+    int iomemtype = cpu_register_io_memory(0, omap_uart_readfn,
-+                    omap_uart_writefn, s);
-+
-+    s->ta = ta;
-+    s->base = base;
-+
-+    cpu_register_physical_memory(s->base + 0x20, 0x100, iomemtype);
-+
-     return s;
- }
- 
-@@ -2778,9 +3133,11 @@ struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
- void omap_uwire_attach(struct omap_uwire_s *s,
-                 struct uwire_slave_s *slave, int chipselect)
- {
--    if (chipselect < 0 || chipselect > 3)
--        cpu_abort(cpu_single_env, "%s: Bad chipselect %i\n", __FUNCTION__,
--                        chipselect);
-+    if (chipselect < 0 || chipselect > 3) {
-+        fprintf(stderr, "%s: Bad chipselect %i\n",
-+                        __FUNCTION__, chipselect);
-+        exit(-1);
-+    }
- 
-     s->chip[chipselect] = slave;
- }
-@@ -4123,7 +4481,7 @@ static void omap_setup_mpui_io(struct omap_mpu_state_s *mpu)
- }
- 
- /* General chip reset */
--static void omap_mpu_reset(void *opaque)
-+static void omap1_mpu_reset(void *opaque)
- {
-     struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
- 
-@@ -4153,7 +4511,7 @@ static void omap_mpu_reset(void *opaque)
-     omap_uwire_reset(mpu->microwire);
-     omap_pwl_reset(mpu);
-     omap_pwt_reset(mpu);
--    omap_i2c_reset(mpu->i2c);
-+    omap_i2c_reset(mpu->i2c[0]);
-     omap_rtc_reset(mpu->rtc);
-     omap_mcbsp_reset(mpu->mcbsp1);
-     omap_mcbsp_reset(mpu->mcbsp2);
-@@ -4205,7 +4563,7 @@ static void omap_setup_dsp_mapping(const struct omap_map_s *map)
-     }
- }
- 
--static void omap_mpu_wakeup(void *opaque, int irq, int req)
-+void omap_mpu_wakeup(void *opaque, int irq, int req)
- {
-     struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
- 
-@@ -4213,7 +4571,7 @@ static void omap_mpu_wakeup(void *opaque, int irq, int req)
-         cpu_interrupt(mpu->env, CPU_INTERRUPT_EXITTB);
- }
- 
--static const struct dma_irq_map omap_dma_irq_map[] = {
-+static const struct dma_irq_map omap1_dma_irq_map[] = {
-     { 0, OMAP_INT_DMA_CH0_6 },
-     { 0, OMAP_INT_DMA_CH1_7 },
-     { 0, OMAP_INT_DMA_CH2_8 },
-@@ -4307,17 +4665,16 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
-     omap_clkm_init(0xfffece00, 0xe1008000, s);
- 
-     cpu_irq = arm_pic_init_cpu(s->env);
--    s->ih[0] = omap_inth_init(0xfffecb00, 0x100, 1,
-+    s->ih[0] = omap_inth_init(0xfffecb00, 0x100, 1, &s->irq[0],
-                     cpu_irq[ARM_PIC_CPU_IRQ], cpu_irq[ARM_PIC_CPU_FIQ],
-                     omap_findclk(s, "arminth_ck"));
--    s->ih[1] = omap_inth_init(0xfffe0000, 0x800, 1,
-+    s->ih[1] = omap_inth_init(0xfffe0000, 0x800, 1, &s->irq[1],
-                     s->ih[0]->pins[OMAP_INT_15XX_IH2_IRQ], NULL,
-                     omap_findclk(s, "arminth_ck"));
--    s->irq[0] = s->ih[0]->pins;
--    s->irq[1] = s->ih[1]->pins;
- 
-     for (i = 0; i < 6; i ++)
--        dma_irqs[i] = s->irq[omap_dma_irq_map[i].ih][omap_dma_irq_map[i].intr];
-+        dma_irqs[i] =
-+                s->irq[omap1_dma_irq_map[i].ih][omap1_dma_irq_map[i].intr];
-     s->dma = omap_dma_init(0xfffed800, dma_irqs, s->irq[0][OMAP_INT_DMA_LCD],
-                            s, omap_findclk(s, "dma_ck"), omap_dma_3_1);
- 
-@@ -4367,12 +4724,18 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
- 
-     s->uart[0] = omap_uart_init(0xfffb0000, s->irq[1][OMAP_INT_UART1],
-                     omap_findclk(s, "uart1_ck"),
-+                    omap_findclk(s, "uart1_ck"),
-+                    s->drq[OMAP_DMA_UART1_TX], s->drq[OMAP_DMA_UART1_RX],
-                     serial_hds[0]);
-     s->uart[1] = omap_uart_init(0xfffb0800, s->irq[1][OMAP_INT_UART2],
-                     omap_findclk(s, "uart2_ck"),
-+                    omap_findclk(s, "uart2_ck"),
-+                    s->drq[OMAP_DMA_UART2_TX], s->drq[OMAP_DMA_UART2_RX],
-                     serial_hds[0] ? serial_hds[1] : 0);
-     s->uart[2] = omap_uart_init(0xe1019800, s->irq[0][OMAP_INT_UART3],
-                     omap_findclk(s, "uart3_ck"),
-+                    omap_findclk(s, "uart3_ck"),
-+                    s->drq[OMAP_DMA_UART3_TX], s->drq[OMAP_DMA_UART3_RX],
-                     serial_hds[0] && serial_hds[1] ? serial_hds[2] : 0);
- 
-     omap_dpll_init(&s->dpll[0], 0xfffecf00, omap_findclk(s, "dpll1"));
-@@ -4401,7 +4764,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
-     omap_pwl_init(0xfffb5800, s, omap_findclk(s, "armxor_ck"));
-     omap_pwt_init(0xfffb6000, s, omap_findclk(s, "armxor_ck"));
- 
--    s->i2c = omap_i2c_init(0xfffb3800, s->irq[1][OMAP_INT_I2C],
-+    s->i2c[0] = omap_i2c_init(0xfffb3800, s->irq[1][OMAP_INT_I2C],
-                     &s->drq[OMAP_DMA_I2C_RX], omap_findclk(s, "mpuper_ck"));
- 
-     s->rtc = omap_rtc_init(0xfffb4800, &s->irq[1][OMAP_INT_RTC_TIMER],
-@@ -4435,7 +4798,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
-     omap_setup_dsp_mapping(omap15xx_dsp_mm);
-     omap_setup_mpui_io(s);
- 
--    qemu_register_reset(omap_mpu_reset, s);
-+    qemu_register_reset(omap1_mpu_reset, s);
- 
-     return s;
- }
-diff --git a/hw/omap2.c b/hw/omap2.c
-new file mode 100644
-index 0000000..1e51197
---- /dev/null
-+++ b/hw/omap2.c
-@@ -0,0 +1,3872 @@
-+/*
-+ * TI OMAP processors emulation.
-+ *
-+ * Copyright (C) 2007-2008 Nokia Corporation
-+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation; either version 2 of
-+ * the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-+ * MA 02111-1307 USA
-+ */
-+#include "hw.h"
-+#include "arm-misc.h"
-+#include "omap.h"
-+#include "sysemu.h"
-+#include "qemu-timer.h"
-+#include "qemu-char.h"
-+#include "flash.h"
-+/* We use pc-style serial ports.  */
-+#include "pc.h"
-+
-+/* GP timers */
-+struct omap_gp_timer_s {
-+    qemu_irq irq;
-+    qemu_irq wkup;
-+    qemu_irq in;
-+    qemu_irq out;
-+    omap_clk clk;
-+    target_phys_addr_t base;
-+    QEMUTimer *timer;
-+    QEMUTimer *match;
-+    struct omap_target_agent_s *ta;
-+
-+    int in_val;
-+    int out_val;
-+    int64_t time;
-+    int64_t rate;
-+    int64_t ticks_per_sec;
-+
-+    int16_t config;
-+    int status;
-+    int it_ena;
-+    int wu_ena;
-+    int enable;
-+    int inout;
-+    int capt2;
-+    int pt;
-+    enum {
-+        gpt_trigger_none, gpt_trigger_overflow, gpt_trigger_both
-+    } trigger;
-+    enum {
-+        gpt_capture_none, gpt_capture_rising,
-+        gpt_capture_falling, gpt_capture_both
-+    } capture;
-+    int scpwm;
-+    int ce;
-+    int pre;
-+    int ptv;
-+    int ar;
-+    int st;
-+    int posted;
-+    uint32_t val;
-+    uint32_t load_val;
-+    uint32_t capture_val[2];
-+    uint32_t match_val;
-+    int capt_num;
-+
-+    uint16_t writeh;	/* LSB */
-+    uint16_t readh;	/* MSB */
-+};
-+
-+#define GPT_TCAR_IT	(1 << 2)
-+#define GPT_OVF_IT	(1 << 1)
-+#define GPT_MAT_IT	(1 << 0)
-+
-+static inline void omap_gp_timer_intr(struct omap_gp_timer_s *timer, int it)
-+{
-+    if (timer->it_ena & it) {
-+        if (!timer->status)
-+            qemu_irq_raise(timer->irq);
-+
-+        timer->status |= it;
-+        /* Or are the status bits set even when masked?
-+         * i.e. is masking applied before or after the status register?  */
-+    }
-+
-+    if (timer->wu_ena & it)
-+        qemu_irq_pulse(timer->wkup);
-+}
-+
-+static inline void omap_gp_timer_out(struct omap_gp_timer_s *timer, int level)
-+{
-+    if (!timer->inout && timer->out_val != level) {
-+        timer->out_val = level;
-+        qemu_set_irq(timer->out, level);
-+    }
-+}
-+
-+static inline uint32_t omap_gp_timer_read(struct omap_gp_timer_s *timer)
-+{
-+    uint64_t distance;
-+
-+    if (timer->st && timer->rate) {
-+        distance = qemu_get_clock(vm_clock) - timer->time;
-+        distance = muldiv64(distance, timer->rate, timer->ticks_per_sec);
-+
-+        if (distance >= 0xffffffff - timer->val)
-+            return 0xffffffff;
-+        else
-+            return timer->val + distance;
-+    } else
-+        return timer->val;
-+}
-+
-+static inline void omap_gp_timer_sync(struct omap_gp_timer_s *timer)
-+{
-+    if (timer->st) {
-+        timer->val = omap_gp_timer_read(timer);
-+        timer->time = qemu_get_clock(vm_clock);
-+    }
-+}
-+
-+static inline void omap_gp_timer_update(struct omap_gp_timer_s *timer)
-+{
-+    int64_t expires, matches;
-+
-+    if (timer->st && timer->rate) {
-+        expires = muldiv64(0x100000000ll - timer->val,
-+                        timer->ticks_per_sec, timer->rate);
-+        qemu_mod_timer(timer->timer, timer->time + expires);
-+
-+        if (timer->ce && timer->match_val >= timer->val) {
-+            matches = muldiv64(timer->match_val - timer->val,
-+                            timer->ticks_per_sec, timer->rate);
-+            qemu_mod_timer(timer->match, timer->time + matches);
-+        } else
-+            qemu_del_timer(timer->match);
-+    } else {
-+        qemu_del_timer(timer->timer);
-+        qemu_del_timer(timer->match);
-+        omap_gp_timer_out(timer, timer->scpwm);
-+    }
-+}
-+
-+static inline void omap_gp_timer_trigger(struct omap_gp_timer_s *timer)
-+{
-+    if (timer->pt)
-+        /* TODO in overflow-and-match mode if the first event to
-+         * occurs is the match, don't toggle.  */
-+        omap_gp_timer_out(timer, !timer->out_val);
-+    else
-+        /* TODO inverted pulse on timer->out_val == 1?  */
-+        qemu_irq_pulse(timer->out);
-+}
-+
-+static void omap_gp_timer_tick(void *opaque)
-+{
-+    struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
-+
-+    if (!timer->ar) {
-+        timer->st = 0;
-+        timer->val = 0;
-+    } else {
-+        timer->val = timer->load_val;
-+        timer->time = qemu_get_clock(vm_clock);
-+    }
-+
-+    if (timer->trigger == gpt_trigger_overflow ||
-+                    timer->trigger == gpt_trigger_both)
-+        omap_gp_timer_trigger(timer);
-+
-+    omap_gp_timer_intr(timer, GPT_OVF_IT);
-+    omap_gp_timer_update(timer);
-+}
-+
-+static void omap_gp_timer_match(void *opaque)
-+{
-+    struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
-+
-+    if (timer->trigger == gpt_trigger_both)
-+        omap_gp_timer_trigger(timer);
-+
-+    omap_gp_timer_intr(timer, GPT_MAT_IT);
-+}
-+
-+static void omap_gp_timer_input(void *opaque, int line, int on)
-+{
-+    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
-+    int trigger;
-+
-+    switch (s->capture) {
-+    default:
-+    case gpt_capture_none:
-+        trigger = 0;
-+        break;
-+    case gpt_capture_rising:
-+        trigger = !s->in_val && on;
-+        break;
-+    case gpt_capture_falling:
-+        trigger = s->in_val && !on;
-+        break;
-+    case gpt_capture_both:
-+        trigger = (s->in_val == !on);
-+        break;
-+    }
-+    s->in_val = on;
-+
-+    if (s->inout && trigger && s->capt_num < 2) {
-+        s->capture_val[s->capt_num] = omap_gp_timer_read(s);
-+
-+        if (s->capt2 == s->capt_num ++)
-+            omap_gp_timer_intr(s, GPT_TCAR_IT);
-+    }
-+}
-+
-+static void omap_gp_timer_clk_update(void *opaque, int line, int on)
-+{
-+    struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
-+
-+    omap_gp_timer_sync(timer);
-+    timer->rate = on ? omap_clk_getrate(timer->clk) : 0;
-+    omap_gp_timer_update(timer);
-+}
-+
-+static void omap_gp_timer_clk_setup(struct omap_gp_timer_s *timer)
-+{
-+    omap_clk_adduser(timer->clk,
-+                    qemu_allocate_irqs(omap_gp_timer_clk_update, timer, 1)[0]);
-+    timer->rate = omap_clk_getrate(timer->clk);
-+}
-+
-+static void omap_gp_timer_reset(struct omap_gp_timer_s *s)
-+{
-+    s->config = 0x000;
-+    s->status = 0;
-+    s->it_ena = 0;
-+    s->wu_ena = 0;
-+    s->inout = 0;
-+    s->capt2 = 0;
-+    s->capt_num = 0;
-+    s->pt = 0;
-+    s->trigger = gpt_trigger_none;
-+    s->capture = gpt_capture_none;
-+    s->scpwm = 0;
-+    s->ce = 0;
-+    s->pre = 0;
-+    s->ptv = 0;
-+    s->ar = 0;
-+    s->st = 0;
-+    s->posted = 1;
-+    s->val = 0x00000000;
-+    s->load_val = 0x00000000;
-+    s->capture_val[0] = 0x00000000;
-+    s->capture_val[1] = 0x00000000;
-+    s->match_val = 0x00000000;
-+    omap_gp_timer_update(s);
-+}
-+
-+static uint32_t omap_gp_timer_readw(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
-+    int offset = addr - s->base;
-+
-+    switch (offset) {
-+    case 0x00:	/* TIDR */
-+        return 0x21;
-+
-+    case 0x10:	/* TIOCP_CFG */
-+        return s->config;
-+
-+    case 0x14:	/* TISTAT */
-+        /* ??? When's this bit reset? */
-+        return 1;						/* RESETDONE */
-+
-+    case 0x18:	/* TISR */
-+        return s->status;
-+
-+    case 0x1c:	/* TIER */
-+        return s->it_ena;
-+
-+    case 0x20:	/* TWER */
-+        return s->wu_ena;
-+
-+    case 0x24:	/* TCLR */
-+        return (s->inout << 14) |
-+                (s->capt2 << 13) |
-+                (s->pt << 12) |
-+                (s->trigger << 10) |
-+                (s->capture << 8) |
-+                (s->scpwm << 7) |
-+                (s->ce << 6) |
-+                (s->pre << 5) |
-+                (s->ptv << 2) |
-+                (s->ar << 1) |
-+                (s->st << 0);
-+
-+    case 0x28:	/* TCRR */
-+        return omap_gp_timer_read(s);
-+
-+    case 0x2c:	/* TLDR */
-+        return s->load_val;
-+
-+    case 0x30:	/* TTGR */
-+        return 0xffffffff;
-+
-+    case 0x34:	/* TWPS */
-+        return 0x00000000;	/* No posted writes pending.  */
-+
-+    case 0x38:	/* TMAR */
-+        return s->match_val;
-+
-+    case 0x3c:	/* TCAR1 */
-+        return s->capture_val[0];
-+
-+    case 0x40:	/* TSICR */
-+        return s->posted << 2;
-+
-+    case 0x44:	/* TCAR2 */
-+        return s->capture_val[1];
-+    }
-+
-+    OMAP_BAD_REG(addr);
-+    return 0;
-+}
-+
-+static uint32_t omap_gp_timer_readh(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
-+    uint32_t ret;
-+
-+    if (addr & 2)
-+        return s->readh;
-+    else {
-+        ret = omap_gp_timer_readw(opaque, addr);
-+        s->readh = ret >> 16;
-+        return ret & 0xffff;
-+    }
-+}
-+
-+static CPUReadMemoryFunc *omap_gp_timer_readfn[] = {
-+    omap_badwidth_read32,
-+    omap_gp_timer_readh,
-+    omap_gp_timer_readw,
-+};
-+
-+static void omap_gp_timer_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
-+    int offset = addr - s->base;
-+
-+    switch (offset) {
-+    case 0x00:	/* TIDR */
-+    case 0x14:	/* TISTAT */
-+    case 0x34:	/* TWPS */
-+    case 0x3c:	/* TCAR1 */
-+    case 0x44:	/* TCAR2 */
-+        OMAP_RO_REG(addr);
-+        break;
-+
-+    case 0x10:	/* TIOCP_CFG */
-+        s->config = value & 0x33d;
-+        if (((value >> 3) & 3) == 3)				/* IDLEMODE */
-+            fprintf(stderr, "%s: illegal IDLEMODE value in TIOCP_CFG\n",
-+                            __FUNCTION__);
-+        if (value & 2)						/* SOFTRESET */
-+            omap_gp_timer_reset(s);
-+        break;
-+
-+    case 0x18:	/* TISR */
-+        if (value & GPT_TCAR_IT)
-+            s->capt_num = 0;
-+        if (s->status && !(s->status &= ~value))
-+            qemu_irq_lower(s->irq);
-+        break;
-+
-+    case 0x1c:	/* TIER */
-+        s->it_ena = value & 7;
-+        break;
-+
-+    case 0x20:	/* TWER */
-+        s->wu_ena = value & 7;
-+        break;
-+
-+    case 0x24:	/* TCLR */
-+        omap_gp_timer_sync(s);
-+        s->inout = (value >> 14) & 1;
-+        s->capt2 = (value >> 13) & 1;
-+        s->pt = (value >> 12) & 1;
-+        s->trigger = (value >> 10) & 3;
-+        if (s->capture == gpt_capture_none &&
-+                        ((value >> 8) & 3) != gpt_capture_none)
-+            s->capt_num = 0;
-+        s->capture = (value >> 8) & 3;
-+        s->scpwm = (value >> 7) & 1;
-+        s->ce = (value >> 6) & 1;
-+        s->pre = (value >> 5) & 1;
-+        s->ptv = (value >> 2) & 7;
-+        s->ar = (value >> 1) & 1;
-+        s->st = (value >> 0) & 1;
-+        if (s->inout && s->trigger != gpt_trigger_none)
-+            fprintf(stderr, "%s: GP timer pin must be an output "
-+                            "for this trigger mode\n", __FUNCTION__);
-+        if (!s->inout && s->capture != gpt_capture_none)
-+            fprintf(stderr, "%s: GP timer pin must be an input "
-+                            "for this capture mode\n", __FUNCTION__);
-+        if (s->trigger == gpt_trigger_none)
-+            omap_gp_timer_out(s, s->scpwm);
-+        /* TODO: make sure this doesn't overflow 32-bits */
-+        s->ticks_per_sec = ticks_per_sec << (s->pre ? s->ptv + 1 : 0);
-+        omap_gp_timer_update(s);
-+        break;
-+
-+    case 0x28:	/* TCRR */
-+        s->time = qemu_get_clock(vm_clock);
-+        s->val = value;
-+        omap_gp_timer_update(s);
-+        break;
-+
-+    case 0x2c:	/* TLDR */
-+        s->load_val = value;
-+        break;
-+
-+    case 0x30:	/* TTGR */
-+        s->time = qemu_get_clock(vm_clock);
-+        s->val = s->load_val;
-+        omap_gp_timer_update(s);
-+        break;
-+
-+    case 0x38:	/* TMAR */
-+        omap_gp_timer_sync(s);
-+        s->match_val = value;
-+        omap_gp_timer_update(s);
-+        break;
-+
-+    case 0x40:	/* TSICR */
-+        s->posted = (value >> 2) & 1;
-+        if (value & 2)	/* How much exactly are we supposed to reset? */
-+            omap_gp_timer_reset(s);
-+        break;
-+
-+    default:
-+        OMAP_BAD_REG(addr);
-+    }
-+}
-+
-+static void omap_gp_timer_writeh(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
-+
-+    if (addr & 2)
-+        return omap_gp_timer_write(opaque, addr, (value << 16) | s->writeh);
-+    else
-+        s->writeh = (uint16_t) value;
-+}
-+
-+static CPUWriteMemoryFunc *omap_gp_timer_writefn[] = {
-+    omap_badwidth_write32,
-+    omap_gp_timer_writeh,
-+    omap_gp_timer_write,
-+};
-+
-+struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
-+                qemu_irq irq, omap_clk fclk, omap_clk iclk)
-+{
-+    int iomemtype;
-+    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *)
-+            qemu_mallocz(sizeof(struct omap_gp_timer_s));
-+
-+    s->ta = ta;
-+    s->irq = irq;
-+    s->clk = fclk;
-+    s->timer = qemu_new_timer(vm_clock, omap_gp_timer_tick, s);
-+    s->match = qemu_new_timer(vm_clock, omap_gp_timer_match, s);
-+    s->in = qemu_allocate_irqs(omap_gp_timer_input, s, 1)[0];
-+    omap_gp_timer_reset(s);
-+    omap_gp_timer_clk_setup(s);
-+
-+    iomemtype = cpu_register_io_memory(0, omap_gp_timer_readfn,
-+                    omap_gp_timer_writefn, s);
-+    s->base = omap_l4_attach(ta, 0, iomemtype);
-+
-+    return s;
-+}
-+
-+/* 32-kHz Sync Timer of the OMAP2 */
-+static uint32_t omap_synctimer_read(struct omap_synctimer_s *s) {
-+    return muldiv64(qemu_get_clock(vm_clock), 0x8000, ticks_per_sec);
-+}
-+
-+static void omap_synctimer_reset(struct omap_synctimer_s *s)
-+{
-+    s->val = omap_synctimer_read(s);
-+}
-+
-+static uint32_t omap_synctimer_readw(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
-+    int offset = addr - s->base;
-+
-+    switch (offset) {
-+    case 0x00:	/* 32KSYNCNT_REV */
-+        return 0x21;
-+
-+    case 0x10:	/* CR */
-+        return omap_synctimer_read(s) - s->val;
-+    }
-+
-+    OMAP_BAD_REG(addr);
-+    return 0;
-+}
-+
-+static uint32_t omap_synctimer_readh(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
-+    uint32_t ret;
-+
-+    if (addr & 2)
-+        return s->readh;
-+    else {
-+        ret = omap_synctimer_readw(opaque, addr);
-+        s->readh = ret >> 16;
-+        return ret & 0xffff;
-+    }
-+}
-+
-+static CPUReadMemoryFunc *omap_synctimer_readfn[] = {
-+    omap_badwidth_read32,
-+    omap_synctimer_readh,
-+    omap_synctimer_readw,
-+};
-+
-+static void omap_synctimer_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    OMAP_BAD_REG(addr);
-+}
-+
-+static CPUWriteMemoryFunc *omap_synctimer_writefn[] = {
-+    omap_badwidth_write32,
-+    omap_synctimer_write,
-+    omap_synctimer_write,
-+};
-+
-+void omap_synctimer_init(struct omap_target_agent_s *ta,
-+                struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk)
-+{
-+    struct omap_synctimer_s *s = &mpu->synctimer;
-+
-+    omap_synctimer_reset(s);
-+    s->base = omap_l4_attach(ta, 0, cpu_register_io_memory(0,
-+                            omap_synctimer_readfn, omap_synctimer_writefn, s));
-+}
-+
-+/* General-Purpose Interface of OMAP2 */
-+struct omap2_gpio_s {
-+    target_phys_addr_t base;
-+    qemu_irq irq[2];
-+    qemu_irq wkup;
-+    qemu_irq *in;
-+    qemu_irq handler[32];
-+
-+    uint8_t config[2];
-+    uint32_t inputs;
-+    uint32_t outputs;
-+    uint32_t dir;
-+    uint32_t level[2];
-+    uint32_t edge[2];
-+    uint32_t mask[2];
-+    uint32_t wumask;
-+    uint32_t ints[2];
-+    uint32_t debounce;
-+    uint8_t delay;
-+};
-+
-+static inline void omap_gpio_module_int_update(struct omap2_gpio_s *s,
-+                int line)
-+{
-+    qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]);
-+}
-+
-+static void omap_gpio_module_wake(struct omap2_gpio_s *s, int line)
-+{
-+    if (!(s->config[0] & (1 << 2)))			/* ENAWAKEUP */
-+        return;
-+    if (!(s->config[0] & (3 << 3)))			/* Force Idle */
-+        return;
-+    if (!(s->wumask & (1 << line)))
-+        return;
-+
-+    qemu_irq_raise(s->wkup);
-+}
-+
-+static inline void omap_gpio_module_out_update(struct omap2_gpio_s *s,
-+                uint32_t diff)
-+{
-+    int ln;
-+
-+    s->outputs ^= diff;
-+    diff &= ~s->dir;
-+    while ((ln = ffs(diff))) {
-+        ln --;
-+        qemu_set_irq(s->handler[ln], (s->outputs >> ln) & 1);
-+        diff &= ~(1 << ln);
-+    }
-+}
-+
-+static void omap_gpio_module_level_update(struct omap2_gpio_s *s, int line)
-+{
-+    s->ints[line] |= s->dir &
-+            ((s->inputs & s->level[1]) | (~s->inputs & s->level[0]));
-+    omap_gpio_module_int_update(s, line);
-+}
-+
-+static inline void omap_gpio_module_int(struct omap2_gpio_s *s, int line)
-+{
-+    s->ints[0] |= 1 << line;
-+    omap_gpio_module_int_update(s, 0);
-+    s->ints[1] |= 1 << line;
-+    omap_gpio_module_int_update(s, 1);
-+    omap_gpio_module_wake(s, line);
-+}
-+
-+static void omap_gpio_module_set(void *opaque, int line, int level)
-+{
-+    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
-+
-+    if (level) {
-+        if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1]))
-+            omap_gpio_module_int(s, line);
-+        s->inputs |= 1 << line;
-+    } else {
-+        if (s->dir & (1 << line) & ((s->inputs & s->edge[1]) | s->level[0]))
-+            omap_gpio_module_int(s, line);
-+        s->inputs &= ~(1 << line);
-+    }
-+}
-+
-+static void omap_gpio_module_reset(struct omap2_gpio_s *s)
-+{
-+    s->config[0] = 0;
-+    s->config[1] = 2;
-+    s->ints[0] = 0;
-+    s->ints[1] = 0;
-+    s->mask[0] = 0;
-+    s->mask[1] = 0;
-+    s->wumask = 0;
-+    s->dir = ~0;
-+    s->level[0] = 0;
-+    s->level[1] = 0;
-+    s->edge[0] = 0;
-+    s->edge[1] = 0;
-+    s->debounce = 0;
-+    s->delay = 0;
-+}
-+
-+static uint32_t omap_gpio_module_read(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
-+    int offset = addr - s->base;
-+
-+    switch (offset) {
-+    case 0x00:	/* GPIO_REVISION */
-+        return 0x18;
-+
-+    case 0x10:	/* GPIO_SYSCONFIG */
-+        return s->config[0];
-+
-+    case 0x14:	/* GPIO_SYSSTATUS */
-+        return 0x01;
-+
-+    case 0x18:	/* GPIO_IRQSTATUS1 */
-+        return s->ints[0];
-+
-+    case 0x1c:	/* GPIO_IRQENABLE1 */
-+    case 0x60:	/* GPIO_CLEARIRQENABLE1 */
-+    case 0x64:	/* GPIO_SETIRQENABLE1 */
-+        return s->mask[0];
-+
-+    case 0x20:	/* GPIO_WAKEUPENABLE */
-+    case 0x80:	/* GPIO_CLEARWKUENA */
-+    case 0x84:	/* GPIO_SETWKUENA */
-+        return s->wumask;
-+
-+    case 0x28:	/* GPIO_IRQSTATUS2 */
-+        return s->ints[1];
-+
-+    case 0x2c:	/* GPIO_IRQENABLE2 */
-+    case 0x70:	/* GPIO_CLEARIRQENABLE2 */
-+    case 0x74:	/* GPIO_SETIREQNEABLE2 */
-+        return s->mask[1];
-+
-+    case 0x30:	/* GPIO_CTRL */
-+        return s->config[1];
-+
-+    case 0x34:	/* GPIO_OE */
-+        return s->dir;
-+
-+    case 0x38:	/* GPIO_DATAIN */
-+        return s->inputs;
-+
-+    case 0x3c:	/* GPIO_DATAOUT */
-+    case 0x90:	/* GPIO_CLEARDATAOUT */
-+    case 0x94:	/* GPIO_SETDATAOUT */
-+        return s->outputs;
-+
-+    case 0x40:	/* GPIO_LEVELDETECT0 */
-+        return s->level[0];
-+
-+    case 0x44:	/* GPIO_LEVELDETECT1 */
-+        return s->level[1];
-+
-+    case 0x48:	/* GPIO_RISINGDETECT */
-+        return s->edge[0];
-+
-+    case 0x4c:	/* GPIO_FALLINGDETECT */
-+        return s->edge[1];
-+
-+    case 0x50:	/* GPIO_DEBOUNCENABLE */
-+        return s->debounce;
-+
-+    case 0x54:	/* GPIO_DEBOUNCINGTIME */
-+        return s->delay;
-+    }
-+
-+    OMAP_BAD_REG(addr);
-+    return 0;
-+}
-+
-+static void omap_gpio_module_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
-+    int offset = addr - s->base;
-+    uint32_t diff;
-+    int ln;
-+
-+    switch (offset) {
-+    case 0x00:	/* GPIO_REVISION */
-+    case 0x14:	/* GPIO_SYSSTATUS */
-+    case 0x38:	/* GPIO_DATAIN */
-+        OMAP_RO_REG(addr);
-+        break;
-+
-+    case 0x10:	/* GPIO_SYSCONFIG */
-+        if (((value >> 3) & 3) == 3)
-+            fprintf(stderr, "%s: bad IDLEMODE value\n", __FUNCTION__);
-+        if (value & 2)
-+            omap_gpio_module_reset(s);
-+        s->config[0] = value & 0x1d;
-+        break;
-+
-+    case 0x18:	/* GPIO_IRQSTATUS1 */
-+        if (s->ints[0] & value) {
-+            s->ints[0] &= ~value;
-+            omap_gpio_module_level_update(s, 0);
-+        }
-+        break;
-+
-+    case 0x1c:	/* GPIO_IRQENABLE1 */
-+        s->mask[0] = value;
-+        omap_gpio_module_int_update(s, 0);
-+        break;
-+
-+    case 0x20:	/* GPIO_WAKEUPENABLE */
-+        s->wumask = value;
-+        break;
-+
-+    case 0x28:	/* GPIO_IRQSTATUS2 */
-+        if (s->ints[1] & value) {
-+            s->ints[1] &= ~value;
-+            omap_gpio_module_level_update(s, 1);
-+        }
-+        break;
-+
-+    case 0x2c:	/* GPIO_IRQENABLE2 */
-+        s->mask[1] = value;
-+        omap_gpio_module_int_update(s, 1);
-+        break;
-+
-+    case 0x30:	/* GPIO_CTRL */
-+        s->config[1] = value & 7;
-+        break;
-+
-+    case 0x34:	/* GPIO_OE */
-+        diff = s->outputs & (s->dir ^ value);
-+        s->dir = value;
-+
-+        value = s->outputs & ~s->dir;
-+        while ((ln = ffs(diff))) {
-+            diff &= ~(1 <<-- ln);
-+            qemu_set_irq(s->handler[ln], (value >> ln) & 1);
-+        }
-+
-+        omap_gpio_module_level_update(s, 0);
-+        omap_gpio_module_level_update(s, 1);
-+        break;
-+
-+    case 0x3c:	/* GPIO_DATAOUT */
-+        omap_gpio_module_out_update(s, s->outputs ^ value);
-+        break;
-+
-+    case 0x40:	/* GPIO_LEVELDETECT0 */
-+        s->level[0] = value;
-+        omap_gpio_module_level_update(s, 0);
-+        omap_gpio_module_level_update(s, 1);
-+        break;
-+
-+    case 0x44:	/* GPIO_LEVELDETECT1 */
-+        s->level[1] = value;
-+        omap_gpio_module_level_update(s, 0);
-+        omap_gpio_module_level_update(s, 1);
-+        break;
-+
-+    case 0x48:	/* GPIO_RISINGDETECT */
-+        s->edge[0] = value;
-+        break;
-+
-+    case 0x4c:	/* GPIO_FALLINGDETECT */
-+        s->edge[1] = value;
-+        break;
-+
-+    case 0x50:	/* GPIO_DEBOUNCENABLE */
-+        s->debounce = value;
-+        break;
-+
-+    case 0x54:	/* GPIO_DEBOUNCINGTIME */
-+        s->delay = value;
-+        break;
-+
-+    case 0x60:	/* GPIO_CLEARIRQENABLE1 */
-+        s->mask[0] &= ~value;
-+        omap_gpio_module_int_update(s, 0);
-+        break;
-+
-+    case 0x64:	/* GPIO_SETIRQENABLE1 */
-+        s->mask[0] |= value;
-+        omap_gpio_module_int_update(s, 0);
-+        break;
-+
-+    case 0x70:	/* GPIO_CLEARIRQENABLE2 */
-+        s->mask[1] &= ~value;
-+        omap_gpio_module_int_update(s, 1);
-+        break;
-+
-+    case 0x74:	/* GPIO_SETIREQNEABLE2 */
-+        s->mask[1] |= value;
-+        omap_gpio_module_int_update(s, 1);
-+        break;
-+
-+    case 0x80:	/* GPIO_CLEARWKUENA */
-+        s->wumask &= ~value;
-+        break;
-+
-+    case 0x84:	/* GPIO_SETWKUENA */
-+        s->wumask |= value;
-+        break;
-+
-+    case 0x90:	/* GPIO_CLEARDATAOUT */
-+        omap_gpio_module_out_update(s, s->outputs & value);
-+        break;
-+
-+    case 0x94:	/* GPIO_SETDATAOUT */
-+        omap_gpio_module_out_update(s, ~s->outputs & value);
-+        break;
-+
-+    default:
-+        OMAP_BAD_REG(addr);
-+        return;
-+    }
-+}
-+
-+static uint32_t omap_gpio_module_readp(void *opaque, target_phys_addr_t addr)
-+{
-+    return omap_gpio_module_readp(opaque, addr) >> ((addr & 3) << 3);
-+}
-+
-+static void omap_gpio_module_writep(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
-+    int offset = addr - s->base;
-+    uint32_t cur = 0;
-+    uint32_t mask = 0xffff;
-+
-+    switch (offset & ~3) {
-+    case 0x00:	/* GPIO_REVISION */
-+    case 0x14:	/* GPIO_SYSSTATUS */
-+    case 0x38:	/* GPIO_DATAIN */
-+        OMAP_RO_REG(addr);
-+        break;
-+
-+    case 0x10:	/* GPIO_SYSCONFIG */
-+    case 0x1c:	/* GPIO_IRQENABLE1 */
-+    case 0x20:	/* GPIO_WAKEUPENABLE */
-+    case 0x2c:	/* GPIO_IRQENABLE2 */
-+    case 0x30:	/* GPIO_CTRL */
-+    case 0x34:	/* GPIO_OE */
-+    case 0x3c:	/* GPIO_DATAOUT */
-+    case 0x40:	/* GPIO_LEVELDETECT0 */
-+    case 0x44:	/* GPIO_LEVELDETECT1 */
-+    case 0x48:	/* GPIO_RISINGDETECT */
-+    case 0x4c:	/* GPIO_FALLINGDETECT */
-+    case 0x50:	/* GPIO_DEBOUNCENABLE */
-+    case 0x54:	/* GPIO_DEBOUNCINGTIME */
-+        cur = omap_gpio_module_read(opaque, addr & ~3) &
-+                ~(mask << ((addr & 3) << 3));
-+
-+        /* Fall through.  */
-+    case 0x18:	/* GPIO_IRQSTATUS1 */
-+    case 0x28:	/* GPIO_IRQSTATUS2 */
-+    case 0x60:	/* GPIO_CLEARIRQENABLE1 */
-+    case 0x64:	/* GPIO_SETIRQENABLE1 */
-+    case 0x70:	/* GPIO_CLEARIRQENABLE2 */
-+    case 0x74:	/* GPIO_SETIREQNEABLE2 */
-+    case 0x80:	/* GPIO_CLEARWKUENA */
-+    case 0x84:	/* GPIO_SETWKUENA */
-+    case 0x90:	/* GPIO_CLEARDATAOUT */
-+    case 0x94:	/* GPIO_SETDATAOUT */
-+        value <<= (addr & 3) << 3;
-+        omap_gpio_module_write(opaque, addr, cur | value);
-+        break;
-+
-+    default:
-+        OMAP_BAD_REG(addr);
-+        return;
-+    }
-+}
-+
-+static CPUReadMemoryFunc *omap_gpio_module_readfn[] = {
-+    omap_gpio_module_readp,
-+    omap_gpio_module_readp,
-+    omap_gpio_module_read,
-+};
-+
-+static CPUWriteMemoryFunc *omap_gpio_module_writefn[] = {
-+    omap_gpio_module_writep,
-+    omap_gpio_module_writep,
-+    omap_gpio_module_write,
-+};
-+
-+static void omap_gpio_module_init(struct omap2_gpio_s *s,
-+                struct omap_target_agent_s *ta, int region,
-+                qemu_irq mpu, qemu_irq dsp, qemu_irq wkup,
-+                omap_clk fclk, omap_clk iclk)
-+{
-+    int iomemtype;
-+
-+    s->irq[0] = mpu;
-+    s->irq[1] = dsp;
-+    s->wkup = wkup;
-+    s->in = qemu_allocate_irqs(omap_gpio_module_set, s, 32);
-+
-+    iomemtype = cpu_register_io_memory(0, omap_gpio_module_readfn,
-+                    omap_gpio_module_writefn, s);
-+    s->base = omap_l4_attach(ta, region, iomemtype);
-+}
-+
-+struct omap_gpif_s {
-+    struct omap2_gpio_s module[5];
-+    int modules;
-+
-+    target_phys_addr_t topbase;
-+    int autoidle;
-+    int gpo;
-+};
-+
-+static void omap_gpif_reset(struct omap_gpif_s *s)
-+{
-+    int i;
-+
-+    for (i = 0; i < s->modules; i ++)
-+        omap_gpio_module_reset(s->module + i);
-+
-+    s->autoidle = 0;
-+    s->gpo = 0;
-+}
-+
-+static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
-+    int offset = addr - s->topbase;
-+
-+    switch (offset) {
-+    case 0x00:	/* IPGENERICOCPSPL_REVISION */
-+        return 0x18;
-+
-+    case 0x10:	/* IPGENERICOCPSPL_SYSCONFIG */
-+        return s->autoidle;
-+
-+    case 0x14:	/* IPGENERICOCPSPL_SYSSTATUS */
-+        return 0x01;
-+
-+    case 0x18:	/* IPGENERICOCPSPL_IRQSTATUS */
-+        return 0x00;
-+
-+    case 0x40:	/* IPGENERICOCPSPL_GPO */
-+        return s->gpo;
-+
-+    case 0x50:	/* IPGENERICOCPSPL_GPI */
-+        return 0x00;
-+    }
-+
-+    OMAP_BAD_REG(addr);
-+    return 0;
-+}
-+
-+static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
-+    int offset = addr - s->topbase;
-+
-+    switch (offset) {
-+    case 0x00:	/* IPGENERICOCPSPL_REVISION */
-+    case 0x14:	/* IPGENERICOCPSPL_SYSSTATUS */
-+    case 0x18:	/* IPGENERICOCPSPL_IRQSTATUS */
-+    case 0x50:	/* IPGENERICOCPSPL_GPI */
-+        OMAP_RO_REG(addr);
-+        break;
-+
-+    case 0x10:	/* IPGENERICOCPSPL_SYSCONFIG */
-+        if (value & (1 << 1))					/* SOFTRESET */
-+            omap_gpif_reset(s);
-+        s->autoidle = value & 1;
-+        break;
-+
-+    case 0x40:	/* IPGENERICOCPSPL_GPO */
-+        s->gpo = value & 1;
-+        break;
-+
-+    default:
-+        OMAP_BAD_REG(addr);
-+        return;
-+    }
-+}
-+
-+static CPUReadMemoryFunc *omap_gpif_top_readfn[] = {
-+    omap_gpif_top_read,
-+    omap_gpif_top_read,
-+    omap_gpif_top_read,
-+};
-+
-+static CPUWriteMemoryFunc *omap_gpif_top_writefn[] = {
-+    omap_gpif_top_write,
-+    omap_gpif_top_write,
-+    omap_gpif_top_write,
-+};
-+
-+struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
-+                qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules)
-+{
-+    int iomemtype, i;
-+    struct omap_gpif_s *s = (struct omap_gpif_s *)
-+            qemu_mallocz(sizeof(struct omap_gpif_s));
-+    int region[4] = { 0, 2, 4, 5 };
-+
-+    s->modules = modules;
-+    for (i = 0; i < modules; i ++)
-+        omap_gpio_module_init(s->module + i, ta, region[i],
-+                        irq[i], 0, 0, fclk[i], iclk);
-+
-+    omap_gpif_reset(s);
-+
-+    iomemtype = cpu_register_io_memory(0, omap_gpif_top_readfn,
-+                    omap_gpif_top_writefn, s);
-+    s->topbase = omap_l4_attach(ta, 1, iomemtype);
-+
-+    return s;
-+}
-+
-+qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start)
-+{
-+    if (start >= s->modules * 32 || start < 0)
-+        cpu_abort(cpu_single_env, "%s: No GPIO line %i\n",
-+                        __FUNCTION__, start);
-+    return s->module[start >> 5].in + (start & 31);
-+}
-+
-+void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler)
-+{
-+    if (line >= s->modules * 32 || line < 0)
-+        cpu_abort(cpu_single_env, "%s: No GPIO line %i\n", __FUNCTION__, line);
-+    s->module[line >> 5].handler[line & 31] = handler;
-+}
-+
-+/* Multichannel SPI */
-+struct omap_mcspi_s {
-+    target_phys_addr_t base;
-+    qemu_irq irq;
-+    int chnum;
-+
-+    uint32_t sysconfig;
-+    uint32_t systest;
-+    uint32_t irqst;
-+    uint32_t irqen;
-+    uint32_t wken;
-+    uint32_t control;
-+
-+    struct omap_mcspi_ch_s {
-+        qemu_irq txdrq;
-+        qemu_irq rxdrq;
-+        uint32_t (*txrx)(void *opaque, uint32_t);
-+        void *opaque;
-+
-+        uint32_t tx;
-+        uint32_t rx;
-+
-+        uint32_t config;
-+        uint32_t status;
-+        uint32_t control;
-+    } ch[4];
-+};
-+
-+static inline void omap_mcspi_interrupt_update(struct omap_mcspi_s *s)
-+{
-+    qemu_set_irq(s->irq, s->irqst & s->irqen);
-+}
-+
-+static inline void omap_mcspi_dmarequest_update(struct omap_mcspi_ch_s *ch)
-+{
-+    qemu_set_irq(ch->txdrq,
-+                    (ch->control & 1) &&		/* EN */
-+                    (ch->config & (1 << 14)) &&		/* DMAW */
-+                    (ch->status & (1 << 1)) &&		/* TXS */
-+                    ((ch->config >> 12) & 3) != 1);	/* TRM */
-+    qemu_set_irq(ch->rxdrq,
-+                    (ch->control & 1) &&		/* EN */
-+                    (ch->config & (1 << 15)) &&		/* DMAW */
-+                    (ch->status & (1 << 0)) &&		/* RXS */
-+                    ((ch->config >> 12) & 3) != 2);	/* TRM */
-+}
-+
-+static void omap_mcspi_transfer_run(struct omap_mcspi_s *s, int chnum)
-+{
-+    struct omap_mcspi_ch_s *ch = s->ch + chnum;
-+
-+    if (!(ch->control & 1))				/* EN */
-+        return;
-+    if ((ch->status & (1 << 0)) &&			/* RXS */
-+                    ((ch->config >> 12) & 3) != 2 &&	/* TRM */
-+                    !(ch->config & (1 << 19)))		/* TURBO */
-+        goto intr_update;
-+    if ((ch->status & (1 << 1)) &&			/* TXS */
-+                    ((ch->config >> 12) & 3) != 1)	/* TRM */
-+        goto intr_update;
-+
-+    if (!(s->control & 1) ||				/* SINGLE */
-+                    (ch->config & (1 << 20))) {		/* FORCE */
-+        if (ch->txrx)
-+            ch->rx = ch->txrx(ch->opaque, ch->tx);
-+    }
-+
-+    ch->tx = 0;
-+    ch->status |= 1 << 2;				/* EOT */
-+    ch->status |= 1 << 1;				/* TXS */
-+    if (((ch->config >> 12) & 3) != 2)			/* TRM */
-+        ch->status |= 1 << 0;				/* RXS */
-+
-+intr_update:
-+    if ((ch->status & (1 << 0)) &&			/* RXS */
-+                    ((ch->config >> 12) & 3) != 2 &&	/* TRM */
-+                    !(ch->config & (1 << 19)))		/* TURBO */
-+        s->irqst |= 1 << (2 + 4 * chnum);		/* RX_FULL */
-+    if ((ch->status & (1 << 1)) &&			/* TXS */
-+                    ((ch->config >> 12) & 3) != 1)	/* TRM */
-+        s->irqst |= 1 << (0 + 4 * chnum);		/* TX_EMPTY */
-+    omap_mcspi_interrupt_update(s);
-+    omap_mcspi_dmarequest_update(ch);
-+}
-+
-+static void omap_mcspi_reset(struct omap_mcspi_s *s)
-+{
-+    int ch;
-+
-+    s->sysconfig = 0;
-+    s->systest = 0;
-+    s->irqst = 0;
-+    s->irqen = 0;
-+    s->wken = 0;
-+    s->control = 4;
-+
-+    for (ch = 0; ch < 4; ch ++) {
-+        s->ch[ch].config = 0x060000;
-+        s->ch[ch].status = 2;				/* TXS */
-+        s->ch[ch].control = 0;
-+
-+        omap_mcspi_dmarequest_update(s->ch + ch);
-+    }
-+
-+    omap_mcspi_interrupt_update(s);
-+}
-+
-+static uint32_t omap_mcspi_read(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
-+    int offset = addr - s->base;
-+    int ch = 0;
-+    uint32_t ret;
-+
-+    switch (offset) {
-+    case 0x00:	/* MCSPI_REVISION */
-+        return 0x91;
-+
-+    case 0x10:	/* MCSPI_SYSCONFIG */
-+        return s->sysconfig;
-+
-+    case 0x14:	/* MCSPI_SYSSTATUS */
-+        return 1;					/* RESETDONE */
-+
-+    case 0x18:	/* MCSPI_IRQSTATUS */
-+        return s->irqst;
-+
-+    case 0x1c:	/* MCSPI_IRQENABLE */
-+        return s->irqen;
-+
-+    case 0x20:	/* MCSPI_WAKEUPENABLE */
-+        return s->wken;
-+
-+    case 0x24:	/* MCSPI_SYST */
-+        return s->systest;
-+
-+    case 0x28:	/* MCSPI_MODULCTRL */
-+        return s->control;
-+
-+    case 0x68: ch ++;
-+    case 0x54: ch ++;
-+    case 0x40: ch ++;
-+    case 0x2c:	/* MCSPI_CHCONF */
-+        return s->ch[ch].config;
-+
-+    case 0x6c: ch ++;
-+    case 0x58: ch ++;
-+    case 0x44: ch ++;
-+    case 0x30:	/* MCSPI_CHSTAT */
-+        return s->ch[ch].status;
-+
-+    case 0x70: ch ++;
-+    case 0x5c: ch ++;
-+    case 0x48: ch ++;
-+    case 0x34:	/* MCSPI_CHCTRL */
-+        return s->ch[ch].control;
-+
-+    case 0x74: ch ++;
-+    case 0x60: ch ++;
-+    case 0x4c: ch ++;
-+    case 0x38:	/* MCSPI_TX */
-+        return s->ch[ch].tx;
-+
-+    case 0x78: ch ++;
-+    case 0x64: ch ++;
-+    case 0x50: ch ++;
-+    case 0x3c:	/* MCSPI_RX */
-+        s->ch[ch].status &= ~(1 << 0);			/* RXS */
-+        ret = s->ch[ch].rx;
-+        omap_mcspi_transfer_run(s, ch);
-+        return ret;
-+    }
-+
-+    OMAP_BAD_REG(addr);
-+    return 0;
-+}
-+
-+static void omap_mcspi_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
-+    int offset = addr - s->base;
-+    int ch = 0;
-+
-+    switch (offset) {
-+    case 0x00:	/* MCSPI_REVISION */
-+    case 0x14:	/* MCSPI_SYSSTATUS */
-+    case 0x30:	/* MCSPI_CHSTAT0 */
-+    case 0x3c:	/* MCSPI_RX0 */
-+    case 0x44:	/* MCSPI_CHSTAT1 */
-+    case 0x50:	/* MCSPI_RX1 */
-+    case 0x58:	/* MCSPI_CHSTAT2 */
-+    case 0x64:	/* MCSPI_RX2 */
-+    case 0x6c:	/* MCSPI_CHSTAT3 */
-+    case 0x78:	/* MCSPI_RX3 */
-+        OMAP_RO_REG(addr);
-+        return;
-+
-+    case 0x10:	/* MCSPI_SYSCONFIG */
-+        if (value & (1 << 1))				/* SOFTRESET */
-+            omap_mcspi_reset(s);
-+        s->sysconfig = value & 0x31d;
-+        break;
-+
-+    case 0x18:	/* MCSPI_IRQSTATUS */
-+        if (!((s->control & (1 << 3)) && (s->systest & (1 << 11)))) {
-+            s->irqst &= ~value;
-+            omap_mcspi_interrupt_update(s);
-+        }
-+        break;
-+
-+    case 0x1c:	/* MCSPI_IRQENABLE */
-+        s->irqen = value & 0x1777f;
-+        omap_mcspi_interrupt_update(s);
-+        break;
-+
-+    case 0x20:	/* MCSPI_WAKEUPENABLE */
-+        s->wken = value & 1;
-+        break;
-+
-+    case 0x24:	/* MCSPI_SYST */
-+        if (s->control & (1 << 3))			/* SYSTEM_TEST */
-+            if (value & (1 << 11)) {			/* SSB */
-+                s->irqst |= 0x1777f;
-+                omap_mcspi_interrupt_update(s);
-+            }
-+        s->systest = value & 0xfff;
-+        break;
-+
-+    case 0x28:	/* MCSPI_MODULCTRL */
-+        if (value & (1 << 3))				/* SYSTEM_TEST */
-+            if (s->systest & (1 << 11)) {		/* SSB */
-+                s->irqst |= 0x1777f;
-+                omap_mcspi_interrupt_update(s);
-+            }
-+        s->control = value & 0xf;
-+        break;
-+
-+    case 0x68: ch ++;
-+    case 0x54: ch ++;
-+    case 0x40: ch ++;
-+    case 0x2c:	/* MCSPI_CHCONF */
-+        if ((value ^ s->ch[ch].config) & (3 << 14))	/* DMAR | DMAW */
-+            omap_mcspi_dmarequest_update(s->ch + ch);
-+        if (((value >> 12) & 3) == 3)			/* TRM */
-+            fprintf(stderr, "%s: invalid TRM value (3)\n", __FUNCTION__);
-+        if (((value >> 7) & 0x1f) < 3)			/* WL */
-+            fprintf(stderr, "%s: invalid WL value (%i)\n",
-+                            __FUNCTION__, (value >> 7) & 0x1f);
-+        s->ch[ch].config = value & 0x7fffff;
-+        break;
-+
-+    case 0x70: ch ++;
-+    case 0x5c: ch ++;
-+    case 0x48: ch ++;
-+    case 0x34:	/* MCSPI_CHCTRL */
-+        if (value & ~s->ch[ch].control & 1) {		/* EN */
-+            s->ch[ch].control |= 1;
-+            omap_mcspi_transfer_run(s, ch);
-+        } else
-+            s->ch[ch].control = value & 1;
-+        break;
-+
-+    case 0x74: ch ++;
-+    case 0x60: ch ++;
-+    case 0x4c: ch ++;
-+    case 0x38:	/* MCSPI_TX */
-+        s->ch[ch].tx = value;
-+        s->ch[ch].status &= ~(1 << 1);			/* TXS */
-+        omap_mcspi_transfer_run(s, ch);
-+        break;
-+
-+    default:
-+        OMAP_BAD_REG(addr);
-+        return;
-+    }
-+}
-+
-+static CPUReadMemoryFunc *omap_mcspi_readfn[] = {
-+    omap_badwidth_read32,
-+    omap_badwidth_read32,
-+    omap_mcspi_read,
-+};
-+
-+static CPUWriteMemoryFunc *omap_mcspi_writefn[] = {
-+    omap_badwidth_write32,
-+    omap_badwidth_write32,
-+    omap_mcspi_write,
-+};
-+
-+struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum,
-+                qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
-+{
-+    int iomemtype;
-+    struct omap_mcspi_s *s = (struct omap_mcspi_s *)
-+            qemu_mallocz(sizeof(struct omap_mcspi_s));
-+    struct omap_mcspi_ch_s *ch = s->ch;
-+
-+    s->irq = irq;
-+    s->chnum = chnum;
-+    while (chnum --) {
-+        ch->txdrq = *drq ++;
-+        ch->rxdrq = *drq ++;
-+        ch ++;
-+    }
-+    omap_mcspi_reset(s);
-+
-+    iomemtype = cpu_register_io_memory(0, omap_mcspi_readfn,
-+                    omap_mcspi_writefn, s);
-+    s->base = omap_l4_attach(ta, 0, iomemtype);
-+
-+    return s;
-+}
-+
-+void omap_mcspi_attach(struct omap_mcspi_s *s,
-+                uint32_t (*txrx)(void *opaque, uint32_t), void *opaque,
-+                int chipselect)
-+{
-+    if (chipselect < 0 || chipselect >= s->chnum)
-+        cpu_abort(cpu_single_env, "%s: Bad chipselect %i\n",
-+                        __FUNCTION__, chipselect);
-+
-+    s->ch[chipselect].txrx = txrx;
-+    s->ch[chipselect].opaque = opaque;
-+}
-+
-+/* L4 Interconnect */
-+struct omap_target_agent_s {
-+    struct omap_l4_s *bus;
-+    int regions;
-+    struct omap_l4_region_s *start;
-+    target_phys_addr_t base;
-+    uint32_t component;
-+    uint32_t control;
-+    uint32_t status;
-+};
-+
-+struct omap_l4_s {
-+    target_phys_addr_t base;
-+    int ta_num;
-+    struct omap_target_agent_s ta[0];
-+};
-+
-+struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num)
-+{
-+    struct omap_l4_s *bus = qemu_mallocz(
-+                    sizeof(*bus) + ta_num * sizeof(*bus->ta));
-+
-+    bus->ta_num = ta_num;
-+    bus->base = base;
-+
-+    return bus;
-+}
-+
-+static uint32_t omap_l4ta_read(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
-+    target_phys_addr_t reg = addr - s->base;
-+
-+    switch (reg) {
-+    case 0x00:	/* COMPONENT */
-+        return s->component;
-+
-+    case 0x20:	/* AGENT_CONTROL */
-+        return s->control;
-+
-+    case 0x28:	/* AGENT_STATUS */
-+        return s->status;
-+    }
-+
-+    OMAP_BAD_REG(addr);
-+    return 0;
-+}
-+
-+static void omap_l4ta_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
-+    target_phys_addr_t reg = addr - s->base;
-+
-+    switch (reg) {
-+    case 0x00:	/* COMPONENT */
-+    case 0x28:	/* AGENT_STATUS */
-+        OMAP_RO_REG(addr);
-+        break;
-+
-+    case 0x20:	/* AGENT_CONTROL */
-+        s->control = value & 0x01000700;
-+        if (value & 1)					/* OCP_RESET */
-+            s->status &= ~1;				/* REQ_TIMEOUT */
-+        break;
-+
-+    default:
-+        OMAP_BAD_REG(addr);
-+    }
-+}
-+
-+static CPUReadMemoryFunc *omap_l4ta_readfn[] = {
-+    omap_badwidth_read16,
-+    omap_l4ta_read,
-+    omap_badwidth_read16,
-+};
-+
-+static CPUWriteMemoryFunc *omap_l4ta_writefn[] = {
-+    omap_badwidth_write32,
-+    omap_badwidth_write32,
-+    omap_l4ta_write,
-+};
-+
-+#define L4TA(n)		(n)
-+#define L4TAO(n)	((n) + 39)
-+
-+static struct omap_l4_region_s {
-+    target_phys_addr_t offset;
-+    size_t size;
-+    int access;
-+} omap_l4_region[125] = {
-+    [  1] = { 0x40800,  0x800, 32          }, /* Initiator agent */
-+    [  2] = { 0x41000, 0x1000, 32          }, /* Link agent */
-+    [  0] = { 0x40000,  0x800, 32          }, /* Address and protection */
-+    [  3] = { 0x00000, 0x1000, 32 | 16 | 8 }, /* System Control and Pinout */
-+    [  4] = { 0x01000, 0x1000, 32 | 16 | 8 }, /* L4TAO1 */
-+    [  5] = { 0x04000, 0x1000, 32 | 16     }, /* 32K Timer */
-+    [  6] = { 0x05000, 0x1000, 32 | 16 | 8 }, /* L4TAO2 */
-+    [  7] = { 0x08000,  0x800, 32          }, /* PRCM Region A */
-+    [  8] = { 0x08800,  0x800, 32          }, /* PRCM Region B */
-+    [  9] = { 0x09000, 0x1000, 32 | 16 | 8 }, /* L4TAO */
-+    [ 10] = { 0x12000, 0x1000, 32 | 16 | 8 }, /* Test (BCM) */
-+    [ 11] = { 0x13000, 0x1000, 32 | 16 | 8 }, /* L4TA1 */
-+    [ 12] = { 0x14000, 0x1000, 32          }, /* Test/emulation (TAP) */
-+    [ 13] = { 0x15000, 0x1000, 32 | 16 | 8 }, /* L4TA2 */
-+    [ 14] = { 0x18000, 0x1000, 32 | 16 | 8 }, /* GPIO1 */
-+    [ 16] = { 0x1a000, 0x1000, 32 | 16 | 8 }, /* GPIO2 */
-+    [ 18] = { 0x1c000, 0x1000, 32 | 16 | 8 }, /* GPIO3 */
-+    [ 19] = { 0x1e000, 0x1000, 32 | 16 | 8 }, /* GPIO4 */
-+    [ 15] = { 0x19000, 0x1000, 32 | 16 | 8 }, /* Quad GPIO TOP */
-+    [ 17] = { 0x1b000, 0x1000, 32 | 16 | 8 }, /* L4TA3 */
-+    [ 20] = { 0x20000, 0x1000, 32 | 16 | 8 }, /* WD Timer 1 (Secure) */
-+    [ 22] = { 0x22000, 0x1000, 32 | 16 | 8 }, /* WD Timer 2 (OMAP) */
-+    [ 21] = { 0x21000, 0x1000, 32 | 16 | 8 }, /* Dual WD timer TOP */
-+    [ 23] = { 0x23000, 0x1000, 32 | 16 | 8 }, /* L4TA4 */
-+    [ 24] = { 0x28000, 0x1000, 32 | 16 | 8 }, /* GP Timer 1 */
-+    [ 25] = { 0x29000, 0x1000, 32 | 16 | 8 }, /* L4TA7 */
-+    [ 26] = { 0x48000, 0x2000, 32 | 16 | 8 }, /* Emulation (ARM11ETB) */
-+    [ 27] = { 0x4a000, 0x1000, 32 | 16 | 8 }, /* L4TA9 */
-+    [ 28] = { 0x50000,  0x400, 32 | 16 | 8 }, /* Display top */
-+    [ 29] = { 0x50400,  0x400, 32 | 16 | 8 }, /* Display control */
-+    [ 30] = { 0x50800,  0x400, 32 | 16 | 8 }, /* Display RFBI */
-+    [ 31] = { 0x50c00,  0x400, 32 | 16 | 8 }, /* Display encoder */
-+    [ 32] = { 0x51000, 0x1000, 32 | 16 | 8 }, /* L4TA10 */
-+    [ 33] = { 0x52000,  0x400, 32 | 16 | 8 }, /* Camera top */
-+    [ 34] = { 0x52400,  0x400, 32 | 16 | 8 }, /* Camera core */
-+    [ 35] = { 0x52800,  0x400, 32 | 16 | 8 }, /* Camera DMA */
-+    [ 36] = { 0x52c00,  0x400, 32 | 16 | 8 }, /* Camera MMU */
-+    [ 37] = { 0x53000, 0x1000, 32 | 16 | 8 }, /* L4TA11 */
-+    [ 38] = { 0x56000, 0x1000, 32 | 16 | 8 }, /* sDMA */
-+    [ 39] = { 0x57000, 0x1000, 32 | 16 | 8 }, /* L4TA12 */
-+    [ 40] = { 0x58000, 0x1000, 32 | 16 | 8 }, /* SSI top */
-+    [ 41] = { 0x59000, 0x1000, 32 | 16 | 8 }, /* SSI GDD */
-+    [ 42] = { 0x5a000, 0x1000, 32 | 16 | 8 }, /* SSI Port1 */
-+    [ 43] = { 0x5b000, 0x1000, 32 | 16 | 8 }, /* SSI Port2 */
-+    [ 44] = { 0x5c000, 0x1000, 32 | 16 | 8 }, /* L4TA13 */
-+    [ 45] = { 0x5e000, 0x1000, 32 | 16 | 8 }, /* USB OTG */
-+    [ 46] = { 0x5f000, 0x1000, 32 | 16 | 8 }, /* L4TAO4 */
-+    [ 47] = { 0x60000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER1SDRC) */
-+    [ 48] = { 0x61000, 0x1000, 32 | 16 | 8 }, /* L4TA14 */
-+    [ 49] = { 0x62000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER2GPMC) */
-+    [ 50] = { 0x63000, 0x1000, 32 | 16 | 8 }, /* L4TA15 */
-+    [ 51] = { 0x64000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER3OCM) */
-+    [ 52] = { 0x65000, 0x1000, 32 | 16 | 8 }, /* L4TA16 */
-+    [ 53] = { 0x66000,  0x300, 32 | 16 | 8 }, /* Emulation (WIN_TRACER4L4) */
-+    [ 54] = { 0x67000, 0x1000, 32 | 16 | 8 }, /* L4TA17 */
-+    [ 55] = { 0x68000, 0x1000, 32 | 16 | 8 }, /* Emulation (XTI) */
-+    [ 56] = { 0x69000, 0x1000, 32 | 16 | 8 }, /* L4TA18 */
-+    [ 57] = { 0x6a000, 0x1000,      16 | 8 }, /* UART1 */
-+    [ 58] = { 0x6b000, 0x1000, 32 | 16 | 8 }, /* L4TA19 */
-+    [ 59] = { 0x6c000, 0x1000,      16 | 8 }, /* UART2 */
-+    [ 60] = { 0x6d000, 0x1000, 32 | 16 | 8 }, /* L4TA20 */
-+    [ 61] = { 0x6e000, 0x1000,      16 | 8 }, /* UART3 */
-+    [ 62] = { 0x6f000, 0x1000, 32 | 16 | 8 }, /* L4TA21 */
-+    [ 63] = { 0x70000, 0x1000,      16     }, /* I2C1 */
-+    [ 64] = { 0x71000, 0x1000, 32 | 16 | 8 }, /* L4TAO5 */
-+    [ 65] = { 0x72000, 0x1000,      16     }, /* I2C2 */
-+    [ 66] = { 0x73000, 0x1000, 32 | 16 | 8 }, /* L4TAO6 */
-+    [ 67] = { 0x74000, 0x1000,      16     }, /* McBSP1 */
-+    [ 68] = { 0x75000, 0x1000, 32 | 16 | 8 }, /* L4TAO7 */
-+    [ 69] = { 0x76000, 0x1000,      16     }, /* McBSP2 */
-+    [ 70] = { 0x77000, 0x1000, 32 | 16 | 8 }, /* L4TAO8 */
-+    [ 71] = { 0x24000, 0x1000, 32 | 16 | 8 }, /* WD Timer 3 (DSP) */
-+    [ 72] = { 0x25000, 0x1000, 32 | 16 | 8 }, /* L4TA5 */
-+    [ 73] = { 0x26000, 0x1000, 32 | 16 | 8 }, /* WD Timer 4 (IVA) */
-+    [ 74] = { 0x27000, 0x1000, 32 | 16 | 8 }, /* L4TA6 */
-+    [ 75] = { 0x2a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 2 */
-+    [ 76] = { 0x2b000, 0x1000, 32 | 16 | 8 }, /* L4TA8 */
-+    [ 77] = { 0x78000, 0x1000, 32 | 16 | 8 }, /* GP Timer 3 */
-+    [ 78] = { 0x79000, 0x1000, 32 | 16 | 8 }, /* L4TA22 */
-+    [ 79] = { 0x7a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 4 */
-+    [ 80] = { 0x7b000, 0x1000, 32 | 16 | 8 }, /* L4TA23 */
-+    [ 81] = { 0x7c000, 0x1000, 32 | 16 | 8 }, /* GP Timer 5 */
-+    [ 82] = { 0x7d000, 0x1000, 32 | 16 | 8 }, /* L4TA24 */
-+    [ 83] = { 0x7e000, 0x1000, 32 | 16 | 8 }, /* GP Timer 6 */
-+    [ 84] = { 0x7f000, 0x1000, 32 | 16 | 8 }, /* L4TA25 */
-+    [ 85] = { 0x80000, 0x1000, 32 | 16 | 8 }, /* GP Timer 7 */
-+    [ 86] = { 0x81000, 0x1000, 32 | 16 | 8 }, /* L4TA26 */
-+    [ 87] = { 0x82000, 0x1000, 32 | 16 | 8 }, /* GP Timer 8 */
-+    [ 88] = { 0x83000, 0x1000, 32 | 16 | 8 }, /* L4TA27 */
-+    [ 89] = { 0x84000, 0x1000, 32 | 16 | 8 }, /* GP Timer 9 */
-+    [ 90] = { 0x85000, 0x1000, 32 | 16 | 8 }, /* L4TA28 */
-+    [ 91] = { 0x86000, 0x1000, 32 | 16 | 8 }, /* GP Timer 10 */
-+    [ 92] = { 0x87000, 0x1000, 32 | 16 | 8 }, /* L4TA29 */
-+    [ 93] = { 0x88000, 0x1000, 32 | 16 | 8 }, /* GP Timer 11 */
-+    [ 94] = { 0x89000, 0x1000, 32 | 16 | 8 }, /* L4TA30 */
-+    [ 95] = { 0x8a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 12 */
-+    [ 96] = { 0x8b000, 0x1000, 32 | 16 | 8 }, /* L4TA31 */
-+    [ 97] = { 0x90000, 0x1000,      16     }, /* EAC */
-+    [ 98] = { 0x91000, 0x1000, 32 | 16 | 8 }, /* L4TA32 */
-+    [ 99] = { 0x92000, 0x1000,      16     }, /* FAC */
-+    [100] = { 0x93000, 0x1000, 32 | 16 | 8 }, /* L4TA33 */
-+    [101] = { 0x94000, 0x1000, 32 | 16 | 8 }, /* IPC (MAILBOX) */
-+    [102] = { 0x95000, 0x1000, 32 | 16 | 8 }, /* L4TA34 */
-+    [103] = { 0x98000, 0x1000, 32 | 16 | 8 }, /* SPI1 */
-+    [104] = { 0x99000, 0x1000, 32 | 16 | 8 }, /* L4TA35 */
-+    [105] = { 0x9a000, 0x1000, 32 | 16 | 8 }, /* SPI2 */
-+    [106] = { 0x9b000, 0x1000, 32 | 16 | 8 }, /* L4TA36 */
-+    [107] = { 0x9c000, 0x1000,      16 | 8 }, /* MMC SDIO */
-+    [108] = { 0x9d000, 0x1000, 32 | 16 | 8 }, /* L4TAO9 */
-+    [109] = { 0x9e000, 0x1000, 32 | 16 | 8 }, /* MS_PRO */
-+    [110] = { 0x9f000, 0x1000, 32 | 16 | 8 }, /* L4TAO10 */
-+    [111] = { 0xa0000, 0x1000, 32          }, /* RNG */
-+    [112] = { 0xa1000, 0x1000, 32 | 16 | 8 }, /* L4TAO11 */
-+    [113] = { 0xa2000, 0x1000, 32          }, /* DES3DES */
-+    [114] = { 0xa3000, 0x1000, 32 | 16 | 8 }, /* L4TAO12 */
-+    [115] = { 0xa4000, 0x1000, 32          }, /* SHA1MD5 */
-+    [116] = { 0xa5000, 0x1000, 32 | 16 | 8 }, /* L4TAO13 */
-+    [117] = { 0xa6000, 0x1000, 32          }, /* AES */
-+    [118] = { 0xa7000, 0x1000, 32 | 16 | 8 }, /* L4TA37 */
-+    [119] = { 0xa8000, 0x2000, 32          }, /* PKA */
-+    [120] = { 0xaa000, 0x1000, 32 | 16 | 8 }, /* L4TA38 */
-+    [121] = { 0xb0000, 0x1000, 32          }, /* MG */
-+    [122] = { 0xb1000, 0x1000, 32 | 16 | 8 },
-+    [123] = { 0xb2000, 0x1000, 32          }, /* HDQ/1-Wire */
-+    [124] = { 0xb3000, 0x1000, 32 | 16 | 8 }, /* L4TA39 */
-+};
-+
-+static struct omap_l4_agent_info_s {
-+    int ta;
-+    int region;
-+    int regions;
-+    int ta_region;
-+} omap_l4_agent_info[54] = {
-+    { 0,           0, 3, 2 }, /* L4IA initiatior agent */
-+    { L4TAO(1),    3, 2, 1 }, /* Control and pinout module */
-+    { L4TAO(2),    5, 2, 1 }, /* 32K timer */
-+    { L4TAO(3),    7, 3, 2 }, /* PRCM */
-+    { L4TA(1),    10, 2, 1 }, /* BCM */
-+    { L4TA(2),    12, 2, 1 }, /* Test JTAG */
-+    { L4TA(3),    14, 6, 3 }, /* Quad GPIO */
-+    { L4TA(4),    20, 4, 3 }, /* WD timer 1/2 */
-+    { L4TA(7),    24, 2, 1 }, /* GP timer 1 */
-+    { L4TA(9),    26, 2, 1 }, /* ATM11 ETB */
-+    { L4TA(10),   28, 5, 4 }, /* Display subsystem */
-+    { L4TA(11),   33, 5, 4 }, /* Camera subsystem */
-+    { L4TA(12),   38, 2, 1 }, /* sDMA */
-+    { L4TA(13),   40, 5, 4 }, /* SSI */
-+    { L4TAO(4),   45, 2, 1 }, /* USB */
-+    { L4TA(14),   47, 2, 1 }, /* Win Tracer1 */
-+    { L4TA(15),   49, 2, 1 }, /* Win Tracer2 */
-+    { L4TA(16),   51, 2, 1 }, /* Win Tracer3 */
-+    { L4TA(17),   53, 2, 1 }, /* Win Tracer4 */
-+    { L4TA(18),   55, 2, 1 }, /* XTI */
-+    { L4TA(19),   57, 2, 1 }, /* UART1 */
-+    { L4TA(20),   59, 2, 1 }, /* UART2 */
-+    { L4TA(21),   61, 2, 1 }, /* UART3 */
-+    { L4TAO(5),   63, 2, 1 }, /* I2C1 */
-+    { L4TAO(6),   65, 2, 1 }, /* I2C2 */
-+    { L4TAO(7),   67, 2, 1 }, /* McBSP1 */
-+    { L4TAO(8),   69, 2, 1 }, /* McBSP2 */
-+    { L4TA(5),    71, 2, 1 }, /* WD Timer 3 (DSP) */
-+    { L4TA(6),    73, 2, 1 }, /* WD Timer 4 (IVA) */
-+    { L4TA(8),    75, 2, 1 }, /* GP Timer 2 */
-+    { L4TA(22),   77, 2, 1 }, /* GP Timer 3 */
-+    { L4TA(23),   79, 2, 1 }, /* GP Timer 4 */
-+    { L4TA(24),   81, 2, 1 }, /* GP Timer 5 */
-+    { L4TA(25),   83, 2, 1 }, /* GP Timer 6 */
-+    { L4TA(26),   85, 2, 1 }, /* GP Timer 7 */
-+    { L4TA(27),   87, 2, 1 }, /* GP Timer 8 */
-+    { L4TA(28),   89, 2, 1 }, /* GP Timer 9 */
-+    { L4TA(29),   91, 2, 1 }, /* GP Timer 10 */
-+    { L4TA(30),   93, 2, 1 }, /* GP Timer 11 */
-+    { L4TA(31),   95, 2, 1 }, /* GP Timer 12 */
-+    { L4TA(32),   97, 2, 1 }, /* EAC */
-+    { L4TA(33),   99, 2, 1 }, /* FAC */
-+    { L4TA(34),  101, 2, 1 }, /* IPC */
-+    { L4TA(35),  103, 2, 1 }, /* SPI1 */
-+    { L4TA(36),  105, 2, 1 }, /* SPI2 */
-+    { L4TAO(9),  107, 2, 1 }, /* MMC SDIO */
-+    { L4TAO(10), 109, 2, 1 },
-+    { L4TAO(11), 111, 2, 1 }, /* RNG */
-+    { L4TAO(12), 113, 2, 1 }, /* DES3DES */
-+    { L4TAO(13), 115, 2, 1 }, /* SHA1MD5 */
-+    { L4TA(37),  117, 2, 1 }, /* AES */
-+    { L4TA(38),  119, 2, 1 }, /* PKA */
-+    { -1,        121, 2, 1 },
-+    { L4TA(39),  123, 2, 1 }, /* HDQ/1-Wire */
-+};
-+
-+#define omap_l4ta(bus, cs)	omap_l4ta_get(bus, L4TA(cs))
-+#define omap_l4tao(bus, cs)	omap_l4ta_get(bus, L4TAO(cs))
-+
-+struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus, int cs)
-+{
-+    int i, iomemtype;
-+    struct omap_target_agent_s *ta = 0;
-+    struct omap_l4_agent_info_s *info = 0;
-+
-+    for (i = 0; i < bus->ta_num; i ++)
-+        if (omap_l4_agent_info[i].ta == cs) {
-+            ta = &bus->ta[i];
-+            info = &omap_l4_agent_info[i];
-+            break;
-+        }
-+    if (!ta) {
-+        fprintf(stderr, "%s: bad target agent (%i)\n", __FUNCTION__, cs);
-+        exit(-1);
-+    }
-+
-+    ta->bus = bus;
-+    ta->start = &omap_l4_region[info->region];
-+    ta->regions = info->regions;
-+    ta->base = bus->base + ta->start[info->ta_region].offset;
-+
-+    ta->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
-+    ta->status = 0x00000000;
-+    ta->control = 0x00000200;	/* XXX 01000200 for L4TAO */
-+
-+    iomemtype = cpu_register_io_memory(0, omap_l4ta_readfn,
-+                    omap_l4ta_writefn, ta);
-+    cpu_register_physical_memory(ta->base, 0x200, iomemtype);
-+
-+    return ta;
-+}
-+
-+target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
-+                int iotype)
-+{
-+    target_phys_addr_t base;
-+    size_t size;
-+
-+    if (region < 0 || region >= ta->regions) {
-+        fprintf(stderr, "%s: bad io region (%i)\n", __FUNCTION__, region);
-+        exit(-1);
-+    }
-+
-+    base = ta->bus->base + ta->start[region].offset;
-+    size = ta->start[region].size;
-+    if (iotype)
-+        cpu_register_physical_memory(base, size, iotype);
-+
-+    return base;
-+}
-+
-+/* TEST-Chip-level TAP */
-+static uint32_t omap_tap_read(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-+    target_phys_addr_t reg = addr - s->tap_base;
-+
-+    switch (reg) {
-+    case 0x204:	/* IDCODE_reg */
-+        switch (s->mpu_model) {
-+        case omap2420:
-+        case omap2422:
-+        case omap2423:
-+            return 0x5b5d902f;	/* ES 2.2 */
-+        case omap2430:
-+            return 0x5b68a02f;	/* ES 2.2 */
-+        case omap3430:
-+            return 0x1b7ae02f;	/* ES 2 */
-+        default:
-+            cpu_abort(cpu_single_env, "%s: Bad mpu model\n", __FUNCTION__);
-+        }
-+
-+    case 0x208:	/* PRODUCTION_ID_reg for OMAP2 */
-+    case 0x210:	/* PRODUCTION_ID_reg for OMAP3 */
-+        switch (s->mpu_model) {
-+        case omap2420:
-+            return 0x000200f0;	/* POP ESHS2.1.1 in N91/93/95, ES2 in N800 */
-+        case omap2422:
-+            return 0x000400f0;
-+        case omap2423:
-+            return 0x000800f0;
-+        case omap2430:
-+            return 0x000000f0;
-+        case omap3430:
-+            return 0x000000f0;
-+        default:
-+            cpu_abort(cpu_single_env, "%s: Bad mpu model\n", __FUNCTION__);
-+        }
-+
-+    case 0x218:	/* DIE_ID_reg */
-+        return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
-+    case 0x21c:	/* DIE_ID_reg */
-+        return (  5 << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
-+    case 0x220:	/* DIE_ID_reg */
-+        return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
-+    case 0x224:	/* DIE_ID_reg */
-+        return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
-+    }
-+
-+    OMAP_BAD_REG(addr);
-+    return 0;
-+}
-+
-+static void omap_tap_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    OMAP_BAD_REG(addr);
-+}
-+
-+static CPUReadMemoryFunc *omap_tap_readfn[] = {
-+    omap_badwidth_read32,
-+    omap_badwidth_read32,
-+    omap_tap_read,
-+};
-+
-+static CPUWriteMemoryFunc *omap_tap_writefn[] = {
-+    omap_badwidth_write32,
-+    omap_badwidth_write32,
-+    omap_tap_write,
-+};
-+
-+void omap_tap_init(struct omap_target_agent_s *ta,
-+                struct omap_mpu_state_s *mpu)
-+{
-+    mpu->tap_base = omap_l4_attach(ta, 0, cpu_register_io_memory(0,
-+                            omap_tap_readfn, omap_tap_writefn, mpu));
-+}
-+
-+/* Power, Reset, and Clock Management */
-+struct omap_prcm_s {
-+    target_phys_addr_t base;
-+    qemu_irq irq[3];
-+    struct omap_mpu_state_s *mpu;
-+
-+    uint32_t irqst[3];
-+    uint32_t irqen[3];
-+
-+    uint32_t sysconfig;
-+    uint32_t voltctrl;
-+    uint32_t scratch[20];
-+
-+    uint32_t clksrc[1];
-+    uint32_t clkout[1];
-+    uint32_t clkemul[1];
-+    uint32_t clkpol[1];
-+    uint32_t clksel[8];
-+    uint32_t clken[12];
-+    uint32_t clkctrl[4];
-+    uint32_t clkidle[7];
-+    uint32_t setuptime[2];
-+
-+    uint32_t wkup[3];
-+    uint32_t wken[3];
-+    uint32_t wkst[3];
-+    uint32_t rst[4];
-+    uint32_t rstctrl[1];
-+    uint32_t power[4];
-+    uint32_t rsttime_wkup;
-+
-+    uint32_t ev;
-+    uint32_t evtime[2];
-+};
-+
-+static void omap_prcm_int_update(struct omap_prcm_s *s, int dom)
-+{
-+    qemu_set_irq(s->irq[dom], s->irqst[dom] & s->irqen[dom]);
-+    /* XXX or is the mask applied before PRCM_IRQSTATUS_* ? */
-+}
-+
-+static uint32_t omap_prcm_read(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
-+    int offset = addr - s->base;
-+
-+    switch (offset) {
-+    case 0x000:	/* PRCM_REVISION */
-+        return 0x10;
-+
-+    case 0x010:	/* PRCM_SYSCONFIG */
-+        return s->sysconfig;
-+
-+    case 0x018:	/* PRCM_IRQSTATUS_MPU */
-+        return s->irqst[0];
-+
-+    case 0x01c:	/* PRCM_IRQENABLE_MPU */
-+        return s->irqen[0];
-+
-+    case 0x050:	/* PRCM_VOLTCTRL */
-+        return s->voltctrl;
-+    case 0x054:	/* PRCM_VOLTST */
-+        return s->voltctrl & 3;
-+
-+    case 0x060:	/* PRCM_CLKSRC_CTRL */
-+        return s->clksrc[0];
-+    case 0x070:	/* PRCM_CLKOUT_CTRL */
-+        return s->clkout[0];
-+    case 0x078:	/* PRCM_CLKEMUL_CTRL */
-+        return s->clkemul[0];
-+    case 0x080:	/* PRCM_CLKCFG_CTRL */
-+    case 0x084:	/* PRCM_CLKCFG_STATUS */
-+        return 0;
-+
-+    case 0x090:	/* PRCM_VOLTSETUP */
-+        return s->setuptime[0];
-+
-+    case 0x094:	/* PRCM_CLKSSETUP */
-+        return s->setuptime[1];
-+
-+    case 0x098:	/* PRCM_POLCTRL */
-+        return s->clkpol[0];
-+
-+    case 0x0b0:	/* GENERAL_PURPOSE1 */
-+    case 0x0b4:	/* GENERAL_PURPOSE2 */
-+    case 0x0b8:	/* GENERAL_PURPOSE3 */
-+    case 0x0bc:	/* GENERAL_PURPOSE4 */
-+    case 0x0c0:	/* GENERAL_PURPOSE5 */
-+    case 0x0c4:	/* GENERAL_PURPOSE6 */
-+    case 0x0c8:	/* GENERAL_PURPOSE7 */
-+    case 0x0cc:	/* GENERAL_PURPOSE8 */
-+    case 0x0d0:	/* GENERAL_PURPOSE9 */
-+    case 0x0d4:	/* GENERAL_PURPOSE10 */
-+    case 0x0d8:	/* GENERAL_PURPOSE11 */
-+    case 0x0dc:	/* GENERAL_PURPOSE12 */
-+    case 0x0e0:	/* GENERAL_PURPOSE13 */
-+    case 0x0e4:	/* GENERAL_PURPOSE14 */
-+    case 0x0e8:	/* GENERAL_PURPOSE15 */
-+    case 0x0ec:	/* GENERAL_PURPOSE16 */
-+    case 0x0f0:	/* GENERAL_PURPOSE17 */
-+    case 0x0f4:	/* GENERAL_PURPOSE18 */
-+    case 0x0f8:	/* GENERAL_PURPOSE19 */
-+    case 0x0fc:	/* GENERAL_PURPOSE20 */
-+        return s->scratch[(offset - 0xb0) >> 2];
-+
-+    case 0x140:	/* CM_CLKSEL_MPU */
-+        return s->clksel[0];
-+    case 0x148:	/* CM_CLKSTCTRL_MPU */
-+        return s->clkctrl[0];
-+
-+    case 0x158:	/* RM_RSTST_MPU */
-+        return s->rst[0];
-+    case 0x1c8:	/* PM_WKDEP_MPU */
-+        return s->wkup[0];
-+    case 0x1d4:	/* PM_EVGENCTRL_MPU */
-+        return s->ev;
-+    case 0x1d8:	/* PM_EVEGENONTIM_MPU */
-+        return s->evtime[0];
-+    case 0x1dc:	/* PM_EVEGENOFFTIM_MPU */
-+        return s->evtime[1];
-+    case 0x1e0:	/* PM_PWSTCTRL_MPU */
-+        return s->power[0];
-+    case 0x1e4:	/* PM_PWSTST_MPU */
-+        return 0;
-+
-+    case 0x200:	/* CM_FCLKEN1_CORE */
-+        return s->clken[0];
-+    case 0x204:	/* CM_FCLKEN2_CORE */
-+        return s->clken[1];
-+    case 0x210:	/* CM_ICLKEN1_CORE */
-+        return s->clken[2];
-+    case 0x214:	/* CM_ICLKEN2_CORE */
-+        return s->clken[3];
-+    case 0x21c:	/* CM_ICLKEN4_CORE */
-+        return s->clken[4];
-+
-+    case 0x220:	/* CM_IDLEST1_CORE */
-+        /* TODO: check the actual iclk status */
-+        return 0x7ffffff9;
-+    case 0x224:	/* CM_IDLEST2_CORE */
-+        /* TODO: check the actual iclk status */
-+        return 0x00000007;
-+    case 0x22c:	/* CM_IDLEST4_CORE */
-+        /* TODO: check the actual iclk status */
-+        return 0x0000001f;
-+
-+    case 0x230:	/* CM_AUTOIDLE1_CORE */
-+        return s->clkidle[0];
-+    case 0x234:	/* CM_AUTOIDLE2_CORE */
-+        return s->clkidle[1];
-+    case 0x238:	/* CM_AUTOIDLE3_CORE */
-+        return s->clkidle[2];
-+    case 0x23c:	/* CM_AUTOIDLE4_CORE */
-+        return s->clkidle[3];
-+
-+    case 0x240:	/* CM_CLKSEL1_CORE */
-+        return s->clksel[1];
-+    case 0x244:	/* CM_CLKSEL2_CORE */
-+        return s->clksel[2];
-+
-+    case 0x248:	/* CM_CLKSTCTRL_CORE */
-+        return s->clkctrl[1];
-+
-+    case 0x2a0:	/* PM_WKEN1_CORE */
-+        return s->wken[0];
-+    case 0x2a4:	/* PM_WKEN2_CORE */
-+        return s->wken[1];
-+
-+    case 0x2b0:	/* PM_WKST1_CORE */
-+        return s->wkst[0];
-+    case 0x2b4:	/* PM_WKST2_CORE */
-+        return s->wkst[1];
-+    case 0x2c8:	/* PM_WKDEP_CORE */
-+        return 0x1e;
-+
-+    case 0x2e0:	/* PM_PWSTCTRL_CORE */
-+        return s->power[1];
-+    case 0x2e4:	/* PM_PWSTST_CORE */
-+        return 0x000030 | (s->power[1] & 0xfc00);
-+
-+    case 0x300:	/* CM_FCLKEN_GFX */
-+        return s->clken[5];
-+    case 0x310:	/* CM_ICLKEN_GFX */
-+        return s->clken[6];
-+    case 0x320:	/* CM_IDLEST_GFX */
-+        /* TODO: check the actual iclk status */
-+        return 0x00000001;
-+    case 0x340:	/* CM_CLKSEL_GFX */
-+        return s->clksel[3];
-+    case 0x348:	/* CM_CLKSTCTRL_GFX */
-+        return s->clkctrl[2];
-+    case 0x350:	/* RM_RSTCTRL_GFX */
-+        return s->rstctrl[0];
-+    case 0x358:	/* RM_RSTST_GFX */
-+        return s->rst[1];
-+    case 0x3c8:	/* PM_WKDEP_GFX */
-+        return s->wkup[1];
-+
-+    case 0x3e0:	/* PM_PWSTCTRL_GFX */
-+        return s->power[2];
-+    case 0x3e4:	/* PM_PWSTST_GFX */
-+        return s->power[2] & 3;
-+
-+    case 0x400:	/* CM_FCLKEN_WKUP */
-+        return s->clken[7];
-+    case 0x410:	/* CM_ICLKEN_WKUP */
-+        return s->clken[8];
-+    case 0x420:	/* CM_IDLEST_WKUP */
-+        /* TODO: check the actual iclk status */
-+        return 0x0000003f;
-+    case 0x430:	/* CM_AUTOIDLE_WKUP */
-+        return s->clkidle[4];
-+    case 0x440:	/* CM_CLKSEL_WKUP */
-+        return s->clksel[4];
-+    case 0x450:	/* RM_RSTCTRL_WKUP */
-+        return 0;
-+    case 0x454:	/* RM_RSTTIME_WKUP */
-+        return s->rsttime_wkup;
-+    case 0x458:	/* RM_RSTST_WKUP */
-+        return s->rst[2];
-+    case 0x4a0:	/* PM_WKEN_WKUP */
-+        return s->wken[2];
-+    case 0x4b0:	/* PM_WKST_WKUP */
-+        return s->wkst[2];
-+
-+    case 0x500:	/* CM_CLKEN_PLL */
-+        return s->clken[9];
-+    case 0x520:	/* CM_IDLEST_CKGEN */
-+        /* Core uses 32-kHz clock */
-+        if (!(s->clksel[6] & 3))
-+            return 0x00000377;
-+        /* DPLL not in lock mode, core uses ref_clk */
-+        if ((s->clken[9] & 3) != 3)
-+            return 0x00000375;
-+        /* Core uses DPLL */
-+        return 0x00000376;
-+    case 0x530:	/* CM_AUTOIDLE_PLL */
-+        return s->clkidle[5];
-+    case 0x540:	/* CM_CLKSEL1_PLL */
-+        return s->clksel[5];
-+    case 0x544:	/* CM_CLKSEL2_PLL */
-+        return s->clksel[6];
-+
-+    case 0x800:	/* CM_FCLKEN_DSP */
-+        return s->clken[10];
-+    case 0x810:	/* CM_ICLKEN_DSP */
-+        return s->clken[11];
-+    case 0x820:	/* CM_IDLEST_DSP */
-+        /* TODO: check the actual iclk status */
-+        return 0x00000103;
-+    case 0x830:	/* CM_AUTOIDLE_DSP */
-+        return s->clkidle[6];
-+    case 0x840:	/* CM_CLKSEL_DSP */
-+        return s->clksel[7];
-+    case 0x848:	/* CM_CLKSTCTRL_DSP */
-+        return s->clkctrl[3];
-+    case 0x850:	/* RM_RSTCTRL_DSP */
-+        return 0;
-+    case 0x858:	/* RM_RSTST_DSP */
-+        return s->rst[3];
-+    case 0x8c8:	/* PM_WKDEP_DSP */
-+        return s->wkup[2];
-+    case 0x8e0:	/* PM_PWSTCTRL_DSP */
-+        return s->power[3];
-+    case 0x8e4:	/* PM_PWSTST_DSP */
-+        return 0x008030 | (s->power[3] & 0x3003);
-+
-+    case 0x8f0:	/* PRCM_IRQSTATUS_DSP */
-+        return s->irqst[1];
-+    case 0x8f4:	/* PRCM_IRQENABLE_DSP */
-+        return s->irqen[1];
-+
-+    case 0x8f8:	/* PRCM_IRQSTATUS_IVA */
-+        return s->irqst[2];
-+    case 0x8fc:	/* PRCM_IRQENABLE_IVA */
-+        return s->irqen[2];
-+    }
-+
-+    OMAP_BAD_REG(addr);
-+    return 0;
-+}
-+
-+static void omap_prcm_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
-+    int offset = addr - s->base;
-+
-+    switch (offset) {
-+    case 0x000:	/* PRCM_REVISION */
-+    case 0x054:	/* PRCM_VOLTST */
-+    case 0x084:	/* PRCM_CLKCFG_STATUS */
-+    case 0x1e4:	/* PM_PWSTST_MPU */
-+    case 0x220:	/* CM_IDLEST1_CORE */
-+    case 0x224:	/* CM_IDLEST2_CORE */
-+    case 0x22c:	/* CM_IDLEST4_CORE */
-+    case 0x2c8:	/* PM_WKDEP_CORE */
-+    case 0x2e4:	/* PM_PWSTST_CORE */
-+    case 0x320:	/* CM_IDLEST_GFX */
-+    case 0x3e4:	/* PM_PWSTST_GFX */
-+    case 0x420:	/* CM_IDLEST_WKUP */
-+    case 0x520:	/* CM_IDLEST_CKGEN */
-+    case 0x820:	/* CM_IDLEST_DSP */
-+    case 0x8e4:	/* PM_PWSTST_DSP */
-+        OMAP_RO_REG(addr);
-+        return;
-+
-+    case 0x010:	/* PRCM_SYSCONFIG */
-+        s->sysconfig = value & 1;
-+        break;
-+
-+    case 0x018:	/* PRCM_IRQSTATUS_MPU */
-+        s->irqst[0] &= ~value;
-+        omap_prcm_int_update(s, 0);
-+        break;
-+    case 0x01c:	/* PRCM_IRQENABLE_MPU */
-+        s->irqen[0] = value & 0x3f;
-+        omap_prcm_int_update(s, 0);
-+        break;
-+
-+    case 0x050:	/* PRCM_VOLTCTRL */
-+        s->voltctrl = value & 0xf1c3;
-+        break;
-+
-+    case 0x060:	/* PRCM_CLKSRC_CTRL */
-+        s->clksrc[0] = value & 0xdb;
-+        /* TODO update clocks */
-+        break;
-+
-+    case 0x070:	/* PRCM_CLKOUT_CTRL */
-+        s->clkout[0] = value & 0xbbbb;
-+        /* TODO update clocks */
-+        break;
-+
-+    case 0x078:	/* PRCM_CLKEMUL_CTRL */
-+        s->clkemul[0] = value & 1;
-+        /* TODO update clocks */
-+        break;
-+
-+    case 0x080:	/* PRCM_CLKCFG_CTRL */
-+        break;
-+
-+    case 0x090:	/* PRCM_VOLTSETUP */
-+        s->setuptime[0] = value & 0xffff;
-+        break;
-+    case 0x094:	/* PRCM_CLKSSETUP */
-+        s->setuptime[1] = value & 0xffff;
-+        break;
-+
-+    case 0x098:	/* PRCM_POLCTRL */
-+        s->clkpol[0] = value & 0x701;
-+        break;
-+
-+    case 0x0b0:	/* GENERAL_PURPOSE1 */
-+    case 0x0b4:	/* GENERAL_PURPOSE2 */
-+    case 0x0b8:	/* GENERAL_PURPOSE3 */
-+    case 0x0bc:	/* GENERAL_PURPOSE4 */
-+    case 0x0c0:	/* GENERAL_PURPOSE5 */
-+    case 0x0c4:	/* GENERAL_PURPOSE6 */
-+    case 0x0c8:	/* GENERAL_PURPOSE7 */
-+    case 0x0cc:	/* GENERAL_PURPOSE8 */
-+    case 0x0d0:	/* GENERAL_PURPOSE9 */
-+    case 0x0d4:	/* GENERAL_PURPOSE10 */
-+    case 0x0d8:	/* GENERAL_PURPOSE11 */
-+    case 0x0dc:	/* GENERAL_PURPOSE12 */
-+    case 0x0e0:	/* GENERAL_PURPOSE13 */
-+    case 0x0e4:	/* GENERAL_PURPOSE14 */
-+    case 0x0e8:	/* GENERAL_PURPOSE15 */
-+    case 0x0ec:	/* GENERAL_PURPOSE16 */
-+    case 0x0f0:	/* GENERAL_PURPOSE17 */
-+    case 0x0f4:	/* GENERAL_PURPOSE18 */
-+    case 0x0f8:	/* GENERAL_PURPOSE19 */
-+    case 0x0fc:	/* GENERAL_PURPOSE20 */
-+        s->scratch[(offset - 0xb0) >> 2] = value;
-+        break;
-+
-+    case 0x140:	/* CM_CLKSEL_MPU */
-+        s->clksel[0] = value & 0x1f;
-+        /* TODO update clocks */
-+        break;
-+    case 0x148:	/* CM_CLKSTCTRL_MPU */
-+        s->clkctrl[0] = value & 0x1f;
-+        break;
-+
-+    case 0x158:	/* RM_RSTST_MPU */
-+        s->rst[0] &= ~value;
-+        break;
-+    case 0x1c8:	/* PM_WKDEP_MPU */
-+        s->wkup[0] = value & 0x15;
-+        break;
-+
-+    case 0x1d4:	/* PM_EVGENCTRL_MPU */
-+        s->ev = value & 0x1f;
-+        break;
-+    case 0x1d8:	/* PM_EVEGENONTIM_MPU */
-+        s->evtime[0] = value;
-+        break;
-+    case 0x1dc:	/* PM_EVEGENOFFTIM_MPU */
-+        s->evtime[1] = value;
-+        break;
-+
-+    case 0x1e0:	/* PM_PWSTCTRL_MPU */
-+        s->power[0] = value & 0xc0f;
-+        break;
-+
-+    case 0x200:	/* CM_FCLKEN1_CORE */
-+        s->clken[0] = value & 0xbfffffff;
-+        /* TODO update clocks */
-+        break;
-+    case 0x204:	/* CM_FCLKEN2_CORE */
-+        s->clken[1] = value & 0x00000007;
-+        /* TODO update clocks */
-+        break;
-+    case 0x210:	/* CM_ICLKEN1_CORE */
-+        s->clken[2] = value & 0xfffffff9;
-+        /* TODO update clocks */
-+        break;
-+    case 0x214:	/* CM_ICLKEN2_CORE */
-+        s->clken[3] = value & 0x00000007;
-+        /* TODO update clocks */
-+        break;
-+    case 0x21c:	/* CM_ICLKEN4_CORE */
-+        s->clken[4] = value & 0x0000001f;
-+        /* TODO update clocks */
-+        break;
-+
-+    case 0x230:	/* CM_AUTOIDLE1_CORE */
-+        s->clkidle[0] = value & 0xfffffff9;
-+        /* TODO update clocks */
-+        break;
-+    case 0x234:	/* CM_AUTOIDLE2_CORE */
-+        s->clkidle[1] = value & 0x00000007;
-+        /* TODO update clocks */
-+        break;
-+    case 0x238:	/* CM_AUTOIDLE3_CORE */
-+        s->clkidle[2] = value & 0x00000007;
-+        /* TODO update clocks */
-+        break;
-+    case 0x23c:	/* CM_AUTOIDLE4_CORE */
-+        s->clkidle[3] = value & 0x0000001f;
-+        /* TODO update clocks */
-+        break;
-+
-+    case 0x240:	/* CM_CLKSEL1_CORE */
-+        s->clksel[1] = value & 0x0fffbf7f;
-+        /* TODO update clocks */
-+        break;
-+
-+    case 0x244:	/* CM_CLKSEL2_CORE */
-+        s->clksel[2] = value & 0x00fffffc;
-+        /* TODO update clocks */
-+        break;
-+
-+    case 0x248:	/* CM_CLKSTCTRL_CORE */
-+        s->clkctrl[1] = value & 0x7;
-+        break;
-+
-+    case 0x2a0:	/* PM_WKEN1_CORE */
-+        s->wken[0] = value & 0x04667ff8;
-+        break;
-+    case 0x2a4:	/* PM_WKEN2_CORE */
-+        s->wken[1] = value & 0x00000005;
-+        break;
-+
-+    case 0x2b0:	/* PM_WKST1_CORE */
-+        s->wkst[0] &= ~value;
-+        break;
-+    case 0x2b4:	/* PM_WKST2_CORE */
-+        s->wkst[1] &= ~value;
-+        break;
-+
-+    case 0x2e0:	/* PM_PWSTCTRL_CORE */
-+        s->power[1] = (value & 0x00fc3f) | (1 << 2);
-+        break;
-+
-+    case 0x300:	/* CM_FCLKEN_GFX */
-+        s->clken[5] = value & 6;
-+        /* TODO update clocks */
-+        break;
-+    case 0x310:	/* CM_ICLKEN_GFX */
-+        s->clken[6] = value & 1;
-+        /* TODO update clocks */
-+        break;
-+    case 0x340:	/* CM_CLKSEL_GFX */
-+        s->clksel[3] = value & 7;
-+        /* TODO update clocks */
-+        break;
-+    case 0x348:	/* CM_CLKSTCTRL_GFX */
-+        s->clkctrl[2] = value & 1;
-+        break;
-+    case 0x350:	/* RM_RSTCTRL_GFX */
-+        s->rstctrl[0] = value & 1;
-+        /* TODO: reset */
-+        break;
-+    case 0x358:	/* RM_RSTST_GFX */
-+        s->rst[1] &= ~value;
-+        break;
-+    case 0x3c8:	/* PM_WKDEP_GFX */
-+        s->wkup[1] = value & 0x13;
-+        break;
-+    case 0x3e0:	/* PM_PWSTCTRL_GFX */
-+        s->power[2] = (value & 0x00c0f) | (3 << 2);
-+        break;
-+
-+    case 0x400:	/* CM_FCLKEN_WKUP */
-+        s->clken[7] = value & 0xd;
-+        /* TODO update clocks */
-+        break;
-+    case 0x410:	/* CM_ICLKEN_WKUP */
-+        s->clken[8] = value & 0x3f;
-+        /* TODO update clocks */
-+        break;
-+    case 0x430:	/* CM_AUTOIDLE_WKUP */
-+        s->clkidle[4] = value & 0x0000003f;
-+        /* TODO update clocks */
-+        break;
-+    case 0x440:	/* CM_CLKSEL_WKUP */
-+        s->clksel[4] = value & 3;
-+        /* TODO update clocks */
-+        break;
-+    case 0x450:	/* RM_RSTCTRL_WKUP */
-+        /* TODO: reset */
-+        if (value & 2)
-+            qemu_system_reset_request();
-+        break;
-+    case 0x454:	/* RM_RSTTIME_WKUP */
-+        s->rsttime_wkup = value & 0x1fff;
-+        break;
-+    case 0x458:	/* RM_RSTST_WKUP */
-+        s->rst[2] &= ~value;
-+        break;
-+    case 0x4a0:	/* PM_WKEN_WKUP */
-+        s->wken[2] = value & 0x00000005;
-+        break;
-+    case 0x4b0:	/* PM_WKST_WKUP */
-+        s->wkst[2] &= ~value;
-+        break;
-+
-+    case 0x500:	/* CM_CLKEN_PLL */
-+        s->clken[9] = value & 0xcf;
-+        /* TODO update clocks */
-+        break;
-+    case 0x530:	/* CM_AUTOIDLE_PLL */
-+        s->clkidle[5] = value & 0x000000cf;
-+        /* TODO update clocks */
-+        break;
-+    case 0x540:	/* CM_CLKSEL1_PLL */
-+        s->clksel[5] = value & 0x03bfff28;
-+        /* TODO update clocks */
-+        break;
-+    case 0x544:	/* CM_CLKSEL2_PLL */
-+        s->clksel[6] = value & 3;
-+        /* TODO update clocks */
-+        break;
-+
-+    case 0x800:	/* CM_FCLKEN_DSP */
-+        s->clken[10] = value & 0x501;
-+        /* TODO update clocks */
-+        break;
-+    case 0x810:	/* CM_ICLKEN_DSP */
-+        s->clken[11] = value & 0x2;
-+        /* TODO update clocks */
-+        break;
-+    case 0x830:	/* CM_AUTOIDLE_DSP */
-+        s->clkidle[6] = value & 0x2;
-+        /* TODO update clocks */
-+        break;
-+    case 0x840:	/* CM_CLKSEL_DSP */
-+        s->clksel[7] = value & 0x3fff;
-+        /* TODO update clocks */
-+        break;
-+    case 0x848:	/* CM_CLKSTCTRL_DSP */
-+        s->clkctrl[3] = value & 0x101;
-+        break;
-+    case 0x850:	/* RM_RSTCTRL_DSP */
-+        /* TODO: reset */
-+        break;
-+    case 0x858:	/* RM_RSTST_DSP */
-+        s->rst[3] &= ~value;
-+        break;
-+    case 0x8c8:	/* PM_WKDEP_DSP */
-+        s->wkup[2] = value & 0x13;
-+        break;
-+    case 0x8e0:	/* PM_PWSTCTRL_DSP */
-+        s->power[3] = (value & 0x03017) | (3 << 2);
-+        break;
-+
-+    case 0x8f0:	/* PRCM_IRQSTATUS_DSP */
-+        s->irqst[1] &= ~value;
-+        omap_prcm_int_update(s, 1);
-+        break;
-+    case 0x8f4:	/* PRCM_IRQENABLE_DSP */
-+        s->irqen[1] = value & 0x7;
-+        omap_prcm_int_update(s, 1);
-+        break;
-+
-+    case 0x8f8:	/* PRCM_IRQSTATUS_IVA */
-+        s->irqst[2] &= ~value;
-+        omap_prcm_int_update(s, 2);
-+        break;
-+    case 0x8fc:	/* PRCM_IRQENABLE_IVA */
-+        s->irqen[2] = value & 0x7;
-+        omap_prcm_int_update(s, 2);
-+        break;
-+
-+    default:
-+        OMAP_BAD_REG(addr);
-+        return;
-+    }
-+}
-+
-+static CPUReadMemoryFunc *omap_prcm_readfn[] = {
-+    omap_badwidth_read32,
-+    omap_badwidth_read32,
-+    omap_prcm_read,
-+};
-+
-+static CPUWriteMemoryFunc *omap_prcm_writefn[] = {
-+    omap_badwidth_write32,
-+    omap_badwidth_write32,
-+    omap_prcm_write,
-+};
-+
-+static void omap_prcm_reset(struct omap_prcm_s *s)
-+{
-+    s->sysconfig = 0;
-+    s->irqst[0] = 0;
-+    s->irqst[1] = 0;
-+    s->irqst[2] = 0;
-+    s->irqen[0] = 0;
-+    s->irqen[1] = 0;
-+    s->irqen[2] = 0;
-+    s->voltctrl = 0x1040;
-+    s->ev = 0x14;
-+    s->evtime[0] = 0;
-+    s->evtime[1] = 0;
-+    s->clkctrl[0] = 0;
-+    s->clkctrl[1] = 0;
-+    s->clkctrl[2] = 0;
-+    s->clkctrl[3] = 0;
-+    s->clken[1] = 7;
-+    s->clken[3] = 7;
-+    s->clken[4] = 0;
-+    s->clken[5] = 0;
-+    s->clken[6] = 0;
-+    s->clken[7] = 0xc;
-+    s->clken[8] = 0x3e;
-+    s->clken[9] = 0x0d;
-+    s->clken[10] = 0;
-+    s->clken[11] = 0;
-+    s->clkidle[0] = 0;
-+    s->clkidle[2] = 7;
-+    s->clkidle[3] = 0;
-+    s->clkidle[4] = 0;
-+    s->clkidle[5] = 0x0c;
-+    s->clkidle[6] = 0;
-+    s->clksel[0] = 0x01;
-+    s->clksel[1] = 0x02100121;
-+    s->clksel[2] = 0x00000000;
-+    s->clksel[3] = 0x01;
-+    s->clksel[4] = 0;
-+    s->clksel[7] = 0x0121;
-+    s->wkup[0] = 0x15;
-+    s->wkup[1] = 0x13;
-+    s->wkup[2] = 0x13;
-+    s->wken[0] = 0x04667ff8;
-+    s->wken[1] = 0x00000005;
-+    s->wken[2] = 5;
-+    s->wkst[0] = 0;
-+    s->wkst[1] = 0;
-+    s->wkst[2] = 0;
-+    s->power[0] = 0x00c;
-+    s->power[1] = 4;
-+    s->power[2] = 0x0000c;
-+    s->power[3] = 0x14;
-+    s->rstctrl[0] = 1;
-+    s->rst[3] = 1;
-+}
-+
-+static void omap_prcm_coldreset(struct omap_prcm_s *s)
-+{
-+    s->setuptime[0] = 0;
-+    s->setuptime[1] = 0;
-+    memset(&s->scratch, 0, sizeof(s->scratch));
-+    s->rst[0] = 0x01;
-+    s->rst[1] = 0x00;
-+    s->rst[2] = 0x01;
-+    s->clken[0] = 0;
-+    s->clken[2] = 0;
-+    s->clkidle[1] = 0;
-+    s->clksel[5] = 0;
-+    s->clksel[6] = 2;
-+    s->clksrc[0] = 0x43;
-+    s->clkout[0] = 0x0303;
-+    s->clkemul[0] = 0;
-+    s->clkpol[0] = 0x100;
-+    s->rsttime_wkup = 0x1002;
-+
-+    omap_prcm_reset(s);
-+}
-+
-+struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
-+                qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
-+                struct omap_mpu_state_s *mpu)
-+{
-+    int iomemtype;
-+    struct omap_prcm_s *s = (struct omap_prcm_s *)
-+            qemu_mallocz(sizeof(struct omap_prcm_s));
-+
-+    s->irq[0] = mpu_int;
-+    s->irq[1] = dsp_int;
-+    s->irq[2] = iva_int;
-+    s->mpu = mpu;
-+    omap_prcm_coldreset(s);
-+
-+    iomemtype = cpu_register_io_memory(0, omap_prcm_readfn,
-+                    omap_prcm_writefn, s);
-+    s->base = omap_l4_attach(ta, 0, iomemtype);
-+    omap_l4_attach(ta, 1, iomemtype);
-+
-+    return s;
-+}
-+
-+/* System and Pinout control */
-+struct omap_sysctl_s {
-+    target_phys_addr_t base;
-+    struct omap_mpu_state_s *mpu;
-+
-+    uint32_t sysconfig;
-+    uint32_t devconfig;
-+    uint32_t psaconfig;
-+    uint32_t padconf[0x45];
-+    uint8_t obs;
-+    uint32_t msuspendmux[5];
-+};
-+
-+static uint32_t omap_sysctl_read(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
-+    int offset = addr - s->base;
-+
-+    switch (offset) {
-+    case 0x000:	/* CONTROL_REVISION */
-+        return 0x20;
-+
-+    case 0x010:	/* CONTROL_SYSCONFIG */
-+        return s->sysconfig;
-+
-+    case 0x030 ... 0x140:	/* CONTROL_PADCONF - only used in the POP */
-+        return s->padconf[(offset - 0x30) >> 2];
-+
-+    case 0x270:	/* CONTROL_DEBOBS */
-+        return s->obs;
-+
-+    case 0x274:	/* CONTROL_DEVCONF */
-+        return s->devconfig;
-+
-+    case 0x28c:	/* CONTROL_EMU_SUPPORT */
-+        return 0;
-+
-+    case 0x290:	/* CONTROL_MSUSPENDMUX_0 */
-+        return s->msuspendmux[0];
-+    case 0x294:	/* CONTROL_MSUSPENDMUX_1 */
-+        return s->msuspendmux[1];
-+    case 0x298:	/* CONTROL_MSUSPENDMUX_2 */
-+        return s->msuspendmux[2];
-+    case 0x29c:	/* CONTROL_MSUSPENDMUX_3 */
-+        return s->msuspendmux[3];
-+    case 0x2a0:	/* CONTROL_MSUSPENDMUX_4 */
-+        return s->msuspendmux[4];
-+    case 0x2a4:	/* CONTROL_MSUSPENDMUX_5 */
-+        return 0;
-+
-+    case 0x2b8:	/* CONTROL_PSA_CTRL */
-+        return s->psaconfig;
-+    case 0x2bc:	/* CONTROL_PSA_CMD */
-+    case 0x2c0:	/* CONTROL_PSA_VALUE */
-+        return 0;
-+
-+    case 0x2b0:	/* CONTROL_SEC_CTRL */
-+        return 0x800000f1;
-+    case 0x2d0:	/* CONTROL_SEC_EMU */
-+        return 0x80000015;
-+    case 0x2d4:	/* CONTROL_SEC_TAP */
-+        return 0x8000007f;
-+    case 0x2b4:	/* CONTROL_SEC_TEST */
-+    case 0x2f0:	/* CONTROL_SEC_STATUS */
-+    case 0x2f4:	/* CONTROL_SEC_ERR_STATUS */
-+        /* Secure mode is not present on general-pusrpose device.  Outside
-+         * secure mode these values cannot be read or written.  */
-+        return 0;
-+
-+    case 0x2d8:	/* CONTROL_OCM_RAM_PERM */
-+        return 0xff;
-+    case 0x2dc:	/* CONTROL_OCM_PUB_RAM_ADD */
-+    case 0x2e0:	/* CONTROL_EXT_SEC_RAM_START_ADD */
-+    case 0x2e4:	/* CONTROL_EXT_SEC_RAM_STOP_ADD */
-+        /* No secure mode so no Extended Secure RAM present.  */
-+        return 0;
-+
-+    case 0x2f8:	/* CONTROL_STATUS */
-+        /* Device Type => General-purpose */
-+        return 0x0300;
-+    case 0x2fc:	/* CONTROL_GENERAL_PURPOSE_STATUS */
-+
-+    case 0x300:	/* CONTROL_RPUB_KEY_H_0 */
-+    case 0x304:	/* CONTROL_RPUB_KEY_H_1 */
-+    case 0x308:	/* CONTROL_RPUB_KEY_H_2 */
-+    case 0x30c:	/* CONTROL_RPUB_KEY_H_3 */
-+        return 0xdecafbad;
-+
-+    case 0x310:	/* CONTROL_RAND_KEY_0 */
-+    case 0x314:	/* CONTROL_RAND_KEY_1 */
-+    case 0x318:	/* CONTROL_RAND_KEY_2 */
-+    case 0x31c:	/* CONTROL_RAND_KEY_3 */
-+    case 0x320:	/* CONTROL_CUST_KEY_0 */
-+    case 0x324:	/* CONTROL_CUST_KEY_1 */
-+    case 0x330:	/* CONTROL_TEST_KEY_0 */
-+    case 0x334:	/* CONTROL_TEST_KEY_1 */
-+    case 0x338:	/* CONTROL_TEST_KEY_2 */
-+    case 0x33c:	/* CONTROL_TEST_KEY_3 */
-+    case 0x340:	/* CONTROL_TEST_KEY_4 */
-+    case 0x344:	/* CONTROL_TEST_KEY_5 */
-+    case 0x348:	/* CONTROL_TEST_KEY_6 */
-+    case 0x34c:	/* CONTROL_TEST_KEY_7 */
-+    case 0x350:	/* CONTROL_TEST_KEY_8 */
-+    case 0x354:	/* CONTROL_TEST_KEY_9 */
-+        /* Can only be accessed in secure mode and when C_FieldAccEnable
-+         * bit is set in CONTROL_SEC_CTRL.
-+         * TODO: otherwise an interconnect access error is generated.  */
-+        return 0;
-+    }
-+
-+    OMAP_BAD_REG(addr);
-+    return 0;
-+}
-+
-+static void omap_sysctl_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
-+    int offset = addr - s->base;
-+
-+    switch (offset) {
-+    case 0x000:	/* CONTROL_REVISION */
-+    case 0x2a4:	/* CONTROL_MSUSPENDMUX_5 */
-+    case 0x2c0:	/* CONTROL_PSA_VALUE */
-+    case 0x2f8:	/* CONTROL_STATUS */
-+    case 0x2fc:	/* CONTROL_GENERAL_PURPOSE_STATUS */
-+    case 0x300:	/* CONTROL_RPUB_KEY_H_0 */
-+    case 0x304:	/* CONTROL_RPUB_KEY_H_1 */
-+    case 0x308:	/* CONTROL_RPUB_KEY_H_2 */
-+    case 0x30c:	/* CONTROL_RPUB_KEY_H_3 */
-+    case 0x310:	/* CONTROL_RAND_KEY_0 */
-+    case 0x314:	/* CONTROL_RAND_KEY_1 */
-+    case 0x318:	/* CONTROL_RAND_KEY_2 */
-+    case 0x31c:	/* CONTROL_RAND_KEY_3 */
-+    case 0x320:	/* CONTROL_CUST_KEY_0 */
-+    case 0x324:	/* CONTROL_CUST_KEY_1 */
-+    case 0x330:	/* CONTROL_TEST_KEY_0 */
-+    case 0x334:	/* CONTROL_TEST_KEY_1 */
-+    case 0x338:	/* CONTROL_TEST_KEY_2 */
-+    case 0x33c:	/* CONTROL_TEST_KEY_3 */
-+    case 0x340:	/* CONTROL_TEST_KEY_4 */
-+    case 0x344:	/* CONTROL_TEST_KEY_5 */
-+    case 0x348:	/* CONTROL_TEST_KEY_6 */
-+    case 0x34c:	/* CONTROL_TEST_KEY_7 */
-+    case 0x350:	/* CONTROL_TEST_KEY_8 */
-+    case 0x354:	/* CONTROL_TEST_KEY_9 */
-+        OMAP_RO_REG(addr);
-+        return;
-+
-+    case 0x010:	/* CONTROL_SYSCONFIG */
-+        s->sysconfig = value & 0x1e;
-+        break;
-+
-+    case 0x030 ... 0x140:	/* CONTROL_PADCONF - only used in the POP */
-+        /* XXX: should check constant bits */
-+        s->padconf[(offset - 0x30) >> 2] = value & 0x1f1f1f1f;
-+        break;
-+
-+    case 0x270:	/* CONTROL_DEBOBS */
-+        s->obs = value & 0xff;
-+        break;
-+
-+    case 0x274:	/* CONTROL_DEVCONF */
-+        s->devconfig = value & 0xffffc7ff;
-+        break;
-+
-+    case 0x28c:	/* CONTROL_EMU_SUPPORT */
-+        break;
-+
-+    case 0x290:	/* CONTROL_MSUSPENDMUX_0 */
-+        s->msuspendmux[0] = value & 0x3fffffff;
-+        break;
-+    case 0x294:	/* CONTROL_MSUSPENDMUX_1 */
-+        s->msuspendmux[1] = value & 0x3fffffff;
-+        break;
-+    case 0x298:	/* CONTROL_MSUSPENDMUX_2 */
-+        s->msuspendmux[2] = value & 0x3fffffff;
-+        break;
-+    case 0x29c:	/* CONTROL_MSUSPENDMUX_3 */
-+        s->msuspendmux[3] = value & 0x3fffffff;
-+        break;
-+    case 0x2a0:	/* CONTROL_MSUSPENDMUX_4 */
-+        s->msuspendmux[4] = value & 0x3fffffff;
-+        break;
-+
-+    case 0x2b8:	/* CONTROL_PSA_CTRL */
-+        s->psaconfig = value & 0x1c;
-+        s->psaconfig |= (value & 0x20) ? 2 : 1;
-+        break;
-+    case 0x2bc:	/* CONTROL_PSA_CMD */
-+        break;
-+
-+    case 0x2b0:	/* CONTROL_SEC_CTRL */
-+    case 0x2b4:	/* CONTROL_SEC_TEST */
-+    case 0x2d0:	/* CONTROL_SEC_EMU */
-+    case 0x2d4:	/* CONTROL_SEC_TAP */
-+    case 0x2d8:	/* CONTROL_OCM_RAM_PERM */
-+    case 0x2dc:	/* CONTROL_OCM_PUB_RAM_ADD */
-+    case 0x2e0:	/* CONTROL_EXT_SEC_RAM_START_ADD */
-+    case 0x2e4:	/* CONTROL_EXT_SEC_RAM_STOP_ADD */
-+    case 0x2f0:	/* CONTROL_SEC_STATUS */
-+    case 0x2f4:	/* CONTROL_SEC_ERR_STATUS */
-+        break;
-+
-+    default:
-+        OMAP_BAD_REG(addr);
-+        return;
-+    }
-+}
-+
-+static CPUReadMemoryFunc *omap_sysctl_readfn[] = {
-+    omap_badwidth_read32,	/* TODO */
-+    omap_badwidth_read32,	/* TODO */
-+    omap_sysctl_read,
-+};
-+
-+static CPUWriteMemoryFunc *omap_sysctl_writefn[] = {
-+    omap_badwidth_write32,	/* TODO */
-+    omap_badwidth_write32,	/* TODO */
-+    omap_sysctl_write,
-+};
-+
-+static void omap_sysctl_reset(struct omap_sysctl_s *s)
-+{
-+    /* (power-on reset) */
-+    s->sysconfig = 0;
-+    s->obs = 0;
-+    s->devconfig = 0x0c000000;
-+    s->msuspendmux[0] = 0x00000000;
-+    s->msuspendmux[1] = 0x00000000;
-+    s->msuspendmux[2] = 0x00000000;
-+    s->msuspendmux[3] = 0x00000000;
-+    s->msuspendmux[4] = 0x00000000;
-+    s->psaconfig = 1;
-+
-+    s->padconf[0x00] = 0x000f0f0f;
-+    s->padconf[0x01] = 0x00000000;
-+    s->padconf[0x02] = 0x00000000;
-+    s->padconf[0x03] = 0x00000000;
-+    s->padconf[0x04] = 0x00000000;
-+    s->padconf[0x05] = 0x00000000;
-+    s->padconf[0x06] = 0x00000000;
-+    s->padconf[0x07] = 0x00000000;
-+    s->padconf[0x08] = 0x08080800;
-+    s->padconf[0x09] = 0x08080808;
-+    s->padconf[0x0a] = 0x08080808;
-+    s->padconf[0x0b] = 0x08080808;
-+    s->padconf[0x0c] = 0x08080808;
-+    s->padconf[0x0d] = 0x08080800;
-+    s->padconf[0x0e] = 0x08080808;
-+    s->padconf[0x0f] = 0x08080808;
-+    s->padconf[0x10] = 0x18181808;	/* | 0x07070700 if SBoot3 */
-+    s->padconf[0x11] = 0x18181818;	/* | 0x07070707 if SBoot3 */
-+    s->padconf[0x12] = 0x18181818;	/* | 0x07070707 if SBoot3 */
-+    s->padconf[0x13] = 0x18181818;	/* | 0x07070707 if SBoot3 */
-+    s->padconf[0x14] = 0x18181818;	/* | 0x00070707 if SBoot3 */
-+    s->padconf[0x15] = 0x18181818;
-+    s->padconf[0x16] = 0x18181818;	/* | 0x07000000 if SBoot3 */
-+    s->padconf[0x17] = 0x1f001f00;
-+    s->padconf[0x18] = 0x1f1f1f1f;
-+    s->padconf[0x19] = 0x00000000;
-+    s->padconf[0x1a] = 0x1f180000;
-+    s->padconf[0x1b] = 0x00001f1f;
-+    s->padconf[0x1c] = 0x1f001f00;
-+    s->padconf[0x1d] = 0x00000000;
-+    s->padconf[0x1e] = 0x00000000;
-+    s->padconf[0x1f] = 0x08000000;
-+    s->padconf[0x20] = 0x08080808;
-+    s->padconf[0x21] = 0x08080808;
-+    s->padconf[0x22] = 0x0f080808;
-+    s->padconf[0x23] = 0x0f0f0f0f;
-+    s->padconf[0x24] = 0x000f0f0f;
-+    s->padconf[0x25] = 0x1f1f1f0f;
-+    s->padconf[0x26] = 0x080f0f1f;
-+    s->padconf[0x27] = 0x070f1808;
-+    s->padconf[0x28] = 0x0f070707;
-+    s->padconf[0x29] = 0x000f0f1f;
-+    s->padconf[0x2a] = 0x0f0f0f1f;
-+    s->padconf[0x2b] = 0x08000000;
-+    s->padconf[0x2c] = 0x0000001f;
-+    s->padconf[0x2d] = 0x0f0f1f00;
-+    s->padconf[0x2e] = 0x1f1f0f0f;
-+    s->padconf[0x2f] = 0x0f1f1f1f;
-+    s->padconf[0x30] = 0x0f0f0f0f;
-+    s->padconf[0x31] = 0x0f1f0f1f;
-+    s->padconf[0x32] = 0x0f0f0f0f;
-+    s->padconf[0x33] = 0x0f1f0f1f;
-+    s->padconf[0x34] = 0x1f1f0f0f;
-+    s->padconf[0x35] = 0x0f0f1f1f;
-+    s->padconf[0x36] = 0x0f0f1f0f;
-+    s->padconf[0x37] = 0x0f0f0f0f;
-+    s->padconf[0x38] = 0x1f18180f;
-+    s->padconf[0x39] = 0x1f1f1f1f;
-+    s->padconf[0x3a] = 0x00001f1f;
-+    s->padconf[0x3b] = 0x00000000;
-+    s->padconf[0x3c] = 0x00000000;
-+    s->padconf[0x3d] = 0x0f0f0f0f;
-+    s->padconf[0x3e] = 0x18000f0f;
-+    s->padconf[0x3f] = 0x00070000;
-+    s->padconf[0x40] = 0x00000707;
-+    s->padconf[0x41] = 0x0f1f0700;
-+    s->padconf[0x42] = 0x1f1f070f;
-+    s->padconf[0x43] = 0x0008081f;
-+    s->padconf[0x44] = 0x00000800;
-+}
-+
-+struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
-+                omap_clk iclk, struct omap_mpu_state_s *mpu)
-+{
-+    int iomemtype;
-+    struct omap_sysctl_s *s = (struct omap_sysctl_s *)
-+            qemu_mallocz(sizeof(struct omap_sysctl_s));
-+
-+    s->mpu = mpu;
-+    omap_sysctl_reset(s);
-+
-+    iomemtype = cpu_register_io_memory(0, omap_sysctl_readfn,
-+                    omap_sysctl_writefn, s);
-+    s->base = omap_l4_attach(ta, 0, iomemtype);
-+    omap_l4_attach(ta, 0, iomemtype);
-+
-+    return s;
-+}
-+
-+/* SDRAM Controller Subsystem */
-+struct omap_sdrc_s {
-+    target_phys_addr_t base;
-+
-+    uint8_t config;
-+};
-+
-+static void omap_sdrc_reset(struct omap_sdrc_s *s)
-+{
-+    s->config = 0x10;
-+}
-+
-+static uint32_t omap_sdrc_read(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
-+    int offset = addr - s->base;
-+
-+    switch (offset) {
-+    case 0x00:	/* SDRC_REVISION */
-+        return 0x20;
-+
-+    case 0x10:	/* SDRC_SYSCONFIG */
-+        return s->config;
-+
-+    case 0x14:	/* SDRC_SYSSTATUS */
-+        return 1;						/* RESETDONE */
-+
-+    case 0x40:	/* SDRC_CS_CFG */
-+    case 0x44:	/* SDRC_SHARING */
-+    case 0x48:	/* SDRC_ERR_ADDR */
-+    case 0x4c:	/* SDRC_ERR_TYPE */
-+    case 0x60:	/* SDRC_DLLA_SCTRL */
-+    case 0x64:	/* SDRC_DLLA_STATUS */
-+    case 0x68:	/* SDRC_DLLB_CTRL */
-+    case 0x6c:	/* SDRC_DLLB_STATUS */
-+    case 0x70:	/* SDRC_POWER */
-+    case 0x80:	/* SDRC_MCFG_0 */
-+    case 0x84:	/* SDRC_MR_0 */
-+    case 0x88:	/* SDRC_EMR1_0 */
-+    case 0x8c:	/* SDRC_EMR2_0 */
-+    case 0x90:	/* SDRC_EMR3_0 */
-+    case 0x94:	/* SDRC_DCDL1_CTRL */
-+    case 0x98:	/* SDRC_DCDL2_CTRL */
-+    case 0x9c:	/* SDRC_ACTIM_CTRLA_0 */
-+    case 0xa0:	/* SDRC_ACTIM_CTRLB_0 */
-+    case 0xa4:	/* SDRC_RFR_CTRL_0 */
-+    case 0xa8:	/* SDRC_MANUAL_0 */
-+    case 0xb0:	/* SDRC_MCFG_1 */
-+    case 0xb4:	/* SDRC_MR_1 */
-+    case 0xb8:	/* SDRC_EMR1_1 */
-+    case 0xbc:	/* SDRC_EMR2_1 */
-+    case 0xc0:	/* SDRC_EMR3_1 */
-+    case 0xc4:	/* SDRC_ACTIM_CTRLA_1 */
-+    case 0xc8:	/* SDRC_ACTIM_CTRLB_1 */
-+    case 0xd4:	/* SDRC_RFR_CTRL_1 */
-+    case 0xd8:	/* SDRC_MANUAL_1 */
-+        return 0x00;
-+    }
-+
-+    OMAP_BAD_REG(addr);
-+    return 0;
-+}
-+
-+static void omap_sdrc_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
-+    int offset = addr - s->base;
-+
-+    switch (offset) {
-+    case 0x00:	/* SDRC_REVISION */
-+    case 0x14:	/* SDRC_SYSSTATUS */
-+    case 0x48:	/* SDRC_ERR_ADDR */
-+    case 0x64:	/* SDRC_DLLA_STATUS */
-+    case 0x6c:	/* SDRC_DLLB_STATUS */
-+        OMAP_RO_REG(addr);
-+        return;
-+
-+    case 0x10:	/* SDRC_SYSCONFIG */
-+        if ((value >> 3) != 0x2)
-+            fprintf(stderr, "%s: bad SDRAM idle mode %i\n",
-+                            __FUNCTION__, value >> 3);
-+        if (value & 2)
-+            omap_sdrc_reset(s);
-+        s->config = value & 0x18;
-+        break;
-+
-+    case 0x40:	/* SDRC_CS_CFG */
-+    case 0x44:	/* SDRC_SHARING */
-+    case 0x4c:	/* SDRC_ERR_TYPE */
-+    case 0x60:	/* SDRC_DLLA_SCTRL */
-+    case 0x68:	/* SDRC_DLLB_CTRL */
-+    case 0x70:	/* SDRC_POWER */
-+    case 0x80:	/* SDRC_MCFG_0 */
-+    case 0x84:	/* SDRC_MR_0 */
-+    case 0x88:	/* SDRC_EMR1_0 */
-+    case 0x8c:	/* SDRC_EMR2_0 */
-+    case 0x90:	/* SDRC_EMR3_0 */
-+    case 0x94:	/* SDRC_DCDL1_CTRL */
-+    case 0x98:	/* SDRC_DCDL2_CTRL */
-+    case 0x9c:	/* SDRC_ACTIM_CTRLA_0 */
-+    case 0xa0:	/* SDRC_ACTIM_CTRLB_0 */
-+    case 0xa4:	/* SDRC_RFR_CTRL_0 */
-+    case 0xa8:	/* SDRC_MANUAL_0 */
-+    case 0xb0:	/* SDRC_MCFG_1 */
-+    case 0xb4:	/* SDRC_MR_1 */
-+    case 0xb8:	/* SDRC_EMR1_1 */
-+    case 0xbc:	/* SDRC_EMR2_1 */
-+    case 0xc0:	/* SDRC_EMR3_1 */
-+    case 0xc4:	/* SDRC_ACTIM_CTRLA_1 */
-+    case 0xc8:	/* SDRC_ACTIM_CTRLB_1 */
-+    case 0xd4:	/* SDRC_RFR_CTRL_1 */
-+    case 0xd8:	/* SDRC_MANUAL_1 */
-+        break;
-+
-+    default:
-+        OMAP_BAD_REG(addr);
-+        return;
-+    }
-+}
-+
-+static CPUReadMemoryFunc *omap_sdrc_readfn[] = {
-+    omap_badwidth_read32,
-+    omap_badwidth_read32,
-+    omap_sdrc_read,
-+};
-+
-+static CPUWriteMemoryFunc *omap_sdrc_writefn[] = {
-+    omap_badwidth_write32,
-+    omap_badwidth_write32,
-+    omap_sdrc_write,
-+};
-+
-+struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base)
-+{
-+    int iomemtype;
-+    struct omap_sdrc_s *s = (struct omap_sdrc_s *)
-+            qemu_mallocz(sizeof(struct omap_sdrc_s));
-+
-+    s->base = base;
-+    omap_sdrc_reset(s);
-+
-+    iomemtype = cpu_register_io_memory(0, omap_sdrc_readfn,
-+                    omap_sdrc_writefn, s);
-+    cpu_register_physical_memory(s->base, 0x1000, iomemtype);
-+
-+    return s;
-+}
-+
-+/* General-Purpose Memory Controller */
-+struct omap_gpmc_s {
-+    target_phys_addr_t base;
-+    qemu_irq irq;
-+
-+    uint8_t sysconfig;
-+    uint16_t irqst;
-+    uint16_t irqen;
-+    uint16_t timeout;
-+    uint16_t config;
-+    uint32_t prefconfig[2];
-+    int prefcontrol;
-+    int preffifo;
-+    int prefcount;
-+    struct omap_gpmc_cs_file_s {
-+        uint32_t config[7];
-+        target_phys_addr_t base;
-+        size_t size;
-+        int iomemtype;
-+        void (*base_update)(void *opaque, target_phys_addr_t new);
-+        void (*unmap)(void *opaque);
-+        void *opaque;
-+    } cs_file[8];
-+    int ecc_cs;
-+    int ecc_ptr;
-+    uint32_t ecc_cfg;
-+    struct ecc_state_s ecc[9];
-+};
-+
-+static void omap_gpmc_int_update(struct omap_gpmc_s *s)
-+{
-+    qemu_set_irq(s->irq, s->irqen & s->irqst);
-+}
-+
-+static void omap_gpmc_cs_map(struct omap_gpmc_cs_file_s *f, int base, int mask)
-+{
-+    /* TODO: check for overlapping regions and report access errors */
-+    if ((mask != 0x8 && mask != 0xc && mask != 0xe && mask != 0xf) ||
-+                    (base < 0 || base >= 0x40) ||
-+                    (base & 0x0f & ~mask)) {
-+        fprintf(stderr, "%s: wrong cs address mapping/decoding!\n",
-+                        __FUNCTION__);
-+        return;
-+    }
-+
-+    if (!f->opaque)
-+        return;
-+
-+    f->base = base << 24;
-+    f->size = (0x0fffffff & ~(mask << 24)) + 1;
-+    /* TODO: rather than setting the size of the mapping (which should be
-+     * constant), the mask should cause wrapping of the address space, so
-+     * that the same memory becomes accessible at every <i>size</i> bytes
-+     * starting from <i>base</i>.  */
-+    if (f->iomemtype)
-+        cpu_register_physical_memory(f->base, f->size, f->iomemtype);
-+
-+    if (f->base_update)
-+        f->base_update(f->opaque, f->base);
-+}
-+
-+static void omap_gpmc_cs_unmap(struct omap_gpmc_cs_file_s *f)
-+{
-+    if (f->size) {
-+        if (f->unmap)
-+            f->unmap(f->opaque);
-+        if (f->iomemtype)
-+            cpu_register_physical_memory(f->base, f->size, IO_MEM_UNASSIGNED);
-+        f->base = 0;
-+        f->size = 0;
-+    }
-+}
-+
-+static void omap_gpmc_reset(struct omap_gpmc_s *s)
-+{
-+    int i;
-+
-+    s->sysconfig = 0;
-+    s->irqst = 0;
-+    s->irqen = 0;
-+    omap_gpmc_int_update(s);
-+    s->timeout = 0;
-+    s->config = 0xa00;
-+    s->prefconfig[0] = 0x00004000;
-+    s->prefconfig[1] = 0x00000000;
-+    s->prefcontrol = 0;
-+    s->preffifo = 0;
-+    s->prefcount = 0;
-+    for (i = 0; i < 8; i ++) {
-+        if (s->cs_file[i].config[6] & (1 << 6))			/* CSVALID */
-+            omap_gpmc_cs_unmap(s->cs_file + i);
-+        s->cs_file[i].config[0] = i ? 1 << 12 : 0;
-+        s->cs_file[i].config[1] = 0x101001;
-+        s->cs_file[i].config[2] = 0x020201;
-+        s->cs_file[i].config[3] = 0x10031003;
-+        s->cs_file[i].config[4] = 0x10f1111;
-+        s->cs_file[i].config[5] = 0;
-+        s->cs_file[i].config[6] = 0xf00 | (i ? 0 : 1 << 6);
-+        if (s->cs_file[i].config[6] & (1 << 6))			/* CSVALID */
-+            omap_gpmc_cs_map(&s->cs_file[i],
-+                            s->cs_file[i].config[6] & 0x1f,	/* MASKADDR */
-+                        (s->cs_file[i].config[6] >> 8 & 0xf));	/* BASEADDR */
-+    }
-+    omap_gpmc_cs_map(s->cs_file, 0, 0xf);
-+    s->ecc_cs = 0;
-+    s->ecc_ptr = 0;
-+    s->ecc_cfg = 0x3fcff000;
-+    for (i = 0; i < 9; i ++)
-+        ecc_reset(&s->ecc[i]);
-+}
-+
-+static uint32_t omap_gpmc_read(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
-+    int offset = addr - s->base;
-+    int cs;
-+    struct omap_gpmc_cs_file_s *f;
-+
-+    switch (offset) {
-+    case 0x000:	/* GPMC_REVISION */
-+        return 0x20;
-+
-+    case 0x010:	/* GPMC_SYSCONFIG */
-+        return s->sysconfig;
-+
-+    case 0x014:	/* GPMC_SYSSTATUS */
-+        return 1;						/* RESETDONE */
-+
-+    case 0x018:	/* GPMC_IRQSTATUS */
-+        return s->irqst;
-+
-+    case 0x01c:	/* GPMC_IRQENABLE */
-+        return s->irqen;
-+
-+    case 0x040:	/* GPMC_TIMEOUT_CONTROL */
-+        return s->timeout;
-+
-+    case 0x044:	/* GPMC_ERR_ADDRESS */
-+    case 0x048:	/* GPMC_ERR_TYPE */
-+        return 0;
-+
-+    case 0x050:	/* GPMC_CONFIG */
-+        return s->config;
-+
-+    case 0x054:	/* GPMC_STATUS */
-+        return 0x001;
-+
-+    case 0x060 ... 0x1d4:
-+        cs = (offset - 0x060) / 0x30;
-+        offset -= cs * 0x30;
-+        f = s->cs_file + cs;
-+        switch (offset - cs * 0x30) {
-+            case 0x60:	/* GPMC_CONFIG1 */
-+                return f->config[0];
-+            case 0x64:	/* GPMC_CONFIG2 */
-+                return f->config[1];
-+            case 0x68:	/* GPMC_CONFIG3 */
-+                return f->config[2];
-+            case 0x6c:	/* GPMC_CONFIG4 */
-+                return f->config[3];
-+            case 0x70:	/* GPMC_CONFIG5 */
-+                return f->config[4];
-+            case 0x74:	/* GPMC_CONFIG6 */
-+                return f->config[5];
-+            case 0x78:	/* GPMC_CONFIG7 */
-+                return f->config[6];
-+            case 0x84:	/* GPMC_NAND_DATA */
-+                return 0;
-+        }
-+        break;
-+
-+    case 0x1e0:	/* GPMC_PREFETCH_CONFIG1 */
-+        return s->prefconfig[0];
-+    case 0x1e4:	/* GPMC_PREFETCH_CONFIG2 */
-+        return s->prefconfig[1];
-+    case 0x1ec:	/* GPMC_PREFETCH_CONTROL */
-+        return s->prefcontrol;
-+    case 0x1f0:	/* GPMC_PREFETCH_STATUS */
-+        return (s->preffifo << 24) |
-+                ((s->preffifo >
-+                  ((s->prefconfig[0] >> 8) & 0x7f) ? 1 : 0) << 16) |
-+                s->prefcount;
-+
-+    case 0x1f4:	/* GPMC_ECC_CONFIG */
-+        return s->ecc_cs;
-+    case 0x1f8:	/* GPMC_ECC_CONTROL */
-+        return s->ecc_ptr;
-+    case 0x1fc:	/* GPMC_ECC_SIZE_CONFIG */
-+        return s->ecc_cfg;
-+    case 0x200 ... 0x220:	/* GPMC_ECC_RESULT */
-+        cs = (offset & 0x1f) >> 2;
-+        /* TODO: check correctness */
-+        return
-+                ((s->ecc[cs].cp    &  0x07) <<  0) |
-+                ((s->ecc[cs].cp    &  0x38) << 13) |
-+                ((s->ecc[cs].lp[0] & 0x1ff) <<  3) |
-+                ((s->ecc[cs].lp[1] & 0x1ff) << 19);
-+
-+    case 0x230:	/* GPMC_TESTMODE_CTRL */
-+        return 0;
-+    case 0x234:	/* GPMC_PSA_LSB */
-+    case 0x238:	/* GPMC_PSA_MSB */
-+        return 0x00000000;
-+    }
-+
-+    OMAP_BAD_REG(addr);
-+    return 0;
-+}
-+
-+static void omap_gpmc_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
-+    int offset = addr - s->base;
-+    int cs;
-+    struct omap_gpmc_cs_file_s *f;
-+
-+    switch (offset) {
-+    case 0x000:	/* GPMC_REVISION */
-+    case 0x014:	/* GPMC_SYSSTATUS */
-+    case 0x054:	/* GPMC_STATUS */
-+    case 0x1f0:	/* GPMC_PREFETCH_STATUS */
-+    case 0x200 ... 0x220:	/* GPMC_ECC_RESULT */
-+    case 0x234:	/* GPMC_PSA_LSB */
-+    case 0x238:	/* GPMC_PSA_MSB */
-+        OMAP_RO_REG(addr);
-+        break;
-+
-+    case 0x010:	/* GPMC_SYSCONFIG */
-+        if ((value >> 3) == 0x3)
-+            fprintf(stderr, "%s: bad SDRAM idle mode %i\n",
-+                            __FUNCTION__, value >> 3);
-+        if (value & 2)
-+            omap_gpmc_reset(s);
-+        s->sysconfig = value & 0x19;
-+        break;
-+
-+    case 0x018:	/* GPMC_IRQSTATUS */
-+        s->irqen = ~value;
-+        omap_gpmc_int_update(s);
-+        break;
-+
-+    case 0x01c:	/* GPMC_IRQENABLE */
-+        s->irqen = value & 0xf03;
-+        omap_gpmc_int_update(s);
-+        break;
-+
-+    case 0x040:	/* GPMC_TIMEOUT_CONTROL */
-+        s->timeout = value & 0x1ff1;
-+        break;
-+
-+    case 0x044:	/* GPMC_ERR_ADDRESS */
-+    case 0x048:	/* GPMC_ERR_TYPE */
-+        break;
-+
-+    case 0x050:	/* GPMC_CONFIG */
-+        s->config = value & 0xf13;
-+        break;
-+
-+    case 0x060 ... 0x1d4:
-+        cs = (offset - 0x060) / 0x30;
-+        offset -= cs * 0x30;
-+        f = s->cs_file + cs;
-+        switch (offset - cs * 0x30) {
-+            case 0x60:	/* GPMC_CONFIG1 */
-+                f->config[0] = value & 0xffef3e13;
-+                break;
-+            case 0x64:	/* GPMC_CONFIG2 */
-+                f->config[1] = value & 0x001f1f8f;
-+                break;
-+            case 0x68:	/* GPMC_CONFIG3 */
-+                f->config[2] = value & 0x001f1f8f;
-+                break;
-+            case 0x6c:	/* GPMC_CONFIG4 */
-+                f->config[3] = value & 0x1f8f1f8f;
-+                break;
-+            case 0x70:	/* GPMC_CONFIG5 */
-+                f->config[4] = value & 0x0f1f1f1f;
-+                break;
-+            case 0x74:	/* GPMC_CONFIG6 */
-+                f->config[5] = value & 0x00000fcf;
-+                break;
-+            case 0x78:	/* GPMC_CONFIG7 */
-+                if ((f->config[6] ^ value) & 0xf7f) {
-+                    if (f->config[6] & (1 << 6))		/* CSVALID */
-+                        omap_gpmc_cs_unmap(f);
-+                    if (value & (1 << 6))			/* CSVALID */
-+                        omap_gpmc_cs_map(f, value & 0x1f,	/* MASKADDR */
-+                                        (value >> 8 & 0xf));	/* BASEADDR */
-+                }
-+                f->config[6] = value & 0x00000f7f;
-+                break;
-+            case 0x7c:	/* GPMC_NAND_COMMAND */
-+            case 0x80:	/* GPMC_NAND_ADDRESS */
-+            case 0x84:	/* GPMC_NAND_DATA */
-+                break;
-+
-+            default:
-+                goto bad_reg;
-+        }
-+        break;
-+
-+    case 0x1e0:	/* GPMC_PREFETCH_CONFIG1 */
-+        s->prefconfig[0] = value & 0x7f8f7fbf;
-+        /* TODO: update interrupts, fifos, dmas */
-+        break;
-+
-+    case 0x1e4:	/* GPMC_PREFETCH_CONFIG2 */
-+        s->prefconfig[1] = value & 0x3fff;
-+        break;
-+
-+    case 0x1ec:	/* GPMC_PREFETCH_CONTROL */
-+        s->prefcontrol = value & 1;
-+        if (s->prefcontrol) {
-+            if (s->prefconfig[0] & 1)
-+                s->preffifo = 0x40;
-+            else
-+                s->preffifo = 0x00;
-+        }
-+        /* TODO: start */
-+        break;
-+
-+    case 0x1f4:	/* GPMC_ECC_CONFIG */
-+        s->ecc_cs = 0x8f;
-+        break;
-+    case 0x1f8:	/* GPMC_ECC_CONTROL */
-+        if (value & (1 << 8))
-+            for (cs = 0; cs < 9; cs ++)
-+                ecc_reset(&s->ecc[cs]);
-+        s->ecc_ptr = value & 0xf;
-+        if (s->ecc_ptr == 0 || s->ecc_ptr > 9) {
-+            s->ecc_ptr = 0;
-+            s->ecc_cs &= ~1;
-+        }
-+        break;
-+    case 0x1fc:	/* GPMC_ECC_SIZE_CONFIG */
-+        s->ecc_cfg = value & 0x3fcff1ff;
-+        break;
-+    case 0x230:	/* GPMC_TESTMODE_CTRL */
-+        if (value & 7)
-+            fprintf(stderr, "%s: test mode enable attempt\n", __FUNCTION__);
-+        break;
-+
-+    default:
-+    bad_reg:
-+        OMAP_BAD_REG(addr);
-+        return;
-+    }
-+}
-+
-+static CPUReadMemoryFunc *omap_gpmc_readfn[] = {
-+    omap_badwidth_read32,	/* TODO */
-+    omap_badwidth_read32,	/* TODO */
-+    omap_gpmc_read,
-+};
-+
-+static CPUWriteMemoryFunc *omap_gpmc_writefn[] = {
-+    omap_badwidth_write32,	/* TODO */
-+    omap_badwidth_write32,	/* TODO */
-+    omap_gpmc_write,
-+};
-+
-+struct omap_gpmc_s *omap_gpmc_init(target_phys_addr_t base, qemu_irq irq)
-+{
-+    int iomemtype;
-+    struct omap_gpmc_s *s = (struct omap_gpmc_s *)
-+            qemu_mallocz(sizeof(struct omap_gpmc_s));
-+
-+    s->base = base;
-+    omap_gpmc_reset(s);
-+
-+    iomemtype = cpu_register_io_memory(0, omap_gpmc_readfn,
-+                    omap_gpmc_writefn, s);
-+    cpu_register_physical_memory(s->base, 0x1000, iomemtype);
-+
-+    return s;
-+}
-+
-+void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, int iomemtype,
-+                void (*base_upd)(void *opaque, target_phys_addr_t new),
-+                void (*unmap)(void *opaque), void *opaque)
-+{
-+    struct omap_gpmc_cs_file_s *f;
-+
-+    if (cs < 0 || cs >= 8) {
-+        fprintf(stderr, "%s: bad chip-select %i\n", __FUNCTION__, cs);
-+        exit(-1);
-+    }
-+    f = &s->cs_file[cs];
-+
-+    f->iomemtype = iomemtype;
-+    f->base_update = base_upd;
-+    f->unmap = unmap;
-+    f->opaque = opaque;
-+
-+    if (f->config[6] & (1 << 6))				/* CSVALID */
-+        omap_gpmc_cs_map(f, f->config[6] & 0x1f,		/* MASKADDR */
-+                        (f->config[6] >> 8 & 0xf));		/* BASEADDR */
-+}
-+
-+/* General chip reset */
-+static void omap2_mpu_reset(void *opaque)
-+{
-+    struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
-+
-+    omap_inth_reset(mpu->ih[0]);
-+    omap_dma_reset(mpu->dma);
-+    omap_prcm_reset(mpu->prcm);
-+    omap_sysctl_reset(mpu->sysc);
-+    omap_gp_timer_reset(mpu->gptimer[0]);
-+    omap_gp_timer_reset(mpu->gptimer[1]);
-+    omap_gp_timer_reset(mpu->gptimer[2]);
-+    omap_gp_timer_reset(mpu->gptimer[3]);
-+    omap_gp_timer_reset(mpu->gptimer[4]);
-+    omap_gp_timer_reset(mpu->gptimer[5]);
-+    omap_gp_timer_reset(mpu->gptimer[6]);
-+    omap_gp_timer_reset(mpu->gptimer[7]);
-+    omap_gp_timer_reset(mpu->gptimer[8]);
-+    omap_gp_timer_reset(mpu->gptimer[9]);
-+    omap_gp_timer_reset(mpu->gptimer[10]);
-+    omap_gp_timer_reset(mpu->gptimer[11]);
-+    omap_synctimer_reset(&mpu->synctimer);
-+    omap_sdrc_reset(mpu->sdrc);
-+    omap_gpmc_reset(mpu->gpmc);
-+    omap_dss_reset(mpu->dss);
-+#if 0
-+    omap_wd_timer_reset(mpu->wdt);
-+    omap_ulpd_pm_reset(mpu);
-+    omap_pin_cfg_reset(mpu);
-+    omap_mpui_reset(mpu);
-+    omap_tipb_bridge_reset(mpu->private_tipb);
-+    omap_tipb_bridge_reset(mpu->public_tipb);
-+    omap_dpll_reset(&mpu->dpll[0]);
-+    omap_dpll_reset(&mpu->dpll[1]);
-+    omap_dpll_reset(&mpu->dpll[2]);
-+#endif
-+    omap_uart_reset(mpu->uart[0]);
-+    omap_uart_reset(mpu->uart[1]);
-+    omap_uart_reset(mpu->uart[2]);
-+    omap_mmc_reset(mpu->mmc);
-+    omap_gpif_reset(mpu->gpif);
-+    omap_mcspi_reset(mpu->mcspi[0]);
-+    omap_mcspi_reset(mpu->mcspi[1]);
-+#if 0
-+    omap_pwl_reset(mpu);
-+    omap_pwt_reset(mpu);
-+#endif
-+    omap_i2c_reset(mpu->i2c[0]);
-+    omap_i2c_reset(mpu->i2c[1]);
-+#if 0
-+    omap_rtc_reset(mpu->rtc);
-+    omap_mcbsp_reset(mpu->mcbsp1);
-+    omap_mcbsp_reset(mpu->mcbsp2);
-+    omap_mcbsp_reset(mpu->mcbsp3);
-+    omap_lpg_reset(mpu->led[0]);
-+    omap_lpg_reset(mpu->led[1]);
-+    omap_clkm_reset(mpu);
-+#endif
-+    cpu_reset(mpu->env);
-+}
-+
-+static int omap2_validate_addr(struct omap_mpu_state_s *s,
-+                target_phys_addr_t addr)
-+{
-+    return 1;
-+}
-+
-+static const struct dma_irq_map omap2_dma_irq_map[] = {
-+    { 0, OMAP_INT_24XX_SDMA_IRQ0 },
-+    { 0, OMAP_INT_24XX_SDMA_IRQ1 },
-+    { 0, OMAP_INT_24XX_SDMA_IRQ2 },
-+    { 0, OMAP_INT_24XX_SDMA_IRQ3 },
-+};
-+
-+struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
-+                DisplayState *ds, const char *core)
-+{
-+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
-+            qemu_mallocz(sizeof(struct omap_mpu_state_s));
-+    ram_addr_t sram_base, q3_base;
-+    qemu_irq *cpu_irq;
-+    qemu_irq dma_irqs[4];
-+    omap_clk gpio_clks[4];
-+    int sdindex;
-+    int i;
-+
-+    /* Core */
-+    s->mpu_model = omap2420;
-+    s->env = cpu_init(core ?: "arm1136-r2");
-+    if (!s->env) {
-+        fprintf(stderr, "Unable to find CPU definition\n");
-+        exit(1);
-+    }
-+    s->sdram_size = sdram_size;
-+    s->sram_size = OMAP242X_SRAM_SIZE;
-+
-+    s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
-+
-+    /* Clocks */
-+    omap_clk_init(s);
-+
-+    /* Memory-mapped stuff */
-+    cpu_register_physical_memory(OMAP2_Q2_BASE, s->sdram_size,
-+                    (q3_base = qemu_ram_alloc(s->sdram_size)) | IO_MEM_RAM);
-+    cpu_register_physical_memory(OMAP2_SRAM_BASE, s->sram_size,
-+                    (sram_base = qemu_ram_alloc(s->sram_size)) | IO_MEM_RAM);
-+
-+    s->l4 = omap_l4_init(OMAP2_L4_BASE, 54);
-+
-+    /* Actually mapped at any 2K boundary in the ARM11 private-peripheral if */
-+    cpu_irq = arm_pic_init_cpu(s->env);
-+    s->ih[0] = omap2_inth_init(0x480fe000, 0x1000, 3, &s->irq[0],
-+                    cpu_irq[ARM_PIC_CPU_IRQ], cpu_irq[ARM_PIC_CPU_FIQ],
-+                    omap_findclk(s, "mpu_intc_fclk"),
-+                    omap_findclk(s, "mpu_intc_iclk"));
-+
-+    s->prcm = omap_prcm_init(omap_l4tao(s->l4, 3),
-+                    s->irq[0][OMAP_INT_24XX_PRCM_MPU_IRQ], NULL, NULL, s);
-+
-+    s->sysc = omap_sysctl_init(omap_l4tao(s->l4, 1),
-+                    omap_findclk(s, "omapctrl_iclk"), s);
-+
-+    for (i = 0; i < 4; i ++)
-+        dma_irqs[i] =
-+                s->irq[omap2_dma_irq_map[i].ih][omap2_dma_irq_map[i].intr];
-+    s->dma = omap_dma4_init(0x48056000, dma_irqs, s, 256, 32,
-+                    omap_findclk(s, "sdma_iclk"),
-+                    omap_findclk(s, "sdma_fclk"));
-+    s->port->addr_valid = omap2_validate_addr;
-+
-+    s->uart[0] = omap2_uart_init(omap_l4ta(s->l4, 19),
-+                    s->irq[0][OMAP_INT_24XX_UART1_IRQ],
-+                    omap_findclk(s, "uart1_fclk"),
-+                    omap_findclk(s, "uart1_iclk"),
-+                    s->drq[OMAP24XX_DMA_UART1_TX],
-+                    s->drq[OMAP24XX_DMA_UART1_RX], serial_hds[0]);
-+    s->uart[1] = omap2_uart_init(omap_l4ta(s->l4, 20),
-+                    s->irq[0][OMAP_INT_24XX_UART2_IRQ],
-+                    omap_findclk(s, "uart2_fclk"),
-+                    omap_findclk(s, "uart2_iclk"),
-+                    s->drq[OMAP24XX_DMA_UART2_TX],
-+                    s->drq[OMAP24XX_DMA_UART2_RX],
-+                    serial_hds[0] ? serial_hds[1] : 0);
-+    s->uart[2] = omap2_uart_init(omap_l4ta(s->l4, 21),
-+                    s->irq[0][OMAP_INT_24XX_UART3_IRQ],
-+                    omap_findclk(s, "uart3_fclk"),
-+                    omap_findclk(s, "uart3_iclk"),
-+                    s->drq[OMAP24XX_DMA_UART3_TX],
-+                    s->drq[OMAP24XX_DMA_UART3_RX],
-+                    serial_hds[0] && serial_hds[1] ? serial_hds[2] : 0);
-+
-+    s->gptimer[0] = omap_gp_timer_init(omap_l4ta(s->l4, 7),
-+                    s->irq[0][OMAP_INT_24XX_GPTIMER1],
-+                    omap_findclk(s, "wu_gpt1_clk"),
-+                    omap_findclk(s, "wu_l4_iclk"));
-+    s->gptimer[1] = omap_gp_timer_init(omap_l4ta(s->l4, 8),
-+                    s->irq[0][OMAP_INT_24XX_GPTIMER2],
-+                    omap_findclk(s, "core_gpt2_clk"),
-+                    omap_findclk(s, "core_l4_iclk"));
-+    s->gptimer[2] = omap_gp_timer_init(omap_l4ta(s->l4, 22),
-+                    s->irq[0][OMAP_INT_24XX_GPTIMER3],
-+                    omap_findclk(s, "core_gpt3_clk"),
-+                    omap_findclk(s, "core_l4_iclk"));
-+    s->gptimer[3] = omap_gp_timer_init(omap_l4ta(s->l4, 23),
-+                    s->irq[0][OMAP_INT_24XX_GPTIMER4],
-+                    omap_findclk(s, "core_gpt4_clk"),
-+                    omap_findclk(s, "core_l4_iclk"));
-+    s->gptimer[4] = omap_gp_timer_init(omap_l4ta(s->l4, 24),
-+                    s->irq[0][OMAP_INT_24XX_GPTIMER5],
-+                    omap_findclk(s, "core_gpt5_clk"),
-+                    omap_findclk(s, "core_l4_iclk"));
-+    s->gptimer[5] = omap_gp_timer_init(omap_l4ta(s->l4, 25),
-+                    s->irq[0][OMAP_INT_24XX_GPTIMER6],
-+                    omap_findclk(s, "core_gpt6_clk"),
-+                    omap_findclk(s, "core_l4_iclk"));
-+    s->gptimer[6] = omap_gp_timer_init(omap_l4ta(s->l4, 26),
-+                    s->irq[0][OMAP_INT_24XX_GPTIMER7],
-+                    omap_findclk(s, "core_gpt7_clk"),
-+                    omap_findclk(s, "core_l4_iclk"));
-+    s->gptimer[7] = omap_gp_timer_init(omap_l4ta(s->l4, 27),
-+                    s->irq[0][OMAP_INT_24XX_GPTIMER8],
-+                    omap_findclk(s, "core_gpt8_clk"),
-+                    omap_findclk(s, "core_l4_iclk"));
-+    s->gptimer[8] = omap_gp_timer_init(omap_l4ta(s->l4, 28),
-+                    s->irq[0][OMAP_INT_24XX_GPTIMER9],
-+                    omap_findclk(s, "core_gpt9_clk"),
-+                    omap_findclk(s, "core_l4_iclk"));
-+    s->gptimer[9] = omap_gp_timer_init(omap_l4ta(s->l4, 29),
-+                    s->irq[0][OMAP_INT_24XX_GPTIMER10],
-+                    omap_findclk(s, "core_gpt10_clk"),
-+                    omap_findclk(s, "core_l4_iclk"));
-+    s->gptimer[10] = omap_gp_timer_init(omap_l4ta(s->l4, 30),
-+                    s->irq[0][OMAP_INT_24XX_GPTIMER11],
-+                    omap_findclk(s, "core_gpt11_clk"),
-+                    omap_findclk(s, "core_l4_iclk"));
-+    s->gptimer[11] = omap_gp_timer_init(omap_l4ta(s->l4, 31),
-+                    s->irq[0][OMAP_INT_24XX_GPTIMER12],
-+                    omap_findclk(s, "core_gpt12_clk"),
-+                    omap_findclk(s, "core_l4_iclk"));
-+
-+    omap_tap_init(omap_l4ta(s->l4, 2), s);
-+
-+    omap_synctimer_init(omap_l4tao(s->l4, 2), s,
-+                    omap_findclk(s, "clk32-kHz"),
-+                    omap_findclk(s, "core_l4_iclk"));
-+
-+    s->i2c[0] = omap2_i2c_init(omap_l4tao(s->l4, 5),
-+                    s->irq[0][OMAP_INT_24XX_I2C1_IRQ],
-+                    &s->drq[OMAP24XX_DMA_I2C1_TX],
-+                    omap_findclk(s, "i2c1.fclk"),
-+                    omap_findclk(s, "i2c1.iclk"));
-+    s->i2c[1] = omap2_i2c_init(omap_l4tao(s->l4, 6),
-+                    s->irq[0][OMAP_INT_24XX_I2C2_IRQ],
-+                    &s->drq[OMAP24XX_DMA_I2C2_TX],
-+                    omap_findclk(s, "i2c2.fclk"),
-+                    omap_findclk(s, "i2c2.iclk"));
-+
-+    gpio_clks[0] = omap_findclk(s, "gpio1_dbclk");
-+    gpio_clks[1] = omap_findclk(s, "gpio2_dbclk");
-+    gpio_clks[2] = omap_findclk(s, "gpio3_dbclk");
-+    gpio_clks[3] = omap_findclk(s, "gpio4_dbclk");
-+    s->gpif = omap2_gpio_init(omap_l4ta(s->l4, 3),
-+                    &s->irq[0][OMAP_INT_24XX_GPIO_BANK1],
-+                    gpio_clks, omap_findclk(s, "gpio_iclk"), 4);
-+
-+    s->sdrc = omap_sdrc_init(0x68009000);
-+    s->gpmc = omap_gpmc_init(0x6800a000, s->irq[0][OMAP_INT_24XX_GPMC_IRQ]);
-+
-+    sdindex = drive_get_index(IF_SD, 0, 0);
-+    if (sdindex == -1) {
-+        fprintf(stderr, "qemu: missing SecureDigital device\n");
-+        exit(1);
-+    }
-+    s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9), drives_table[sdindex].bdrv,
-+                    s->irq[0][OMAP_INT_24XX_MMC_IRQ],
-+                    &s->drq[OMAP24XX_DMA_MMC1_TX],
-+                    omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk"));
-+
-+    s->mcspi[0] = omap_mcspi_init(omap_l4ta(s->l4, 35), 4,
-+                    s->irq[0][OMAP_INT_24XX_MCSPI1_IRQ], 
-+                    &s->drq[OMAP24XX_DMA_SPI1_TX0],
-+                    omap_findclk(s, "spi1_fclk"),
-+                    omap_findclk(s, "spi1_iclk"));
-+    s->mcspi[1] = omap_mcspi_init(omap_l4ta(s->l4, 36), 2,
-+                    s->irq[0][OMAP_INT_24XX_MCSPI2_IRQ], 
-+                    &s->drq[OMAP24XX_DMA_SPI2_TX0],
-+                    omap_findclk(s, "spi2_fclk"),
-+                    omap_findclk(s, "spi2_iclk"));
-+
-+    s->dss = omap_dss_init(omap_l4ta(s->l4, 10), 0x68000800, ds,
-+                    /* XXX wire M_IRQ_25, D_L2_IRQ_30 and I_IRQ_13 together */
-+                    s->irq[0][OMAP_INT_24XX_DSS_IRQ], s->drq[OMAP24XX_DMA_DSS],
-+                    omap_findclk(s, "dss_clk1"), omap_findclk(s, "dss_clk2"),
-+                    omap_findclk(s, "dss_54m_clk"),
-+                    omap_findclk(s, "dss_l3_iclk"),
-+                    omap_findclk(s, "dss_l4_iclk"));
-+
-+    /* Register mappings not currenlty implemented:
-+     * SystemControlMod	48000000 - 48000fff
-+     * SystemControlL4	48001000 - 48001fff
-+     * 32kHz Timer Mod	48004000 - 48004fff
-+     * 32kHz Timer L4	48005000 - 48005fff
-+     * PRCM ModA	48008000 - 480087ff
-+     * PRCM ModB	48008800 - 48008fff
-+     * PRCM L4		48009000 - 48009fff
-+     * TEST-BCM Mod	48012000 - 48012fff
-+     * TEST-BCM L4	48013000 - 48013fff
-+     * TEST-TAP Mod	48014000 - 48014fff
-+     * TEST-TAP L4	48015000 - 48015fff
-+     * GPIO1 Mod	48018000 - 48018fff
-+     * GPIO Top		48019000 - 48019fff
-+     * GPIO2 Mod	4801a000 - 4801afff
-+     * GPIO L4		4801b000 - 4801bfff
-+     * GPIO3 Mod	4801c000 - 4801cfff
-+     * GPIO4 Mod	4801e000 - 4801efff
-+     * WDTIMER1 Mod	48020000 - 48010fff
-+     * WDTIMER Top	48021000 - 48011fff
-+     * WDTIMER2 Mod	48022000 - 48012fff
-+     * WDTIMER L4	48023000 - 48013fff
-+     * WDTIMER3 Mod	48024000 - 48014fff
-+     * WDTIMER3 L4	48025000 - 48015fff
-+     * WDTIMER4 Mod	48026000 - 48016fff
-+     * WDTIMER4 L4	48027000 - 48017fff
-+     * GPTIMER1 Mod	48028000 - 48018fff
-+     * GPTIMER1 L4	48029000 - 48019fff
-+     * GPTIMER2 Mod	4802a000 - 4801afff
-+     * GPTIMER2 L4	4802b000 - 4801bfff
-+     * L4-Config AP	48040000 - 480407ff
-+     * L4-Config IP	48040800 - 48040fff
-+     * L4-Config LA	48041000 - 48041fff
-+     * ARM11ETB Mod	48048000 - 48049fff
-+     * ARM11ETB L4	4804a000 - 4804afff
-+     * DISPLAY Top	48050000 - 480503ff
-+     * DISPLAY DISPC	48050400 - 480507ff
-+     * DISPLAY RFBI	48050800 - 48050bff
-+     * DISPLAY VENC	48050c00 - 48050fff
-+     * DISPLAY L4	48051000 - 48051fff
-+     * CAMERA Top	48052000 - 480523ff
-+     * CAMERA core	48052400 - 480527ff
-+     * CAMERA DMA	48052800 - 48052bff
-+     * CAMERA MMU	48052c00 - 48052fff
-+     * CAMERA L4	48053000 - 48053fff
-+     * SDMA Mod		48056000 - 48056fff
-+     * SDMA L4		48057000 - 48057fff
-+     * SSI Top		48058000 - 48058fff
-+     * SSI GDD		48059000 - 48059fff
-+     * SSI Port1	4805a000 - 4805afff
-+     * SSI Port2	4805b000 - 4805bfff
-+     * SSI L4		4805c000 - 4805cfff
-+     * USB Mod		4805e000 - 480fefff
-+     * USB L4		4805f000 - 480fffff
-+     * WIN_TRACER1 Mod	48060000 - 48060fff
-+     * WIN_TRACER1 L4	48061000 - 48061fff
-+     * WIN_TRACER2 Mod	48062000 - 48062fff
-+     * WIN_TRACER2 L4	48063000 - 48063fff
-+     * WIN_TRACER3 Mod	48064000 - 48064fff
-+     * WIN_TRACER3 L4	48065000 - 48065fff
-+     * WIN_TRACER4 Top	48066000 - 480660ff
-+     * WIN_TRACER4 ETT	48066100 - 480661ff
-+     * WIN_TRACER4 WT	48066200 - 480662ff
-+     * WIN_TRACER4 L4	48067000 - 48067fff
-+     * XTI Mod		48068000 - 48068fff
-+     * XTI L4		48069000 - 48069fff
-+     * UART1 Mod	4806a000 - 4806afff
-+     * UART1 L4		4806b000 - 4806bfff
-+     * UART2 Mod	4806c000 - 4806cfff
-+     * UART2 L4		4806d000 - 4806dfff
-+     * UART3 Mod	4806e000 - 4806efff
-+     * UART3 L4		4806f000 - 4806ffff
-+     * I2C1 Mod		48070000 - 48070fff
-+     * I2C1 L4		48071000 - 48071fff
-+     * I2C2 Mod		48072000 - 48072fff
-+     * I2C2 L4		48073000 - 48073fff
-+     * McBSP1 Mod	48074000 - 48074fff
-+     * McBSP1 L4	48075000 - 48075fff
-+     * McBSP2 Mod	48076000 - 48076fff
-+     * McBSP2 L4	48077000 - 48077fff
-+     * GPTIMER3 Mod	48078000 - 48078fff
-+     * GPTIMER3 L4	48079000 - 48079fff
-+     * GPTIMER4 Mod	4807a000 - 4807afff
-+     * GPTIMER4 L4	4807b000 - 4807bfff
-+     * GPTIMER5 Mod	4807c000 - 4807cfff
-+     * GPTIMER5 L4	4807d000 - 4807dfff
-+     * GPTIMER6 Mod	4807e000 - 4807efff
-+     * GPTIMER6 L4	4807f000 - 4807ffff
-+     * GPTIMER7 Mod	48080000 - 48080fff
-+     * GPTIMER7 L4	48081000 - 48081fff
-+     * GPTIMER8 Mod	48082000 - 48082fff
-+     * GPTIMER8 L4	48083000 - 48083fff
-+     * GPTIMER9 Mod	48084000 - 48084fff
-+     * GPTIMER9 L4	48085000 - 48085fff
-+     * GPTIMER10 Mod	48086000 - 48086fff
-+     * GPTIMER10 L4	48087000 - 48087fff
-+     * GPTIMER11 Mod	48088000 - 48088fff
-+     * GPTIMER11 L4	48089000 - 48089fff
-+     * GPTIMER12 Mod	4808a000 - 4808afff
-+     * GPTIMER12 L4	4808b000 - 4808bfff
-+     * EAC Mod		48090000 - 48090fff
-+     * EAC L4		48091000 - 48091fff
-+     * FAC Mod		48092000 - 48092fff
-+     * FAC L4		48093000 - 48093fff
-+     * MAILBOX Mod	48094000 - 48094fff
-+     * MAILBOX L4	48095000 - 48095fff
-+     * SPI1 Mod		48098000 - 48098fff
-+     * SPI1 L4		48099000 - 48099fff
-+     * SPI2 Mod		4809a000 - 4809afff
-+     * SPI2 L4		4809b000 - 4809bfff
-+     * MMC/SDIO Mod	4809c000 - 4809cfff
-+     * MMC/SDIO L4	4809d000 - 4809dfff
-+     * MS_PRO Mod	4809e000 - 4809efff
-+     * MS_PRO L4	4809f000 - 4809ffff
-+     * RNG Mod		480a0000 - 480a0fff
-+     * RNG L4		480a1000 - 480a1fff
-+     * DES3DES Mod	480a2000 - 480a2fff
-+     * DES3DES L4	480a3000 - 480a3fff
-+     * SHA1MD5 Mod	480a4000 - 480a4fff
-+     * SHA1MD5 L4	480a5000 - 480a5fff
-+     * AES Mod		480a6000 - 480a6fff
-+     * AES L4		480a7000 - 480a7fff
-+     * PKA Mod		480a8000 - 480a9fff
-+     * PKA L4		480aa000 - 480aafff
-+     * MG Mod		480b0000 - 480b0fff
-+     * MG L4		480b1000 - 480b1fff
-+     * HDQ/1-wire Mod	480b2000 - 480b2fff
-+     * HDQ/1-wire L4	480b3000 - 480b3fff
-+     * MPU interrupt	480fe000 - 480fefff
-+     * IVA RAM		5c000000 - 5c01ffff
-+     * IVA ROM		5c020000 - 5c027fff
-+     * IMG_BUF_A	5c040000 - 5c040fff
-+     * IMG_BUF_B	5c042000 - 5c042fff
-+     * VLCDS		5c048000 - 5c0487ff
-+     * IMX_COEF		5c049000 - 5c04afff
-+     * IMX_CMD		5c051000 - 5c051fff
-+     * VLCDQ		5c053000 - 5c0533ff
-+     * VLCDH		5c054000 - 5c054fff
-+     * SEQ_CMD		5c055000 - 5c055fff
-+     * IMX_REG		5c056000 - 5c0560ff
-+     * VLCD_REG		5c056100 - 5c0561ff
-+     * SEQ_REG		5c056200 - 5c0562ff
-+     * IMG_BUF_REG	5c056300 - 5c0563ff
-+     * SEQIRQ_REG	5c056400 - 5c0564ff
-+     * OCP_REG		5c060000 - 5c060fff
-+     * SYSC_REG		5c070000 - 5c070fff
-+     * MMU_REG		5d000000 - 5d000fff
-+     * sDMA R		68000400 - 680005ff
-+     * sDMA W		68000600 - 680007ff
-+     * Display Control	68000800 - 680009ff
-+     * DSP subsystem	68000a00 - 68000bff
-+     * MPU subsystem	68000c00 - 68000dff
-+     * IVA subsystem	68001000 - 680011ff
-+     * USB		68001200 - 680013ff
-+     * Camera		68001400 - 680015ff
-+     * VLYNQ (firewall)	68001800 - 68001bff
-+     * VLYNQ		68001e00 - 68001fff
-+     * SSI		68002000 - 680021ff
-+     * L4		68002400 - 680025ff
-+     * DSP (firewall)	68002800 - 68002bff
-+     * DSP subsystem	68002e00 - 68002fff
-+     * IVA (firewall)	68003000 - 680033ff
-+     * IVA		68003600 - 680037ff
-+     * GFX		68003a00 - 68003bff
-+     * CMDWR emulation	68003c00 - 68003dff
-+     * SMS		68004000 - 680041ff
-+     * OCM		68004200 - 680043ff
-+     * GPMC		68004400 - 680045ff
-+     * RAM (firewall)	68005000 - 680053ff
-+     * RAM (err login)	68005400 - 680057ff
-+     * ROM (firewall)	68005800 - 68005bff
-+     * ROM (err login)	68005c00 - 68005fff
-+     * GPMC (firewall)	68006000 - 680063ff
-+     * GPMC (err login)	68006400 - 680067ff
-+     * SMS (err login)	68006c00 - 68006fff
-+     * SMS registers	68008000 - 68008fff
-+     * SDRC registers	68009000 - 68009fff
-+     * GPMC registers	6800a000   6800afff
-+     */
-+
-+    qemu_register_reset(omap2_mpu_reset, s);
-+
-+    return s;
-+}
-diff --git a/hw/omap_clk.c b/hw/omap_clk.c
-index 37daec2..da03e15 100644
---- a/hw/omap_clk.c
-+++ b/hw/omap_clk.c
-@@ -34,6 +34,9 @@ struct clk {
- #define CLOCK_IN_OMAP730	(1 << 11)
- #define CLOCK_IN_OMAP1510	(1 << 12)
- #define CLOCK_IN_OMAP16XX	(1 << 13)
-+#define CLOCK_IN_OMAP242X	(1 << 14)
-+#define CLOCK_IN_OMAP243X	(1 << 15)
-+#define CLOCK_IN_OMAP343X	(1 << 16)
-     uint32_t flags;
-     int id;
- 
-@@ -55,7 +58,8 @@ static struct clk xtal_osc12m = {
- static struct clk xtal_osc32k = {
-     .name	= "xtal_osc_32k",
-     .rate	= 32768,
--    .flags	= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310,
-+    .flags	= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 |
-+            CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
- };
- 
- static struct clk ck_ref = {
-@@ -502,11 +506,441 @@ static struct clk i2c_ick = {
- static struct clk clk32k = {
-     .name	= "clk32-kHz",
-     .flags	= CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
--            ALWAYS_ENABLED,
--    .parent     = &xtal_osc32k,
-+            CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
-+    .parent	= &xtal_osc32k,
-+};
-+
-+static struct clk apll_96m = {
-+    .name	= "apll_96m",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
-+    .rate	= 96000000,
-+    /*.parent	= sys.xtalin */
-+};
-+
-+static struct clk apll_54m = {
-+    .name	= "apll_54m",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
-+    .rate	= 54000000,
-+    /*.parent	= sys.xtalin */
-+};
-+
-+static struct clk sys_clk = {
-+    .name	= "sys_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
-+    .rate	= 32768,
-+    /*.parent	= sys.xtalin */
-+};
-+
-+static struct clk sleep_clk = {
-+    .name	= "sleep_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
-+    .rate	= 32768,
-+    /*.parent	= sys.xtalin */
-+};
-+
-+static struct clk dpll_ck = {
-+    .name	= "dpll",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
-+    /*.parent	= sys.xtalin */
-+};
-+
-+static struct clk dpll_x2_ck = {
-+    .name	= "dpll_x2",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
-+    /*.parent	= sys.xtalin */
-+};
-+
-+static struct clk wdt1_sys_clk = {
-+    .name	= "wdt1_sys_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
-+    .rate	= 32768,
-+    /*.parent	= sys.xtalin */
-+};
-+
-+static struct clk func_96m_clk = {
-+    .name	= "func_96m_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .divisor	= 1,
-+    .parent	= &apll_96m,
-+};
-+
-+static struct clk func_48m_clk = {
-+    .name	= "func_48m_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .divisor	= 2,
-+    .parent	= &apll_96m,
-+};
-+
-+static struct clk func_12m_clk = {
-+    .name	= "func_12m_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .divisor	= 8,
-+    .parent	= &apll_96m,
-+};
-+
-+static struct clk func_54m_clk = {
-+    .name	= "func_54m_clk",
-+    .flags	= CLOCK_IN_OMAP242X,
-+    .divisor	= 1,
-+    .parent	= &apll_54m,
-+};
-+
-+static struct clk sys_clkout = {
-+    .name	= "clkout",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &sys_clk,
-+};
-+
-+static struct clk sys_clkout2 = {
-+    .name	= "clkout2",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &sys_clk,
-+};
-+
-+static struct clk core_clk = {
-+    .name	= "core_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &dpll_ck,
-+};
-+
-+static struct clk l3_clk = {
-+    .name	= "l3_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &core_clk,
-+};
-+
-+static struct clk core_l4_iclk = {
-+    .name	= "core_l4_iclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &l3_clk,
-+};
-+
-+static struct clk wu_l4_iclk = {
-+    .name	= "wu_l4_iclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &l3_clk,
-+};
-+
-+static struct clk core_l3_iclk = {
-+    .name	= "core_l3_iclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &core_clk,
-+};
-+
-+static struct clk core_l4_usb_clk = {
-+    .name	= "core_l4_usb_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &l3_clk,
-+};
-+
-+static struct clk wu_gpt1_clk = {
-+    .name	= "wu_gpt1_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &sys_clk,
-+};
-+
-+static struct clk wu_32k_clk = {
-+    .name	= "wu_32k_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &sys_clk,
-+};
-+
-+static struct clk uart1_fclk = {
-+    .name	= "uart1_fclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &func_48m_clk,
-+};
-+
-+static struct clk uart1_iclk = {
-+    .name	= "uart1_iclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &core_l4_iclk,
-+};
-+
-+static struct clk uart2_fclk = {
-+    .name	= "uart2_fclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &func_48m_clk,
-+};
-+
-+static struct clk uart2_iclk = {
-+    .name	= "uart2_iclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &core_l4_iclk,
-+};
-+
-+static struct clk uart3_fclk = {
-+    .name	= "uart3_fclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &func_48m_clk,
-+};
-+
-+static struct clk uart3_iclk = {
-+    .name	= "uart3_iclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &core_l4_iclk,
-+};
-+
-+static struct clk mpu_fclk = {
-+    .name	= "mpu_fclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &core_clk,
-+};
-+
-+static struct clk mpu_iclk = {
-+    .name	= "mpu_iclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &core_clk,
-+};
-+
-+static struct clk int_m_fclk = {
-+    .name	= "int_m_fclk",
-+    .alias	= "mpu_intc_fclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &core_clk,
-+};
-+
-+static struct clk int_m_iclk = {
-+    .name	= "int_m_iclk",
-+    .alias	= "mpu_intc_iclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &core_clk,
-+};
-+
-+static struct clk core_gpt2_clk = {
-+    .name	= "core_gpt2_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &sys_clk,
-+};
-+
-+static struct clk core_gpt3_clk = {
-+    .name	= "core_gpt3_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &sys_clk,
-+};
-+
-+static struct clk core_gpt4_clk = {
-+    .name	= "core_gpt4_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &sys_clk,
-+};
-+
-+static struct clk core_gpt5_clk = {
-+    .name	= "core_gpt5_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &sys_clk,
-+};
-+
-+static struct clk core_gpt6_clk = {
-+    .name	= "core_gpt6_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &sys_clk,
-+};
-+
-+static struct clk core_gpt7_clk = {
-+    .name	= "core_gpt7_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &sys_clk,
-+};
-+
-+static struct clk core_gpt8_clk = {
-+    .name	= "core_gpt8_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &sys_clk,
-+};
-+
-+static struct clk core_gpt9_clk = {
-+    .name	= "core_gpt9_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &sys_clk,
-+};
-+
-+static struct clk core_gpt10_clk = {
-+    .name	= "core_gpt10_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &sys_clk,
-+};
-+
-+static struct clk core_gpt11_clk = {
-+    .name	= "core_gpt11_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &sys_clk,
-+};
-+
-+static struct clk core_gpt12_clk = {
-+    .name	= "core_gpt12_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &sys_clk,
-+};
-+
-+static struct clk mcbsp1_clk = {
-+    .name	= "mcbsp1_cg",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .divisor	= 2,
-+    .parent	= &func_96m_clk,
-+};
-+
-+static struct clk mcbsp2_clk = {
-+    .name	= "mcbsp2_cg",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .divisor	= 2,
-+    .parent	= &func_96m_clk,
-+};
-+
-+static struct clk emul_clk = {
-+    .name	= "emul_ck",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &func_54m_clk,
-+};
-+
-+static struct clk sdma_fclk = {
-+    .name	= "sdma_fclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &l3_clk,
-+};
-+
-+static struct clk sdma_iclk = {
-+    .name	= "sdma_iclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &core_l3_iclk, /* core_l4_iclk for the configuration port */
-+};
-+
-+static struct clk i2c1_fclk = {
-+    .name	= "i2c1.fclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &func_12m_clk,
-+    .divisor	= 1,
-+};
-+
-+static struct clk i2c1_iclk = {
-+    .name	= "i2c1.iclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &core_l4_iclk,
-+};
-+
-+static struct clk i2c2_fclk = {
-+    .name	= "i2c2.fclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &func_12m_clk,
-+    .divisor	= 1,
-+};
-+
-+static struct clk i2c2_iclk = {
-+    .name	= "i2c2.iclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &core_l4_iclk,
-+};
-+
-+static struct clk gpio_dbclk[4] = {
-+    {
-+        .name	= "gpio1_dbclk",
-+        .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+        .parent	= &wu_32k_clk,
-+    }, {
-+        .name	= "gpio2_dbclk",
-+        .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+        .parent	= &wu_32k_clk,
-+    }, {
-+        .name	= "gpio3_dbclk",
-+        .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+        .parent	= &wu_32k_clk,
-+    }, {
-+        .name	= "gpio4_dbclk",
-+        .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+        .parent	= &wu_32k_clk,
-+    },
-+};
-+
-+static struct clk gpio_iclk = {
-+    .name	= "gpio_iclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &wu_l4_iclk,
-+};
-+
-+static struct clk mmc_fck = {
-+    .name	= "mmc_fclk",
-+    .flags	= CLOCK_IN_OMAP242X,
-+    .parent	= &func_96m_clk,
-+};
-+
-+static struct clk mmc_ick = {
-+    .name	= "mmc_iclk",
-+    .flags	= CLOCK_IN_OMAP242X,
-+    .parent	= &core_l4_iclk,
-+};
-+
-+static struct clk spi_fclk[3] = {
-+    {
-+        .name	= "spi1_fclk",
-+        .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+        .parent	= &func_48m_clk,
-+    }, {
-+        .name	= "spi2_fclk",
-+        .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+        .parent	= &func_48m_clk,
-+    }, {
-+        .name	= "spi3_fclk",
-+        .flags	= CLOCK_IN_OMAP243X,
-+        .parent	= &func_48m_clk,
-+    },
-+};
-+
-+static struct clk dss_clk[2] = {
-+    {
-+        .name	= "dss_clk1",
-+        .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+        .parent	= &core_clk,
-+    }, {
-+        .name	= "dss_clk2",
-+        .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+        .parent	= &sys_clk,
-+    },
-+};
-+
-+static struct clk dss_54m_clk = {
-+    .name	= "dss_54m_clk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &func_54m_clk,
-+};
-+
-+static struct clk dss_l3_iclk = {
-+    .name	= "dss_l3_iclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &core_l3_iclk,
-+};
-+
-+static struct clk dss_l4_iclk = {
-+    .name	= "dss_l4_iclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    .parent	= &core_l4_iclk,
-+};
-+
-+static struct clk spi_iclk[3] = {
-+    {
-+        .name	= "spi1_iclk",
-+        .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+        .parent	= &core_l4_iclk,
-+    }, {
-+        .name	= "spi2_iclk",
-+        .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+        .parent	= &core_l4_iclk,
-+    }, {
-+        .name	= "spi3_iclk",
-+        .flags	= CLOCK_IN_OMAP243X,
-+        .parent	= &core_l4_iclk,
-+    },
-+};
-+
-+static struct clk omapctrl_clk = {
-+    .name	= "omapctrl_iclk",
-+    .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-+    /* XXX Should be in WKUP domain */
-+    .parent	= &core_l4_iclk,
- };
- 
- static struct clk *onchip_clks[] = {
-+    /* OMAP 1 */
-+
-     /* non-ULPD clocks */
-     &xtal_osc12m,
-     &xtal_osc32k,
-@@ -572,6 +1006,80 @@ static struct clk *onchip_clks[] = {
-     /* Virtual clocks */
-     &i2c_fck,
-     &i2c_ick,
-+
-+    /* OMAP 2 */
-+
-+    &apll_96m,
-+    &apll_54m,
-+    &sys_clk,
-+    &sleep_clk,
-+    &dpll_ck,
-+    &dpll_x2_ck,
-+    &wdt1_sys_clk,
-+    &func_96m_clk,
-+    &func_48m_clk,
-+    &func_12m_clk,
-+    &func_54m_clk,
-+    &sys_clkout,
-+    &sys_clkout2,
-+    &core_clk,
-+    &l3_clk,
-+    &core_l4_iclk,
-+    &wu_l4_iclk,
-+    &core_l3_iclk,
-+    &core_l4_usb_clk,
-+    &wu_gpt1_clk,
-+    &wu_32k_clk,
-+    &uart1_fclk,
-+    &uart1_iclk,
-+    &uart2_fclk,
-+    &uart2_iclk,
-+    &uart3_fclk,
-+    &uart3_iclk,
-+    &mpu_fclk,
-+    &mpu_iclk,
-+    &int_m_fclk,
-+    &int_m_iclk,
-+    &core_gpt2_clk,
-+    &core_gpt3_clk,
-+    &core_gpt4_clk,
-+    &core_gpt5_clk,
-+    &core_gpt6_clk,
-+    &core_gpt7_clk,
-+    &core_gpt8_clk,
-+    &core_gpt9_clk,
-+    &core_gpt10_clk,
-+    &core_gpt11_clk,
-+    &core_gpt12_clk,
-+    &mcbsp1_clk,
-+    &mcbsp2_clk,
-+    &emul_clk,
-+    &sdma_fclk,
-+    &sdma_iclk,
-+    &i2c1_fclk,
-+    &i2c1_iclk,
-+    &i2c2_fclk,
-+    &i2c2_iclk,
-+    &gpio_dbclk[0],
-+    &gpio_dbclk[1],
-+    &gpio_dbclk[2],
-+    &gpio_dbclk[3],
-+    &gpio_iclk,
-+    &mmc_fck,
-+    &mmc_ick,
-+    &spi_fclk[0],
-+    &spi_iclk[0],
-+    &spi_fclk[1],
-+    &spi_iclk[1],
-+    &spi_fclk[2],
-+    &spi_iclk[2],
-+    &dss_clk[0],
-+    &dss_clk[1],
-+    &dss_54m_clk,
-+    &dss_l3_iclk,
-+    &dss_l4_iclk,
-+    &omapctrl_clk,
-+
-     0
- };
- 
-@@ -727,6 +1235,12 @@ void omap_clk_init(struct omap_mpu_state_s *mpu)
-         flag = CLOCK_IN_OMAP310;
-     else if (cpu_is_omap1510(mpu))
-         flag = CLOCK_IN_OMAP1510;
-+    else if (cpu_is_omap2410(mpu) || cpu_is_omap2420(mpu))
-+        flag = CLOCK_IN_OMAP242X;
-+    else if (cpu_is_omap2430(mpu))
-+        flag = CLOCK_IN_OMAP243X;
-+    else if (cpu_is_omap3430(mpu))
-+        flag = CLOCK_IN_OMAP243X;
-     else
-         return;
- 
-diff --git a/hw/omap_dma.c b/hw/omap_dma.c
-index 1835826..6c0bd82 100644
---- a/hw/omap_dma.c
-+++ b/hw/omap_dma.c
-@@ -28,12 +28,15 @@ struct omap_dma_channel_s {
-     /* transfer data */
-     int burst[2];
-     int pack[2];
-+    int endian[2];
-+    int endian_lock[2];
-+    int translate[2];
-     enum omap_dma_port port[2];
-     target_phys_addr_t addr[2];
-     omap_dma_addressing_t mode[2];
--    uint16_t elements;
-+    uint32_t elements;
-     uint16_t frames;
--    int16_t frame_index[2];
-+    int32_t frame_index[2];
-     int16_t element_index[2];
-     int data_type;
- 
-@@ -41,6 +44,7 @@ struct omap_dma_channel_s {
-     int transparent_copy;
-     int constant_fill;
-     uint32_t color;
-+    int prefetch;
- 
-     /* auto init and linked channel data */
-     int end_prog;
-@@ -52,11 +56,13 @@ struct omap_dma_channel_s {
-     /* interruption data */
-     int interrupts;
-     int status;
-+    int cstatus;
- 
-     /* state data */
-     int active;
-     int enable;
-     int sync;
-+    int src_sync;
-     int pending_request;
-     int waiting_end_prog;
-     uint16_t cpc;
-@@ -75,16 +81,21 @@ struct omap_dma_channel_s {
-         target_phys_addr_t src, dest;
-         int frame;
-         int element;
-+        int pck_element;
-         int frame_delta[2];
-         int elem_delta[2];
-         int frames;
-         int elements;
-+        int pck_elements;
-     } active_set;
- 
-     /* unused parameters */
-+    int write_mode;
-     int priority;
-     int interleave_disabled;
-     int type;
-+    int suspend;
-+    int buf_disable;
- };
- 
- struct omap_dma_s {
-@@ -93,15 +104,21 @@ struct omap_dma_s {
-     target_phys_addr_t base;
-     omap_clk clk;
-     int64_t delay;
--    uint32_t drq;
-+    uint64_t drq;
-+    qemu_irq irq[4];
-+    void (*intr_update)(struct omap_dma_s *s);
-     enum omap_dma_model model;
-     int omap_3_1_mapping_disabled;
- 
--    uint16_t gcr;
-+    uint32_t gcr;
-+    uint32_t ocp;
-+    uint32_t caps[5];
-+    uint32_t irqen[4];
-+    uint32_t irqstat[4];
-     int run_count;
- 
-     int chans;
--    struct omap_dma_channel_s ch[16];
-+    struct omap_dma_channel_s ch[32];
-     struct omap_dma_lcd_channel_s lcd_ch;
- };
- 
-@@ -113,23 +130,13 @@ struct omap_dma_s {
- #define LAST_FRAME_INTR (1 << 4)
- #define END_BLOCK_INTR  (1 << 5)
- #define SYNC            (1 << 6)
-+#define END_PKT_INTR	(1 << 7)
-+#define TRANS_ERR_INTR	(1 << 8)
-+#define MISALIGN_INTR	(1 << 11)
- 
--static void omap_dma_interrupts_update(struct omap_dma_s *s)
-+static inline void omap_dma_interrupts_update(struct omap_dma_s *s)
- {
--    struct omap_dma_channel_s *ch = s->ch;
--    int i;
--
--    if (s->omap_3_1_mapping_disabled) {
--        for (i = 0; i < s->chans; i ++, ch ++)
--            if (ch->status)
--                qemu_irq_raise(ch->irq);
--    } else {
--        /* First three interrupts are shared between two channels each. */
--        for (i = 0; i < 6; i ++, ch ++) {
--            if (ch->status || (ch->sibling && ch->sibling->status))
--                qemu_irq_raise(ch->irq);
--        }
--    }
-+    return s->intr_update(s);
- }
- 
- static void omap_dma_channel_load(struct omap_dma_s *s,
-@@ -148,8 +155,10 @@ static void omap_dma_channel_load(struct omap_dma_s *s,
-     a->dest = ch->addr[1];
-     a->frames = ch->frames;
-     a->elements = ch->elements;
-+    a->pck_elements = ch->frame_index[!ch->src_sync];
-     a->frame = 0;
-     a->element = 0;
-+    a->pck_element = 0;
- 
-     if (unlikely(!ch->elements || !ch->frames)) {
-         printf("%s: bad DMA request\n", __FUNCTION__);
-@@ -202,16 +211,15 @@ static void omap_dma_deactivate_channel(struct omap_dma_s *s,
-     /* Update cpc */
-     ch->cpc = ch->active_set.dest & 0xffff;
- 
--    if (ch->pending_request && !ch->waiting_end_prog) {
-+    if (ch->pending_request && !ch->waiting_end_prog && ch->enable) {
-         /* Don't deactivate the channel */
-         ch->pending_request = 0;
--        if (ch->enable)
--            return;
-+        return;
-     }
- 
-     /* Don't deactive the channel if it is synchronized and the DMA request is
-        active */
--    if (ch->sync && (s->drq & (1 << ch->sync)) && ch->enable)
-+    if (ch->sync && ch->enable && (s->drq & (1 << ch->sync)))
-         return;
- 
-     if (ch->active) {
-@@ -231,6 +239,9 @@ static void omap_dma_enable_channel(struct omap_dma_s *s,
-         ch->enable = 1;
-         ch->waiting_end_prog = 0;
-         omap_dma_channel_load(s, ch);
-+        /* TODO: theoretically if ch->sync && ch->prefetch &&
-+         * !s->drq[ch->sync], we should also activate and fetch from source
-+         * and then stall until signalled.  */
-         if ((!ch->sync) || (s->drq & (1 << ch->sync)))
-             omap_dma_activate_channel(s, ch);
-     }
-@@ -259,16 +270,47 @@ static void omap_dma_channel_end_prog(struct omap_dma_s *s,
-     }
- }
- 
-+static void omap_dma_interrupts_3_1_update(struct omap_dma_s *s)
-+{
-+    struct omap_dma_channel_s *ch = s->ch;
-+
-+    /* First three interrupts are shared between two channels each. */
-+    if (ch[0].status | ch[6].status)
-+        qemu_irq_raise(ch[0].irq);
-+    if (ch[1].status | ch[7].status)
-+        qemu_irq_raise(ch[1].irq);
-+    if (ch[2].status | ch[8].status)
-+        qemu_irq_raise(ch[2].irq);
-+    if (ch[3].status)
-+        qemu_irq_raise(ch[3].irq);
-+    if (ch[4].status)
-+        qemu_irq_raise(ch[4].irq);
-+    if (ch[5].status)
-+        qemu_irq_raise(ch[5].irq);
-+}
-+
-+static void omap_dma_interrupts_3_2_update(struct omap_dma_s *s)
-+{
-+    struct omap_dma_channel_s *ch = s->ch;
-+    int i;
-+
-+    for (i = s->chans; i; ch ++, i --)
-+        if (ch->status)
-+            qemu_irq_raise(ch->irq);
-+}
-+
- static void omap_dma_enable_3_1_mapping(struct omap_dma_s *s)
- {
-     s->omap_3_1_mapping_disabled = 0;
-     s->chans = 9;
-+    s->intr_update = omap_dma_interrupts_3_1_update;
- }
- 
- static void omap_dma_disable_3_1_mapping(struct omap_dma_s *s)
- {
-     s->omap_3_1_mapping_disabled = 1;
-     s->chans = 16;
-+    s->intr_update = omap_dma_interrupts_3_2_update;
- }
- 
- static void omap_dma_process_request(struct omap_dma_s *s, int request)
-@@ -358,6 +400,22 @@ static void omap_dma_channel_run(struct omap_dma_s *s)
-                 if (ch->interrupts & HALF_FRAME_INTR)
-                     ch->status |= HALF_FRAME_INTR;
- 
-+            if (ch->fs && ch->bs) {
-+                a->pck_element ++;
-+                /* Check if a full packet has beed transferred.  */
-+                if (a->pck_element == a->pck_elements) {
-+                    a->pck_element = 0;
-+
-+                    /* Set the END_PKT interrupt */
-+                    if ((ch->interrupts & END_PKT_INTR) && !ch->src_sync)
-+                        ch->status |= END_PKT_INTR;
-+
-+                    /* If the channel is packet-synchronized, deactivate it */
-+                    if (ch->sync)
-+                        omap_dma_deactivate_channel(s, ch);
-+                }
-+            }
-+
-             if (a->element == a->elements) {
-                 /* End of Frame */
-                 a->element = 0;
-@@ -366,7 +424,7 @@ static void omap_dma_channel_run(struct omap_dma_s *s)
-                 a->frame ++;
- 
-                 /* If the channel is frame synchronized, deactivate it */
--                if (ch->sync && ch->fs)
-+                if (ch->sync && ch->fs && !ch->bs)
-                     omap_dma_deactivate_channel(s, ch);
- 
-                 /* If the channel is async, update cpc */
-@@ -414,50 +472,62 @@ void omap_dma_reset(struct omap_dma_s *s)
-     int i;
- 
-     qemu_del_timer(s->tm);
--    s->gcr = 0x0004;
-+    if (s->model < omap_dma_4)
-+        s->gcr = 0x0004;
-+    else
-+        s->gcr = 0x00010010;
-+    s->ocp = 0x00000000;
-+    memset(&s->irqstat, 0, sizeof(s->irqstat));
-+    memset(&s->irqen, 0, sizeof(s->irqen));
-     s->drq = 0x00000000;
-     s->run_count = 0;
-     s->lcd_ch.src = emiff;
-     s->lcd_ch.condition = 0;
-     s->lcd_ch.interrupts = 0;
-     s->lcd_ch.dual = 0;
--    omap_dma_enable_3_1_mapping(s);
-+    if (s->model < omap_dma_4)
-+        omap_dma_enable_3_1_mapping(s);
-     for (i = 0; i < s->chans; i ++) {
-+        s->ch[i].suspend = 0;
-+        s->ch[i].prefetch = 0;
-+        s->ch[i].buf_disable = 0;
-+        s->ch[i].src_sync = 0;
-         memset(&s->ch[i].burst, 0, sizeof(s->ch[i].burst));
-         memset(&s->ch[i].port, 0, sizeof(s->ch[i].port));
-         memset(&s->ch[i].mode, 0, sizeof(s->ch[i].mode));
--        memset(&s->ch[i].elements, 0, sizeof(s->ch[i].elements));
--        memset(&s->ch[i].frames, 0, sizeof(s->ch[i].frames));
-         memset(&s->ch[i].frame_index, 0, sizeof(s->ch[i].frame_index));
-         memset(&s->ch[i].element_index, 0, sizeof(s->ch[i].element_index));
--        memset(&s->ch[i].data_type, 0, sizeof(s->ch[i].data_type));
--        memset(&s->ch[i].transparent_copy, 0,
--                        sizeof(s->ch[i].transparent_copy));
--        memset(&s->ch[i].constant_fill, 0, sizeof(s->ch[i].constant_fill));
--        memset(&s->ch[i].color, 0, sizeof(s->ch[i].color));
--        memset(&s->ch[i].end_prog, 0, sizeof(s->ch[i].end_prog));
--        memset(&s->ch[i].repeat, 0, sizeof(s->ch[i].repeat));
--        memset(&s->ch[i].auto_init, 0, sizeof(s->ch[i].auto_init));
--        memset(&s->ch[i].link_enabled, 0, sizeof(s->ch[i].link_enabled));
--        memset(&s->ch[i].link_next_ch, 0, sizeof(s->ch[i].link_next_ch));
--        s->ch[i].interrupts = 0x0003;
--        memset(&s->ch[i].status, 0, sizeof(s->ch[i].status));
--        memset(&s->ch[i].active, 0, sizeof(s->ch[i].active));
--        memset(&s->ch[i].enable, 0, sizeof(s->ch[i].enable));
--        memset(&s->ch[i].sync, 0, sizeof(s->ch[i].sync));
--        memset(&s->ch[i].pending_request, 0, sizeof(s->ch[i].pending_request));
--        memset(&s->ch[i].waiting_end_prog, 0,
--                        sizeof(s->ch[i].waiting_end_prog));
--        memset(&s->ch[i].cpc, 0, sizeof(s->ch[i].cpc));
--        memset(&s->ch[i].fs, 0, sizeof(s->ch[i].fs));
--        memset(&s->ch[i].bs, 0, sizeof(s->ch[i].bs));
--        memset(&s->ch[i].omap_3_1_compatible_disable, 0,
--                        sizeof(s->ch[i].omap_3_1_compatible_disable));
-+        memset(&s->ch[i].endian, 0, sizeof(s->ch[i].endian));
-+        memset(&s->ch[i].endian_lock, 0, sizeof(s->ch[i].endian_lock));
-+        memset(&s->ch[i].translate, 0, sizeof(s->ch[i].translate));
-+        s->ch[i].write_mode = 0;
-+        s->ch[i].data_type = 0;
-+        s->ch[i].transparent_copy = 0;
-+        s->ch[i].constant_fill = 0;
-+        s->ch[i].color = 0x00000000;
-+        s->ch[i].end_prog = 0;
-+        s->ch[i].repeat = 0;
-+        s->ch[i].auto_init = 0;
-+        s->ch[i].link_enabled = 0;
-+        if (s->model < omap_dma_4)
-+            s->ch[i].interrupts = 0x0003;
-+        else
-+            s->ch[i].interrupts = 0x0000;
-+        s->ch[i].status = 0;
-+        s->ch[i].cstatus = 0;
-+        s->ch[i].active = 0;
-+        s->ch[i].enable = 0;
-+        s->ch[i].sync = 0;
-+        s->ch[i].pending_request = 0;
-+        s->ch[i].waiting_end_prog = 0;
-+        s->ch[i].cpc = 0x0000;
-+        s->ch[i].fs = 0;
-+        s->ch[i].bs = 0;
-+        s->ch[i].omap_3_1_compatible_disable = 0;
-         memset(&s->ch[i].active_set, 0, sizeof(s->ch[i].active_set));
--        memset(&s->ch[i].priority, 0, sizeof(s->ch[i].priority));
--        memset(&s->ch[i].interleave_disabled, 0,
--                        sizeof(s->ch[i].interleave_disabled));
--        memset(&s->ch[i].type, 0, sizeof(s->ch[i].type));
-+        s->ch[i].priority = 0;
-+        s->ch[i].interleave_disabled = 0;
-+        s->ch[i].type = 0;
-     }
- }
- 
-@@ -476,7 +546,7 @@ static int omap_dma_ch_reg_read(struct omap_dma_s *s,
-         break;
- 
-     case 0x02:	/* SYS_DMA_CCR_CH0 */
--        if (s->model == omap_dma_3_1)
-+        if (s->model <= omap_dma_3_1)
-             *value = 0 << 10;			/* FIFO_FLUSH reads as 0 */
-         else
-             *value = ch->omap_3_1_compatible_disable << 10;
-@@ -596,11 +666,11 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s,
-         ch->burst[0] = (value & 0x0180) >> 7;
-         ch->pack[0] = (value & 0x0040) >> 6;
-         ch->port[0] = (enum omap_dma_port) ((value & 0x003c) >> 2);
--        ch->data_type = (1 << (value & 3));
--        if (ch->port[0] >= omap_dma_port_last)
-+        ch->data_type = 1 << (value & 3);
-+        if (ch->port[0] >= __omap_dma_port_last)
-             printf("%s: invalid DMA port %i\n", __FUNCTION__,
-                             ch->port[0]);
--        if (ch->port[1] >= omap_dma_port_last)
-+        if (ch->port[1] >= __omap_dma_port_last)
-             printf("%s: invalid DMA port %i\n", __FUNCTION__,
-                             ch->port[1]);
-         if ((value & 3) == 3)
-@@ -611,7 +681,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s,
-         ch->mode[1] = (omap_dma_addressing_t) ((value & 0xc000) >> 14);
-         ch->mode[0] = (omap_dma_addressing_t) ((value & 0x3000) >> 12);
-         ch->end_prog = (value & 0x0800) >> 11;
--        if (s->model > omap_dma_3_1)
-+        if (s->model >= omap_dma_3_2)
-             ch->omap_3_1_compatible_disable  = (value >> 10) & 0x1;
-         ch->repeat = (value & 0x0200) >> 9;
-         ch->auto_init = (value & 0x0100) >> 8;
-@@ -630,7 +700,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s,
-         break;
- 
-     case 0x04:	/* SYS_DMA_CICR_CH0 */
--        ch->interrupts = value;
-+        ch->interrupts = value & 0x3f;
-         break;
- 
-     case 0x06:	/* SYS_DMA_CSR_CH0 */
-@@ -696,7 +766,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s,
-         break;
- 
-     case 0x24:	/* DMA_CCR2 */
--        ch->bs  = (value >> 2) & 0x1;
-+        ch->bs = (value >> 2) & 0x1;
-         ch->transparent_copy = (value >> 1) & 0x1;
-         ch->constant_fill = value & 0x1;
-         break;
-@@ -1126,48 +1196,29 @@ static int omap_dma_sys_read(struct omap_dma_s *s, int offset,
-         break;
- 
-     case 0x44e:	/* DMA_CAPS_0_U */
--        *ret = (1 << 3) | /* Constant Fill Capacity */
--            (1 << 2);     /* Transparent BLT Capacity */
-+        *ret = (s->caps[0] >> 16) & 0xffff;
-         break;
--
-     case 0x450:	/* DMA_CAPS_0_L */
--    case 0x452:	/* DMA_CAPS_1_U */
--        *ret = 0;
-+        *ret = (s->caps[0] >>  0) & 0xffff;
-         break;
- 
-+    case 0x452:	/* DMA_CAPS_1_U */
-+        *ret = (s->caps[1] >> 16) & 0xffff;
-+        break;
-     case 0x454:	/* DMA_CAPS_1_L */
--        *ret = (1 << 1); /* 1-bit palletized capability */
-+        *ret = (s->caps[1] >>  0) & 0xffff;
-         break;
- 
-     case 0x456:	/* DMA_CAPS_2 */
--        *ret = (1 << 8) | /* SSDIC */
--            (1 << 7) |    /* DDIAC */
--            (1 << 6) |    /* DSIAC */
--            (1 << 5) |    /* DPIAC */
--            (1 << 4) |    /* DCAC  */
--            (1 << 3) |    /* SDIAC */
--            (1 << 2) |    /* SSIAC */
--            (1 << 1) |    /* SPIAC */
--            1;            /* SCAC  */
-+        *ret = s->caps[2];
-         break;
- 
-     case 0x458:	/* DMA_CAPS_3 */
--        *ret = (1 << 5) | /* CCC */
--            (1 << 4) |    /* IC  */
--            (1 << 3) |    /* ARC */
--            (1 << 2) |    /* AEC */
--            (1 << 1) |    /* FSC */
--            1;            /* ESC */
-+        *ret = s->caps[3];
-         break;
- 
-     case 0x45a:	/* DMA_CAPS_4 */
--        *ret = (1 << 6) | /* SSC  */
--            (1 << 5) |    /* BIC  */
--            (1 << 4) |    /* LFIC */
--            (1 << 3) |    /* FIC  */
--            (1 << 2) |    /* HFIC */
--            (1 << 1) |    /* EDIC */
--            1;            /* TOIC */
-+        *ret = s->caps[4];
-         break;
- 
-     case 0x460:	/* DMA_PCh2_SR */
-@@ -1193,7 +1244,7 @@ static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr)
- 
-     switch (offset) {
-     case 0x300 ... 0x3fe:
--        if (s->model == omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
-+        if (s->model <= omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
-             if (omap_dma_3_1_lcd_read(&s->lcd_ch, offset, &ret))
-                 break;
-             return ret;
-@@ -1207,7 +1258,7 @@ static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr)
-         return ret;
- 
-     case 0x404 ... 0x4fe:
--        if (s->model == omap_dma_3_1)
-+        if (s->model <= omap_dma_3_1)
-             break;
-         /* Fall through. */
-     case 0x400:
-@@ -1236,7 +1287,7 @@ static void omap_dma_write(void *opaque, target_phys_addr_t addr,
- 
-     switch (offset) {
-     case 0x300 ... 0x3fe:
--        if (s->model == omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
-+        if (s->model <= omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
-             if (omap_dma_3_1_lcd_write(&s->lcd_ch, offset, value))
-                 break;
-             return;
-@@ -1250,7 +1301,7 @@ static void omap_dma_write(void *opaque, target_phys_addr_t addr,
-         return;
- 
-     case 0x404 ... 0x4fe:
--        if (s->model == omap_dma_3_1)
-+        if (s->model <= omap_dma_3_1)
-             break;
-     case 0x400:
-         /* Fall through. */
-@@ -1285,7 +1336,7 @@ static CPUWriteMemoryFunc *omap_dma_writefn[] = {
- static void omap_dma_request(void *opaque, int drq, int req)
- {
-     struct omap_dma_s *s = (struct omap_dma_s *) opaque;
--    /* The request pins are level triggered.  */
-+    /* The request pins are level triggered in QEMU.  */
-     if (req) {
-         if (~s->drq & (1 << drq)) {
-             s->drq |= 1 << drq;
-@@ -1310,6 +1361,52 @@ static void omap_dma_clk_update(void *opaque, int line, int on)
-     }
- }
- 
-+static void omap_dma_setcaps(struct omap_dma_s *s)
-+{
-+    switch (s->model) {
-+    default:
-+    case omap_dma_3_1:
-+        break;
-+    case omap_dma_3_2:
-+    case omap_dma_4:
-+        /* XXX Only available for sDMA */
-+        s->caps[0] =
-+                (1 << 19) |	/* Constant Fill Capability */
-+                (1 << 18);	/* Transparent BLT Capability */
-+        s->caps[1] =
-+                (1 << 1);	/* 1-bit palettized capability (DMA 3.2 only) */
-+        s->caps[2] =
-+                (1 << 8) |	/* SEPARATE_SRC_AND_DST_INDEX_CPBLTY */
-+                (1 << 7) |	/* DST_DOUBLE_INDEX_ADRS_CPBLTY */
-+                (1 << 6) |	/* DST_SINGLE_INDEX_ADRS_CPBLTY */
-+                (1 << 5) |	/* DST_POST_INCRMNT_ADRS_CPBLTY */
-+                (1 << 4) |	/* DST_CONST_ADRS_CPBLTY */
-+                (1 << 3) |	/* SRC_DOUBLE_INDEX_ADRS_CPBLTY */
-+                (1 << 2) |	/* SRC_SINGLE_INDEX_ADRS_CPBLTY */
-+                (1 << 1) |	/* SRC_POST_INCRMNT_ADRS_CPBLTY */
-+                (1 << 0);	/* SRC_CONST_ADRS_CPBLTY */
-+        s->caps[3] =
-+                (1 << 6) |	/* BLOCK_SYNCHR_CPBLTY (DMA 4 only) */
-+                (1 << 7) |	/* PKT_SYNCHR_CPBLTY (DMA 4 only) */
-+                (1 << 5) |	/* CHANNEL_CHAINING_CPBLTY */
-+                (1 << 4) |	/* LCh_INTERLEAVE_CPBLTY */
-+                (1 << 3) |	/* AUTOINIT_REPEAT_CPBLTY (DMA 3.2 only) */
-+                (1 << 2) |	/* AUTOINIT_ENDPROG_CPBLTY (DMA 3.2 only) */
-+                (1 << 1) |	/* FRAME_SYNCHR_CPBLTY */
-+                (1 << 0);	/* ELMNT_SYNCHR_CPBLTY */
-+        s->caps[4] =
-+                (1 << 7) |	/* PKT_INTERRUPT_CPBLTY (DMA 4 only) */
-+                (1 << 6) |	/* SYNC_STATUS_CPBLTY */
-+                (1 << 5) |	/* BLOCK_INTERRUPT_CPBLTY */
-+                (1 << 4) |	/* LAST_FRAME_INTERRUPT_CPBLTY */
-+                (1 << 3) |	/* FRAME_INTERRUPT_CPBLTY */
-+                (1 << 2) |	/* HALF_FRAME_INTERRUPT_CPBLTY */
-+                (1 << 1) |	/* EVENT_DROP_INTERRUPT_CPBLTY */
-+                (1 << 0);	/* TIMEOUT_INTERRUPT_CPBLTY (DMA 3.2 only) */
-+        break;
-+    }
-+}
-+
- struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
-                 qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk,
-                 enum omap_dma_model model)
-@@ -1318,7 +1415,7 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
-     struct omap_dma_s *s = (struct omap_dma_s *)
-             qemu_mallocz(sizeof(struct omap_dma_s));
- 
--    if (model == omap_dma_3_1) {
-+    if (model <= omap_dma_3_1) {
-         num_irqs = 6;
-         memsize = 0x800;
-     } else {
-@@ -1331,6 +1428,7 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
-     s->clk = clk;
-     s->lcd_ch.irq = lcd_irq;
-     s->lcd_ch.mpu = mpu;
-+    omap_dma_setcaps(s);
-     while (num_irqs --)
-         s->ch[num_irqs].irq = irqs[num_irqs];
-     for (i = 0; i < 3; i ++) {
-@@ -1350,6 +1448,393 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
-     return s;
- }
- 
-+static void omap_dma_interrupts_4_update(struct omap_dma_s *s)
-+{
-+    struct omap_dma_channel_s *ch = s->ch;
-+    uint32_t bmp, bit;
-+
-+    for (bmp = 0, bit = 1; bit; ch ++, bit <<= 1)
-+        if (ch->status) {
-+            bmp |= bit;
-+            ch->cstatus |= ch->status;
-+            ch->status = 0;
-+        }
-+    if ((s->irqstat[0] |= s->irqen[0] & bmp))
-+        qemu_irq_raise(s->irq[0]);
-+    if ((s->irqstat[1] |= s->irqen[1] & bmp))
-+        qemu_irq_raise(s->irq[1]);
-+    if ((s->irqstat[2] |= s->irqen[2] & bmp))
-+        qemu_irq_raise(s->irq[2]);
-+    if ((s->irqstat[3] |= s->irqen[3] & bmp))
-+        qemu_irq_raise(s->irq[3]);
-+}
-+
-+static uint32_t omap_dma4_read(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_dma_s *s = (struct omap_dma_s *) opaque;
-+    int irqn = 0, chnum, offset = addr - s->base;
-+    struct omap_dma_channel_s *ch;
-+
-+    switch (offset) {
-+    case 0x00:	/* DMA4_REVISION */
-+        return 0x40;
-+
-+    case 0x14:	/* DMA4_IRQSTATUS_L3 */
-+        irqn ++;
-+    case 0x10:	/* DMA4_IRQSTATUS_L2 */
-+        irqn ++;
-+    case 0x0c:	/* DMA4_IRQSTATUS_L1 */
-+        irqn ++;
-+    case 0x08:	/* DMA4_IRQSTATUS_L0 */
-+        return s->irqstat[irqn];
-+
-+    case 0x24:	/* DMA4_IRQENABLE_L3 */
-+        irqn ++;
-+    case 0x20:	/* DMA4_IRQENABLE_L2 */
-+        irqn ++;
-+    case 0x1c:	/* DMA4_IRQENABLE_L1 */
-+        irqn ++;
-+    case 0x18:	/* DMA4_IRQENABLE_L0 */
-+        return s->irqen[irqn];
-+
-+    case 0x28:	/* DMA4_SYSSTATUS */
-+        return 1;						/* RESETDONE */
-+
-+    case 0x2c:	/* DMA4_OCP_SYSCONFIG */
-+        return s->ocp;
-+
-+    case 0x64:	/* DMA4_CAPS_0 */
-+        return s->caps[0];
-+    case 0x6c:	/* DMA4_CAPS_2 */
-+        return s->caps[2];
-+    case 0x70:	/* DMA4_CAPS_3 */
-+        return s->caps[3];
-+    case 0x74:	/* DMA4_CAPS_4 */
-+        return s->caps[4];
-+
-+    case 0x78:	/* DMA4_GCR */
-+        return s->gcr;
-+
-+    case 0x80 ... 0xfff:
-+        offset -= 0x80;
-+        chnum = offset / 0x60;
-+        ch = s->ch + chnum;
-+        offset -= chnum * 0x60;
-+        break;
-+
-+    default:
-+        OMAP_BAD_REG(addr);
-+        return 0;
-+    }
-+
-+    /* Per-channel registers */
-+    switch (offset) {
-+    case 0x00:	/* DMA4_CCR */
-+        return (ch->buf_disable << 25) |
-+                (ch->src_sync << 24) |
-+                (ch->prefetch << 23) |
-+                ((ch->sync & 0x60) << 14) |
-+                (ch->bs << 18) |
-+                (ch->transparent_copy << 17) |
-+                (ch->constant_fill << 16) |
-+                (ch->mode[1] << 14) |
-+                (ch->mode[0] << 12) |
-+                (0 << 10) | (0 << 9) |
-+                (ch->suspend << 8) |
-+                (ch->enable << 7) |
-+                (ch->priority << 6) |
-+                (ch->fs << 5) | (ch->sync & 0x1f);
-+
-+    case 0x04:	/* DMA4_CLNK_CTRL */
-+        return (ch->link_enabled << 15) | ch->link_next_ch;
-+
-+    case 0x08:	/* DMA4_CICR */
-+        return ch->interrupts;
-+
-+    case 0x0c:	/* DMA4_CSR */
-+        return ch->cstatus;
-+
-+    case 0x10:	/* DMA4_CSDP */
-+        return (ch->endian[0] << 21) |
-+                (ch->endian_lock[0] << 20) |
-+                (ch->endian[1] << 19) |
-+                (ch->endian_lock[1] << 18) |
-+                (ch->write_mode << 16) |
-+                (ch->burst[1] << 14) |
-+                (ch->pack[1] << 13) |
-+                (ch->translate[1] << 9) |
-+                (ch->burst[0] << 7) |
-+                (ch->pack[0] << 6) |
-+                (ch->translate[0] << 2) |
-+                (ch->data_type >> 1);
-+
-+    case 0x14:	/* DMA4_CEN */
-+        return ch->elements;
-+
-+    case 0x18:	/* DMA4_CFN */
-+        return ch->frames;
-+
-+    case 0x1c:	/* DMA4_CSSA */
-+        return ch->addr[0];
-+
-+    case 0x20:	/* DMA4_CDSA */
-+        return ch->addr[1];
-+
-+    case 0x24:	/* DMA4_CSEI */
-+        return ch->element_index[0];
-+
-+    case 0x28:	/* DMA4_CSFI */
-+        return ch->frame_index[0];
-+
-+    case 0x2c:	/* DMA4_CDEI */
-+        return ch->element_index[1];
-+
-+    case 0x30:	/* DMA4_CDFI */
-+        return ch->frame_index[1];
-+
-+    case 0x34:	/* DMA4_CSAC */
-+        return ch->active_set.src & 0xffff;
-+
-+    case 0x38:	/* DMA4_CDAC */
-+        return ch->active_set.dest & 0xffff;
-+
-+    case 0x3c:	/* DMA4_CCEN */
-+        return ch->active_set.element;
-+
-+    case 0x40:	/* DMA4_CCFN */
-+        return ch->active_set.frame;
-+
-+    case 0x44:	/* DMA4_COLOR */
-+        /* XXX only in sDMA */
-+        return ch->color;
-+
-+    default:
-+        OMAP_BAD_REG(addr);
-+        return 0;
-+    }
-+}
-+
-+static void omap_dma4_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct omap_dma_s *s = (struct omap_dma_s *) opaque;
-+    int chnum, irqn = 0, offset = addr - s->base;
-+    struct omap_dma_channel_s *ch;
-+
-+    switch (offset) {
-+    case 0x14:	/* DMA4_IRQSTATUS_L3 */
-+        irqn ++;
-+    case 0x10:	/* DMA4_IRQSTATUS_L2 */
-+        irqn ++;
-+    case 0x0c:	/* DMA4_IRQSTATUS_L1 */
-+        irqn ++;
-+    case 0x08:	/* DMA4_IRQSTATUS_L0 */
-+        s->irqstat[irqn] &= ~value;
-+        if (!s->irqstat[irqn])
-+            qemu_irq_lower(s->irq[irqn]);
-+        return;
-+
-+    case 0x24:	/* DMA4_IRQENABLE_L3 */
-+        irqn ++;
-+    case 0x20:	/* DMA4_IRQENABLE_L2 */
-+        irqn ++;
-+    case 0x1c:	/* DMA4_IRQENABLE_L1 */
-+        irqn ++;
-+    case 0x18:	/* DMA4_IRQENABLE_L0 */
-+        s->irqen[irqn] = value;
-+        return;
-+
-+    case 0x2c:	/* DMA4_OCP_SYSCONFIG */
-+        if (value & 2)						/* SOFTRESET */
-+            omap_dma_reset(s);
-+        s->ocp = value & 0x3321;
-+        if (((s->ocp >> 12) & 3) == 3)				/* MIDLEMODE */
-+            fprintf(stderr, "%s: invalid DMA power mode\n", __FUNCTION__);
-+        return;
-+
-+    case 0x78:	/* DMA4_GCR */
-+        s->gcr = value & 0x00ff00ff;
-+	if ((value & 0xff) == 0x00)		/* MAX_CHANNEL_FIFO_DEPTH */
-+            fprintf(stderr, "%s: wrong FIFO depth in GCR\n", __FUNCTION__);
-+        return;
-+
-+    case 0x80 ... 0xfff:
-+        offset -= 0x80;
-+        chnum = offset / 0x60;
-+        ch = s->ch + chnum;
-+        offset -= chnum * 0x60;
-+        break;
-+
-+    case 0x00:	/* DMA4_REVISION */
-+    case 0x28:	/* DMA4_SYSSTATUS */
-+    case 0x64:	/* DMA4_CAPS_0 */
-+    case 0x6c:	/* DMA4_CAPS_2 */
-+    case 0x70:	/* DMA4_CAPS_3 */
-+    case 0x74:	/* DMA4_CAPS_4 */
-+        OMAP_RO_REG(addr);
-+        return;
-+
-+    default:
-+        OMAP_BAD_REG(addr);
-+        return;
-+    }
-+
-+    /* Per-channel registers */
-+    switch (offset) {
-+    case 0x00:	/* DMA4_CCR */
-+        ch->buf_disable = (value >> 25) & 1;
-+        ch->src_sync = (value >> 24) & 1;	/* XXX For CamDMA must be 1 */
-+        if (ch->buf_disable && !ch->src_sync)
-+            fprintf(stderr, "%s: Buffering disable is not allowed in "
-+                            "destination synchronised mode\n", __FUNCTION__);
-+        ch->prefetch = (value >> 23) & 1;
-+        ch->bs = (value >> 18) & 1;
-+        ch->transparent_copy = (value >> 17) & 1;
-+        ch->constant_fill = (value >> 16) & 1;
-+        ch->mode[1] = (omap_dma_addressing_t) ((value & 0xc000) >> 14);
-+        ch->mode[0] = (omap_dma_addressing_t) ((value & 0x3000) >> 12);
-+        ch->suspend = (value & 0x0100) >> 8;
-+        ch->priority = (value & 0x0040) >> 6;
-+        ch->fs = (value & 0x0020) >> 5;
-+        if (ch->fs && ch->bs && ch->mode[0] && ch->mode[1])
-+            fprintf(stderr, "%s: For a packet transfer at least one port "
-+                            "must be constant-addressed\n", __FUNCTION__);
-+        ch->sync = (value & 0x001f) | ((value >> 14) & 0x0060);
-+        /* XXX must be 0x01 for CamDMA */
-+
-+        if (value & 0x0080)
-+            omap_dma_enable_channel(s, ch);
-+        else
-+            omap_dma_disable_channel(s, ch);
-+
-+        break;
-+
-+    case 0x04:	/* DMA4_CLNK_CTRL */
-+        ch->link_enabled = (value >> 15) & 0x1;
-+        ch->link_next_ch = value & 0x1f;
-+        break;
-+
-+    case 0x08:	/* DMA4_CICR */
-+        ch->interrupts = value & 0x09be;
-+        break;
-+
-+    case 0x0c:	/* DMA4_CSR */
-+        ch->cstatus &= ~value;
-+        break;
-+
-+    case 0x10:	/* DMA4_CSDP */
-+        ch->endian[0] =(value >> 21) & 1;
-+        ch->endian_lock[0] =(value >> 20) & 1;
-+        ch->endian[1] =(value >> 19) & 1;
-+        ch->endian_lock[1] =(value >> 18) & 1;
-+        if (ch->endian[0] != ch->endian[1])
-+            fprintf(stderr, "%s: DMA endianned conversion enable attempt\n",
-+                            __FUNCTION__);
-+        ch->write_mode = (value >> 16) & 3;
-+        ch->burst[1] = (value & 0xc000) >> 14;
-+        ch->pack[1] = (value & 0x2000) >> 13;
-+        ch->translate[1] = (value & 0x1e00) >> 9;
-+        ch->burst[0] = (value & 0x0180) >> 7;
-+        ch->pack[0] = (value & 0x0040) >> 6;
-+        ch->translate[0] = (value & 0x003c) >> 2;
-+        if (ch->translate[0] | ch->translate[1])
-+            fprintf(stderr, "%s: bad MReqAddressTranslate sideband signal\n",
-+                            __FUNCTION__);
-+        ch->data_type = 1 << (value & 3);
-+        if ((value & 3) == 3)
-+            printf("%s: bad data_type for DMA channel\n", __FUNCTION__);
-+        break;
-+
-+    case 0x14:	/* DMA4_CEN */
-+        ch->elements = value & 0xffffff;
-+        break;
-+
-+    case 0x18:	/* DMA4_CFN */
-+        ch->frames = value & 0xffff;
-+        break;
-+
-+    case 0x1c:	/* DMA4_CSSA */
-+        ch->addr[0] = (target_phys_addr_t) (uint32_t) value;
-+        break;
-+
-+    case 0x20:	/* DMA4_CDSA */
-+        ch->addr[1] = (target_phys_addr_t) (uint32_t) value;
-+        break;
-+
-+    case 0x24:	/* DMA4_CSEI */
-+        ch->element_index[0] = (int16_t) value;
-+        break;
-+
-+    case 0x28:	/* DMA4_CSFI */
-+        ch->frame_index[0] = (int32_t) value;
-+        break;
-+
-+    case 0x2c:	/* DMA4_CDEI */
-+        ch->element_index[1] = (int16_t) value;
-+        break;
-+
-+    case 0x30:	/* DMA4_CDFI */
-+        ch->frame_index[1] = (int32_t) value;
-+        break;
-+
-+    case 0x44:	/* DMA4_COLOR */
-+        /* XXX only in sDMA */
-+        ch->color = value;
-+        break;
-+
-+    case 0x34:	/* DMA4_CSAC */
-+    case 0x38:	/* DMA4_CDAC */
-+    case 0x3c:	/* DMA4_CCEN */
-+    case 0x40:	/* DMA4_CCFN */
-+        OMAP_RO_REG(addr);
-+        break;
-+
-+    default:
-+        OMAP_BAD_REG(addr);
-+    }
-+}
-+
-+static CPUReadMemoryFunc *omap_dma4_readfn[] = {
-+    omap_badwidth_read16,
-+    omap_dma4_read,
-+    omap_dma4_read,
-+};
-+
-+static CPUWriteMemoryFunc *omap_dma4_writefn[] = {
-+    omap_badwidth_write16,
-+    omap_dma4_write,
-+    omap_dma4_write,
-+};
-+
-+struct omap_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
-+                struct omap_mpu_state_s *mpu, int fifo,
-+                int chans, omap_clk iclk, omap_clk fclk)
-+{
-+    int iomemtype;
-+    struct omap_dma_s *s = (struct omap_dma_s *)
-+            qemu_mallocz(sizeof(struct omap_dma_s));
-+
-+    s->base = base;
-+    s->model = omap_dma_4;
-+    s->chans = chans;
-+    s->mpu = mpu;
-+    s->clk = fclk;
-+    memcpy(&s->irq, irqs, sizeof(s->irq));
-+    s->intr_update = omap_dma_interrupts_4_update;
-+    omap_dma_setcaps(s);
-+    s->tm = qemu_new_timer(vm_clock, (QEMUTimerCB *) omap_dma_channel_run, s);
-+    omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]);
-+    mpu->drq = qemu_allocate_irqs(omap_dma_request, s, 64);
-+    omap_dma_reset(s);
-+    omap_dma_clk_update(s, 0, 1);
-+
-+    iomemtype = cpu_register_io_memory(0, omap_dma4_readfn,
-+                    omap_dma4_writefn, s);
-+    cpu_register_physical_memory(s->base, 0x1000, iomemtype);
-+
-+    return s;
-+}
-+
- struct omap_dma_lcd_channel_s *omap_dma_get_lcdch(struct omap_dma_s *s)
- {
-     return &s->lcd_ch;
-diff --git a/hw/omap_dss.c b/hw/omap_dss.c
-new file mode 100644
-index 0000000..1c16802
---- /dev/null
-+++ b/hw/omap_dss.c
-@@ -0,0 +1,1088 @@
-+/*
-+ * OMAP2 Display Subsystem.
-+ *
-+ * Copyright (C) 2008 Nokia Corporation
-+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation; either version 2 of
-+ * the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-+ * MA 02111-1307 USA
-+ */
-+#include "hw.h"
-+#include "console.h"
-+#include "omap.h"
-+
-+struct omap_dss_s {
-+    target_phys_addr_t diss_base;
-+    target_phys_addr_t disc_base;
-+    target_phys_addr_t rfbi_base;
-+    target_phys_addr_t venc_base;
-+    target_phys_addr_t im3_base;
-+    qemu_irq irq;
-+    qemu_irq drq;
-+    DisplayState *state;
-+
-+    int autoidle;
-+    int control;
-+    int enable;
-+
-+    struct omap_dss_panel_s {
-+        int enable;
-+        int nx;
-+        int ny;
-+
-+        int x;
-+        int y;
-+    } dig, lcd;
-+
-+    struct {
-+        uint32_t idlemode;
-+        uint32_t irqst;
-+        uint32_t irqen;
-+        uint32_t control;
-+        uint32_t config;
-+        uint32_t capable;
-+        uint32_t timing[3];
-+        int line;
-+        uint32_t bg[2];
-+        uint32_t trans[2];
-+
-+        struct omap_dss_plane_s {
-+            int enable;
-+            int bpp;
-+            int posx;
-+            int posy;
-+            int nx;
-+            int ny;
-+
-+            target_phys_addr_t addr[3];
-+
-+            uint32_t attr;
-+            uint32_t tresh;
-+            int rowinc;
-+            int colinc;
-+            int wininc;
-+        } l[3];
-+
-+        int invalidate;
-+        uint16_t palette[256];
-+    } dispc;
-+
-+    struct {
-+        int idlemode;
-+        uint32_t control;
-+        int enable;
-+        int pixels;
-+        int busy;
-+        int skiplines;
-+        uint16_t rxbuf;
-+        uint32_t config[2];
-+        uint32_t time[4];
-+        uint32_t data[6];
-+        uint16_t vsync;
-+        uint16_t hsync;
-+        struct rfbi_chip_s *chip[2];
-+    } rfbi;
-+};
-+
-+static void omap_dispc_interrupt_update(struct omap_dss_s *s)
-+{
-+    qemu_set_irq(s->irq, s->dispc.irqst & s->dispc.irqen);
-+}
-+
-+static void omap_rfbi_reset(struct omap_dss_s *s)
-+{
-+    s->rfbi.idlemode = 0;
-+    s->rfbi.control = 2;
-+    s->rfbi.enable = 0;
-+    s->rfbi.pixels = 0;
-+    s->rfbi.skiplines = 0;
-+    s->rfbi.busy = 0;
-+    s->rfbi.config[0] = 0x00310000;
-+    s->rfbi.config[1] = 0x00310000;
-+    s->rfbi.time[0] = 0;
-+    s->rfbi.time[1] = 0;
-+    s->rfbi.time[2] = 0;
-+    s->rfbi.time[3] = 0;
-+    s->rfbi.data[0] = 0;
-+    s->rfbi.data[1] = 0;
-+    s->rfbi.data[2] = 0;
-+    s->rfbi.data[3] = 0;
-+    s->rfbi.data[4] = 0;
-+    s->rfbi.data[5] = 0;
-+    s->rfbi.vsync = 0;
-+    s->rfbi.hsync = 0;
-+}
-+
-+void omap_dss_reset(struct omap_dss_s *s)
-+{
-+    s->autoidle = 0;
-+    s->control = 0;
-+    s->enable = 0;
-+
-+    s->dig.enable = 0;
-+    s->dig.nx = 1;
-+    s->dig.ny = 1;
-+
-+    s->lcd.enable = 0;
-+    s->lcd.nx = 1;
-+    s->lcd.ny = 1;
-+
-+    s->dispc.idlemode = 0;
-+    s->dispc.irqst = 0;
-+    s->dispc.irqen = 0;
-+    s->dispc.control = 0;
-+    s->dispc.config = 0;
-+    s->dispc.capable = 0x161;
-+    s->dispc.timing[0] = 0;
-+    s->dispc.timing[1] = 0;
-+    s->dispc.timing[2] = 0;
-+    s->dispc.line = 0;
-+    s->dispc.bg[0] = 0;
-+    s->dispc.bg[1] = 0;
-+    s->dispc.trans[0] = 0;
-+    s->dispc.trans[1] = 0;
-+
-+    s->dispc.l[0].enable = 0;
-+    s->dispc.l[0].bpp = 0;
-+    s->dispc.l[0].addr[0] = 0;
-+    s->dispc.l[0].addr[1] = 0;
-+    s->dispc.l[0].addr[2] = 0;
-+    s->dispc.l[0].posx = 0;
-+    s->dispc.l[0].posy = 0;
-+    s->dispc.l[0].nx = 1;
-+    s->dispc.l[0].ny = 1;
-+    s->dispc.l[0].attr = 0;
-+    s->dispc.l[0].tresh = 0;
-+    s->dispc.l[0].rowinc = 1;
-+    s->dispc.l[0].colinc = 1;
-+    s->dispc.l[0].wininc = 0;
-+
-+    omap_rfbi_reset(s);
-+    omap_dispc_interrupt_update(s);
-+}
-+
-+static uint32_t omap_diss_read(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
-+    int offset = addr - s->diss_base;
-+
-+    switch (offset) {
-+    case 0x00:	/* DSS_REVISIONNUMBER */
-+        return 0x20;
-+
-+    case 0x10:	/* DSS_SYSCONFIG */
-+        return s->autoidle;
-+
-+    case 0x14:	/* DSS_SYSSTATUS */
-+        return 1;						/* RESETDONE */
-+
-+    case 0x40:	/* DSS_CONTROL */
-+        return s->control;
-+
-+    case 0x50:	/* DSS_PSA_LCD_REG_1 */
-+    case 0x54:	/* DSS_PSA_LCD_REG_2 */
-+    case 0x58:	/* DSS_PSA_VIDEO_REG */
-+        /* TODO: fake some values when appropriate s->control bits are set */
-+        return 0;
-+
-+    case 0x5c:	/* DSS_STATUS */
-+        return 1 + (s->control & 1);
-+
-+    default:
-+        break;
-+    }
-+    OMAP_BAD_REG(addr);
-+    return 0;
-+}
-+
-+static void omap_diss_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
-+    int offset = addr - s->diss_base;
-+
-+    switch (offset) {
-+    case 0x00:	/* DSS_REVISIONNUMBER */
-+    case 0x14:	/* DSS_SYSSTATUS */
-+    case 0x50:	/* DSS_PSA_LCD_REG_1 */
-+    case 0x54:	/* DSS_PSA_LCD_REG_2 */
-+    case 0x58:	/* DSS_PSA_VIDEO_REG */
-+    case 0x5c:	/* DSS_STATUS */
-+        OMAP_RO_REG(addr);
-+        break;
-+
-+    case 0x10:	/* DSS_SYSCONFIG */
-+        if (value & 2)						/* SOFTRESET */
-+            omap_dss_reset(s);
-+        s->autoidle = value & 1;
-+        break;
-+
-+    case 0x40:	/* DSS_CONTROL */
-+        s->control = value & 0x3dd;
-+        break;
-+
-+    default:
-+        OMAP_BAD_REG(addr);
-+    }
-+}
-+
-+static CPUReadMemoryFunc *omap_diss1_readfn[] = {
-+    omap_badwidth_read32,
-+    omap_badwidth_read32,
-+    omap_diss_read,
-+};
-+
-+static CPUWriteMemoryFunc *omap_diss1_writefn[] = {
-+    omap_badwidth_write32,
-+    omap_badwidth_write32,
-+    omap_diss_write,
-+};
-+
-+static uint32_t omap_disc_read(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
-+    int offset = addr - s->disc_base;
-+
-+    switch (offset) {
-+    case 0x000:	/* DISPC_REVISION */
-+        return 0x20;
-+
-+    case 0x010:	/* DISPC_SYSCONFIG */
-+        return s->dispc.idlemode;
-+
-+    case 0x014:	/* DISPC_SYSSTATUS */
-+        return 1;						/* RESETDONE */
-+
-+    case 0x018:	/* DISPC_IRQSTATUS */
-+        return s->dispc.irqst;
-+
-+    case 0x01c:	/* DISPC_IRQENABLE */
-+        return s->dispc.irqen;
-+
-+    case 0x040:	/* DISPC_CONTROL */
-+        return s->dispc.control;
-+
-+    case 0x044:	/* DISPC_CONFIG */
-+        return s->dispc.config;
-+
-+    case 0x048:	/* DISPC_CAPABLE */
-+        return s->dispc.capable;
-+
-+    case 0x04c:	/* DISPC_DEFAULT_COLOR0 */
-+        return s->dispc.bg[0];
-+    case 0x050:	/* DISPC_DEFAULT_COLOR1 */
-+        return s->dispc.bg[1];
-+    case 0x054:	/* DISPC_TRANS_COLOR0 */
-+        return s->dispc.trans[0];
-+    case 0x058:	/* DISPC_TRANS_COLOR1 */
-+        return s->dispc.trans[1];
-+
-+    case 0x05c:	/* DISPC_LINE_STATUS */
-+        return 0x7ff;
-+    case 0x060:	/* DISPC_LINE_NUMBER */
-+        return s->dispc.line;
-+
-+    case 0x064:	/* DISPC_TIMING_H */
-+        return s->dispc.timing[0];
-+    case 0x068:	/* DISPC_TIMING_V */
-+        return s->dispc.timing[1];
-+    case 0x06c:	/* DISPC_POL_FREQ */
-+        return s->dispc.timing[2];
-+    case 0x070:	/* DISPC_DIVISOR */
-+        return s->dispc.timing[3];
-+
-+    case 0x078:	/* DISPC_SIZE_DIG */
-+        return ((s->dig.ny - 1) << 16) | (s->dig.nx - 1);
-+    case 0x07c:	/* DISPC_SIZE_LCD */
-+        return ((s->lcd.ny - 1) << 16) | (s->lcd.nx - 1);
-+
-+    case 0x080:	/* DISPC_GFX_BA0 */
-+        return s->dispc.l[0].addr[0];
-+    case 0x084:	/* DISPC_GFX_BA1 */
-+        return s->dispc.l[0].addr[1];
-+    case 0x088:	/* DISPC_GFX_POSITION */
-+        return (s->dispc.l[0].posy << 16) | s->dispc.l[0].posx;
-+    case 0x08c:	/* DISPC_GFX_SIZE */
-+        return ((s->dispc.l[0].ny - 1) << 16) | (s->dispc.l[0].nx - 1);
-+    case 0x0a0:	/* DISPC_GFX_ATTRIBUTES */
-+        return s->dispc.l[0].attr;
-+    case 0x0a4:	/* DISPC_GFX_FIFO_TRESHOLD */
-+        return s->dispc.l[0].tresh;
-+    case 0x0a8:	/* DISPC_GFX_FIFO_SIZE_STATUS */
-+        return 256;
-+    case 0x0ac:	/* DISPC_GFX_ROW_INC */
-+        return s->dispc.l[0].rowinc;
-+    case 0x0b0:	/* DISPC_GFX_PIXEL_INC */
-+        return s->dispc.l[0].colinc;
-+    case 0x0b4:	/* DISPC_GFX_WINDOW_SKIP */
-+        return s->dispc.l[0].wininc;
-+    case 0x0b8:	/* DISPC_GFX_TABLE_BA */
-+        return s->dispc.l[0].addr[2];
-+
-+    case 0x0bc:	/* DISPC_VID1_BA0 */
-+    case 0x0c0:	/* DISPC_VID1_BA1 */
-+    case 0x0c4:	/* DISPC_VID1_POSITION */
-+    case 0x0c8:	/* DISPC_VID1_SIZE */
-+    case 0x0cc:	/* DISPC_VID1_ATTRIBUTES */
-+    case 0x0d0:	/* DISPC_VID1_FIFO_TRESHOLD */
-+    case 0x0d4:	/* DISPC_VID1_FIFO_SIZE_STATUS */
-+    case 0x0d8:	/* DISPC_VID1_ROW_INC */
-+    case 0x0dc:	/* DISPC_VID1_PIXEL_INC */
-+    case 0x0e0:	/* DISPC_VID1_FIR */
-+    case 0x0e4:	/* DISPC_VID1_PICTURE_SIZE */
-+    case 0x0e8:	/* DISPC_VID1_ACCU0 */
-+    case 0x0ec:	/* DISPC_VID1_ACCU1 */
-+    case 0x0f0 ... 0x140:	/* DISPC_VID1_FIR_COEF, DISPC_VID1_CONV_COEF */
-+    case 0x14c:	/* DISPC_VID2_BA0 */
-+    case 0x150:	/* DISPC_VID2_BA1 */
-+    case 0x154:	/* DISPC_VID2_POSITION */
-+    case 0x158:	/* DISPC_VID2_SIZE */
-+    case 0x15c:	/* DISPC_VID2_ATTRIBUTES */
-+    case 0x160:	/* DISPC_VID2_FIFO_TRESHOLD */
-+    case 0x164:	/* DISPC_VID2_FIFO_SIZE_STATUS */
-+    case 0x168:	/* DISPC_VID2_ROW_INC */
-+    case 0x16c:	/* DISPC_VID2_PIXEL_INC */
-+    case 0x170:	/* DISPC_VID2_FIR */
-+    case 0x174:	/* DISPC_VID2_PICTURE_SIZE */
-+    case 0x178:	/* DISPC_VID2_ACCU0 */
-+    case 0x17c:	/* DISPC_VID2_ACCU1 */
-+    case 0x180 ... 0x1d0:	/* DISPC_VID2_FIR_COEF, DISPC_VID2_CONV_COEF */
-+    case 0x1d4:	/* DISPC_DATA_CYCLE1 */
-+    case 0x1d8:	/* DISPC_DATA_CYCLE2 */
-+    case 0x1dc:	/* DISPC_DATA_CYCLE3 */
-+        return 0;
-+
-+    default:
-+        break;
-+    }
-+    OMAP_BAD_REG(addr);
-+    return 0;
-+}
-+
-+static void omap_disc_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
-+    int offset = addr - s->disc_base;
-+
-+    switch (offset) {
-+    case 0x010:	/* DISPC_SYSCONFIG */
-+        if (value & 2)						/* SOFTRESET */
-+            omap_dss_reset(s);
-+        s->dispc.idlemode = value & 0x301b;
-+        break;
-+
-+    case 0x018:	/* DISPC_IRQSTATUS */
-+        s->dispc.irqst &= ~value;
-+        omap_dispc_interrupt_update(s);
-+        break;
-+
-+    case 0x01c:	/* DISPC_IRQENABLE */
-+        s->dispc.irqen = value & 0xffff;
-+        omap_dispc_interrupt_update(s);
-+        break;
-+
-+    case 0x040:	/* DISPC_CONTROL */
-+        s->dispc.control = value & 0x07ff9fff;
-+        s->dig.enable = (value >> 1) & 1;
-+        s->lcd.enable = (value >> 0) & 1;
-+        if (value & (1 << 12))			/* OVERLAY_OPTIMIZATION */
-+            if (~((s->dispc.l[1].attr | s->dispc.l[2].attr) & 1))
-+                 fprintf(stderr, "%s: Overlay Optimization when no overlay "
-+                                 "region effectively exists leads to "
-+                                 "unpredictable behaviour!\n", __FUNCTION__);
-+        if (value & (1 << 6)) {				/* GODIGITAL */
-+            //// Shadows:
-+            //// s->dispc.config
-+            //// s->dispc.capable
-+            //// s->dispc.bg[0]
-+            //// s->dispc.bg[1]
-+            //// s->dispc.trans[0]
-+            //// s->dispc.trans[1]
-+            //// s->dispc.line
-+            //// s->dispc.timing[0]
-+            //// s->dispc.timing[1]
-+            //// s->dispc.timing[2]
-+            //// s->dispc.timing[3]
-+            //// s->lcd.nx
-+            //// s->lcd.ny
-+            //// s->dig.nx
-+            //// s->dig.ny
-+            //// s->dispc.l[0].addr[0]
-+            //// s->dispc.l[0].addr[1]
-+            //// s->dispc.l[0].addr[2]
-+            //// s->dispc.l[0].posx
-+            //// s->dispc.l[0].posy
-+            //// s->dispc.l[0].nx
-+            //// s->dispc.l[0].ny
-+            //// s->dispc.l[0].tresh
-+            //// s->dispc.l[0].rowinc
-+            //// s->dispc.l[0].colinc
-+            //// s->dispc.l[0].wininc
-+        }
-+        if (value & (1 << 5)) {				/* GOLCD */
-+        }
-+        s->dispc.invalidate = 1;
-+        break;
-+
-+    case 0x044:	/* DISPC_CONFIG */
-+        s->dispc.config = value & 0x3fff;
-+        //// bits 2:1 (LOADMODE) reset to 0 after set to 1 and palette loaded
-+        //// bits 2:1 (LOADMODE) reset to 2 after set to 3 and palette loaded
-+        s->dispc.invalidate = 1;
-+        break;
-+
-+    case 0x048:	/* DISPC_CAPABLE */
-+        s->dispc.capable = value & 0x3ff;
-+        break;
-+
-+    case 0x04c:	/* DISPC_DEFAULT_COLOR0 */
-+        s->dispc.bg[0] = value & 0xffffff;
-+        s->dispc.invalidate = 1;
-+        break;
-+    case 0x050:	/* DISPC_DEFAULT_COLOR1 */
-+        s->dispc.bg[1] = value & 0xffffff;
-+        s->dispc.invalidate = 1;
-+        break;
-+    case 0x054:	/* DISPC_TRANS_COLOR0 */
-+        s->dispc.trans[0] = value & 0xffffff;
-+        s->dispc.invalidate = 1;
-+        break;
-+    case 0x058:	/* DISPC_TRANS_COLOR1 */
-+        s->dispc.trans[1] = value & 0xffffff;
-+        s->dispc.invalidate = 1;
-+        break;
-+
-+    case 0x060:	/* DISPC_LINE_NUMBER */
-+        s->dispc.line = value & 0x7ff;
-+        break;
-+
-+    case 0x064:	/* DISPC_TIMING_H */
-+        s->dispc.timing[0] = value & 0x0ff0ff3f;
-+        break;
-+    case 0x068:	/* DISPC_TIMING_V */
-+        s->dispc.timing[1] = value & 0x0ff0ff3f;
-+        break;
-+    case 0x06c:	/* DISPC_POL_FREQ */
-+        s->dispc.timing[2] = value & 0x0003ffff;
-+        break;
-+    case 0x070:	/* DISPC_DIVISOR */
-+        s->dispc.timing[3] = value & 0x00ff00ff;
-+        break;
-+
-+    case 0x078:	/* DISPC_SIZE_DIG */
-+        s->dig.nx = ((value >>  0) & 0x7ff) + 1;		/* PPL */
-+        s->dig.ny = ((value >> 16) & 0x7ff) + 1;		/* LPP */
-+        s->dispc.invalidate = 1;
-+        break;
-+    case 0x07c:	/* DISPC_SIZE_LCD */
-+        s->lcd.nx = ((value >>  0) & 0x7ff) + 1;		/* PPL */
-+        s->lcd.ny = ((value >> 16) & 0x7ff) + 1;		/* LPP */
-+        s->dispc.invalidate = 1;
-+        break;
-+    case 0x080:	/* DISPC_GFX_BA0 */
-+        s->dispc.l[0].addr[0] = (target_phys_addr_t) value;
-+        s->dispc.invalidate = 1;
-+        break;
-+    case 0x084:	/* DISPC_GFX_BA1 */
-+        s->dispc.l[0].addr[1] = (target_phys_addr_t) value;
-+        s->dispc.invalidate = 1;
-+        break;
-+    case 0x088:	/* DISPC_GFX_POSITION */
-+        s->dispc.l[0].posx = ((value >>  0) & 0x7ff);		/* GFXPOSX */
-+        s->dispc.l[0].posy = ((value >> 16) & 0x7ff);		/* GFXPOSY */
-+        s->dispc.invalidate = 1;
-+        break;
-+    case 0x08c:	/* DISPC_GFX_SIZE */
-+        s->dispc.l[0].nx = ((value >>  0) & 0x7ff) + 1;		/* GFXSIZEX */
-+        s->dispc.l[0].ny = ((value >> 16) & 0x7ff) + 1;		/* GFXSIZEY */
-+        s->dispc.invalidate = 1;
-+        break;
-+    case 0x0a0:	/* DISPC_GFX_ATTRIBUTES */
-+        s->dispc.l[0].attr = value & 0x7ff;
-+        if (value & (3 << 9))
-+            fprintf(stderr, "%s: Big-endian pixel format not supported\n",
-+                            __FUNCTION__);
-+        s->dispc.l[0].enable = value & 1;
-+        s->dispc.l[0].bpp = (value >> 1) & 0xf;
-+        s->dispc.invalidate = 1;
-+        break;
-+    case 0x0a4:	/* DISPC_GFX_FIFO_TRESHOLD */
-+        s->dispc.l[0].tresh = value & 0x01ff01ff;
-+        break;
-+    case 0x0ac:	/* DISPC_GFX_ROW_INC */
-+        s->dispc.l[0].rowinc = value;
-+        s->dispc.invalidate = 1;
-+        break;
-+    case 0x0b0:	/* DISPC_GFX_PIXEL_INC */
-+        s->dispc.l[0].colinc = value;
-+        s->dispc.invalidate = 1;
-+        break;
-+    case 0x0b4:	/* DISPC_GFX_WINDOW_SKIP */
-+        s->dispc.l[0].wininc = value;
-+        break;
-+    case 0x0b8:	/* DISPC_GFX_TABLE_BA */
-+        s->dispc.l[0].addr[2] = (target_phys_addr_t) value;
-+        s->dispc.invalidate = 1;
-+        break;
-+
-+    case 0x0bc:	/* DISPC_VID1_BA0 */
-+    case 0x0c0:	/* DISPC_VID1_BA1 */
-+    case 0x0c4:	/* DISPC_VID1_POSITION */
-+    case 0x0c8:	/* DISPC_VID1_SIZE */
-+    case 0x0cc:	/* DISPC_VID1_ATTRIBUTES */
-+    case 0x0d0:	/* DISPC_VID1_FIFO_TRESHOLD */
-+    case 0x0d8:	/* DISPC_VID1_ROW_INC */
-+    case 0x0dc:	/* DISPC_VID1_PIXEL_INC */
-+    case 0x0e0:	/* DISPC_VID1_FIR */
-+    case 0x0e4:	/* DISPC_VID1_PICTURE_SIZE */
-+    case 0x0e8:	/* DISPC_VID1_ACCU0 */
-+    case 0x0ec:	/* DISPC_VID1_ACCU1 */
-+    case 0x0f0 ... 0x140:	/* DISPC_VID1_FIR_COEF, DISPC_VID1_CONV_COEF */
-+    case 0x14c:	/* DISPC_VID2_BA0 */
-+    case 0x150:	/* DISPC_VID2_BA1 */
-+    case 0x154:	/* DISPC_VID2_POSITION */
-+    case 0x158:	/* DISPC_VID2_SIZE */
-+    case 0x15c:	/* DISPC_VID2_ATTRIBUTES */
-+    case 0x160:	/* DISPC_VID2_FIFO_TRESHOLD */
-+    case 0x168:	/* DISPC_VID2_ROW_INC */
-+    case 0x16c:	/* DISPC_VID2_PIXEL_INC */
-+    case 0x170:	/* DISPC_VID2_FIR */
-+    case 0x174:	/* DISPC_VID2_PICTURE_SIZE */
-+    case 0x178:	/* DISPC_VID2_ACCU0 */
-+    case 0x17c:	/* DISPC_VID2_ACCU1 */
-+    case 0x180 ... 0x1d0:	/* DISPC_VID2_FIR_COEF, DISPC_VID2_CONV_COEF */
-+    case 0x1d4:	/* DISPC_DATA_CYCLE1 */
-+    case 0x1d8:	/* DISPC_DATA_CYCLE2 */
-+    case 0x1dc:	/* DISPC_DATA_CYCLE3 */
-+        break;
-+
-+    default:
-+        OMAP_BAD_REG(addr);
-+    }
-+}
-+
-+static CPUReadMemoryFunc *omap_disc1_readfn[] = {
-+    omap_badwidth_read32,
-+    omap_badwidth_read32,
-+    omap_disc_read,
-+};
-+
-+static CPUWriteMemoryFunc *omap_disc1_writefn[] = {
-+    omap_badwidth_write32,
-+    omap_badwidth_write32,
-+    omap_disc_write,
-+};
-+
-+static void *omap_rfbi_get_buffer(struct omap_dss_s *s)
-+{
-+    target_phys_addr_t fb;
-+    uint32_t pd;
-+
-+    /* TODO */
-+    fb = s->dispc.l[0].addr[0];
-+
-+    pd = cpu_get_physical_page_desc(fb);
-+    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM)
-+        /* TODO */
-+        cpu_abort(cpu_single_env, "%s: framebuffer outside RAM!\n",
-+                        __FUNCTION__);
-+    else
-+        return phys_ram_base +
-+                (pd & TARGET_PAGE_MASK) +
-+                (fb & ~TARGET_PAGE_MASK);
-+}
-+
-+static void omap_rfbi_transfer_stop(struct omap_dss_s *s)
-+{
-+    if (!s->rfbi.busy)
-+        return;
-+
-+    /* TODO: in non-Bypass mode we probably need to just deassert the DRQ.  */
-+
-+    s->rfbi.busy = 0;
-+}
-+
-+static void omap_rfbi_transfer_start(struct omap_dss_s *s)
-+{
-+    void *data;
-+    size_t len;
-+    int pitch;
-+
-+    if (!s->rfbi.enable || s->rfbi.busy)
-+        return;
-+
-+    if (s->rfbi.control & (1 << 1)) {				/* BYPASS */
-+        /* TODO: in non-Bypass mode we probably need to just assert the
-+         * DRQ and wait for DMA to write the pixels.  */
-+        fprintf(stderr, "%s: Bypass mode unimplemented\n", __FUNCTION__);
-+        return;
-+    }
-+
-+    if (!(s->dispc.control & (1 << 11)))			/* RFBIMODE */
-+        return;
-+    /* TODO: check that LCD output is enabled in DISPC.  */
-+
-+    s->rfbi.busy = 1;
-+
-+    data = omap_rfbi_get_buffer(s);
-+
-+    /* TODO bpp */
-+    len = s->rfbi.pixels * 2;
-+    s->rfbi.pixels = 0;
-+
-+    /* TODO: negative values */
-+    pitch = s->dispc.l[0].nx + (s->dispc.l[0].rowinc - 1) / 2;
-+
-+    if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
-+        s->rfbi.chip[0]->block(s->rfbi.chip[0]->opaque, 1, data, len, pitch);
-+    if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
-+        s->rfbi.chip[1]->block(s->rfbi.chip[1]->opaque, 1, data, len, pitch);
-+
-+    omap_rfbi_transfer_stop(s);
-+
-+    /* TODO */
-+    s->dispc.irqst |= 1;					/* FRAMEDONE */
-+    omap_dispc_interrupt_update(s);
-+}
-+
-+static uint32_t omap_rfbi_read(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
-+    int offset = addr - s->rfbi_base;
-+
-+    switch (offset) {
-+    case 0x00:	/* RFBI_REVISION */
-+        return 0x10;
-+
-+    case 0x10:	/* RFBI_SYSCONFIG */
-+        return s->rfbi.idlemode;
-+
-+    case 0x14:	/* RFBI_SYSSTATUS */
-+        return 1 | (s->rfbi.busy << 8);				/* RESETDONE */
-+
-+    case 0x40:	/* RFBI_CONTROL */
-+        return s->rfbi.control;
-+
-+    case 0x44:	/* RFBI_PIXELCNT */
-+        return s->rfbi.pixels;
-+
-+    case 0x48:	/* RFBI_LINE_NUMBER */
-+        return s->rfbi.skiplines;
-+
-+    case 0x58:	/* RFBI_READ */
-+    case 0x5c:	/* RFBI_STATUS */
-+        return s->rfbi.rxbuf;
-+
-+    case 0x60:	/* RFBI_CONFIG0 */
-+        return s->rfbi.config[0];
-+    case 0x64:	/* RFBI_ONOFF_TIME0 */
-+        return s->rfbi.time[0];
-+    case 0x68:	/* RFBI_CYCLE_TIME0 */
-+        return s->rfbi.time[1];
-+    case 0x6c:	/* RFBI_DATA_CYCLE1_0 */
-+        return s->rfbi.data[0];
-+    case 0x70:	/* RFBI_DATA_CYCLE2_0 */
-+        return s->rfbi.data[1];
-+    case 0x74:	/* RFBI_DATA_CYCLE3_0 */
-+        return s->rfbi.data[2];
-+
-+    case 0x78:	/* RFBI_CONFIG1 */
-+        return s->rfbi.config[1];
-+    case 0x7c:	/* RFBI_ONOFF_TIME1 */
-+        return s->rfbi.time[2];
-+    case 0x80:	/* RFBI_CYCLE_TIME1 */
-+        return s->rfbi.time[3];
-+    case 0x84:	/* RFBI_DATA_CYCLE1_1 */
-+        return s->rfbi.data[3];
-+    case 0x88:	/* RFBI_DATA_CYCLE2_1 */
-+        return s->rfbi.data[4];
-+    case 0x8c:	/* RFBI_DATA_CYCLE3_1 */
-+        return s->rfbi.data[5];
-+
-+    case 0x90:	/* RFBI_VSYNC_WIDTH */
-+        return s->rfbi.vsync;
-+    case 0x94:	/* RFBI_HSYNC_WIDTH */
-+        return s->rfbi.hsync;
-+    }
-+    OMAP_BAD_REG(addr);
-+    return 0;
-+}
-+
-+static void omap_rfbi_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
-+    int offset = addr - s->rfbi_base;
-+
-+    switch (offset) {
-+    case 0x10:	/* RFBI_SYSCONFIG */
-+        if (value & 2)						/* SOFTRESET */
-+            omap_rfbi_reset(s);
-+        s->rfbi.idlemode = value & 0x19;
-+        break;
-+
-+    case 0x40:	/* RFBI_CONTROL */
-+        s->rfbi.control = value & 0xf;
-+        s->rfbi.enable = value & 1;
-+        if (value & (1 << 4) &&					/* ITE */
-+                        !(s->rfbi.config[0] & s->rfbi.config[1] & 0xc))
-+            omap_rfbi_transfer_start(s);
-+        break;
-+
-+    case 0x44:	/* RFBI_PIXELCNT */
-+        s->rfbi.pixels = value;
-+        break;
-+
-+    case 0x48:	/* RFBI_LINE_NUMBER */
-+        s->rfbi.skiplines = value & 0x7ff;
-+        break;
-+
-+    case 0x4c:	/* RFBI_CMD */
-+        if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
-+            s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 0, value & 0xffff);
-+        if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
-+            s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 0, value & 0xffff);
-+        break;
-+    case 0x50:	/* RFBI_PARAM */
-+        if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
-+            s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
-+        if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
-+            s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
-+        break;
-+    case 0x54:	/* RFBI_DATA */
-+        /* TODO: take into account the format set up in s->rfbi.config[?] and
-+         * s->rfbi.data[?], but special-case the most usual scenario so that
-+         * speed doesn't suffer.  */
-+        if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) {
-+            s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
-+            s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value >> 16);
-+        }
-+        if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) {
-+            s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
-+            s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value >> 16);
-+        }
-+        if (!-- s->rfbi.pixels)
-+            omap_rfbi_transfer_stop(s);
-+        break;
-+    case 0x58:	/* RFBI_READ */
-+        if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
-+            s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1);
-+        else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
-+            s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1);
-+        if (!-- s->rfbi.pixels)
-+            omap_rfbi_transfer_stop(s);
-+        break;
-+
-+    case 0x5c:	/* RFBI_STATUS */
-+        if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
-+            s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0);
-+        else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
-+            s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0);
-+        if (!-- s->rfbi.pixels)
-+            omap_rfbi_transfer_stop(s);
-+        break;
-+
-+    case 0x60:	/* RFBI_CONFIG0 */
-+        s->rfbi.config[0] = value & 0x003f1fff;
-+        break;
-+
-+    case 0x64:	/* RFBI_ONOFF_TIME0 */
-+        s->rfbi.time[0] = value & 0x3fffffff;
-+        break;
-+    case 0x68:	/* RFBI_CYCLE_TIME0 */
-+        s->rfbi.time[1] = value & 0x0fffffff;
-+        break;
-+    case 0x6c:	/* RFBI_DATA_CYCLE1_0 */
-+        s->rfbi.data[0] = value & 0x0f1f0f1f;
-+        break;
-+    case 0x70:	/* RFBI_DATA_CYCLE2_0 */
-+        s->rfbi.data[1] = value & 0x0f1f0f1f;
-+        break;
-+    case 0x74:	/* RFBI_DATA_CYCLE3_0 */
-+        s->rfbi.data[2] = value & 0x0f1f0f1f;
-+        break;
-+    case 0x78:	/* RFBI_CONFIG1 */
-+        s->rfbi.config[1] = value & 0x003f1fff;
-+        break;
-+
-+    case 0x7c:	/* RFBI_ONOFF_TIME1 */
-+        s->rfbi.time[2] = value & 0x3fffffff;
-+        break;
-+    case 0x80:	/* RFBI_CYCLE_TIME1 */
-+        s->rfbi.time[3] = value & 0x0fffffff;
-+        break;
-+    case 0x84:	/* RFBI_DATA_CYCLE1_1 */
-+        s->rfbi.data[3] = value & 0x0f1f0f1f;
-+        break;
-+    case 0x88:	/* RFBI_DATA_CYCLE2_1 */
-+        s->rfbi.data[4] = value & 0x0f1f0f1f;
-+        break;
-+    case 0x8c:	/* RFBI_DATA_CYCLE3_1 */
-+        s->rfbi.data[5] = value & 0x0f1f0f1f;
-+        break;
-+
-+    case 0x90:	/* RFBI_VSYNC_WIDTH */
-+        s->rfbi.vsync = value & 0xffff;
-+        break;
-+    case 0x94:	/* RFBI_HSYNC_WIDTH */
-+        s->rfbi.hsync = value & 0xffff;
-+        break;
-+
-+    default:
-+        OMAP_BAD_REG(addr);
-+    }
-+}
-+
-+static CPUReadMemoryFunc *omap_rfbi1_readfn[] = {
-+    omap_badwidth_read32,
-+    omap_badwidth_read32,
-+    omap_rfbi_read,
-+};
-+
-+static CPUWriteMemoryFunc *omap_rfbi1_writefn[] = {
-+    omap_badwidth_write32,
-+    omap_badwidth_write32,
-+    omap_rfbi_write,
-+};
-+
-+static uint32_t omap_venc_read(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
-+    int offset = addr - s->venc_base;
-+
-+    switch (offset) {
-+    case 0x00:	/* REV_ID */
-+    case 0x04:	/* STATUS */
-+    case 0x08:	/* F_CONTROL */
-+    case 0x10:	/* VIDOUT_CTRL */
-+    case 0x14:	/* SYNC_CTRL */
-+    case 0x1c:	/* LLEN */
-+    case 0x20:	/* FLENS */
-+    case 0x24:	/* HFLTR_CTRL */
-+    case 0x28:	/* CC_CARR_WSS_CARR */
-+    case 0x2c:	/* C_PHASE */
-+    case 0x30:	/* GAIN_U */
-+    case 0x34:	/* GAIN_V */
-+    case 0x38:	/* GAIN_Y */
-+    case 0x3c:	/* BLACK_LEVEL */
-+    case 0x40:	/* BLANK_LEVEL */
-+    case 0x44:	/* X_COLOR */
-+    case 0x48:	/* M_CONTROL */
-+    case 0x4c:	/* BSTAMP_WSS_DATA */
-+    case 0x50:	/* S_CARR */
-+    case 0x54:	/* LINE21 */
-+    case 0x58:	/* LN_SEL */
-+    case 0x5c:	/* L21__WC_CTL */
-+    case 0x60:	/* HTRIGGER_VTRIGGER */
-+    case 0x64:	/* SAVID__EAVID */
-+    case 0x68:	/* FLEN__FAL */
-+    case 0x6c:	/* LAL__PHASE_RESET */
-+    case 0x70:	/* HS_INT_START_STOP_X */
-+    case 0x74:	/* HS_EXT_START_STOP_X */
-+    case 0x78:	/* VS_INT_START_X */
-+    case 0x7c:	/* VS_INT_STOP_X__VS_INT_START_Y */
-+    case 0x80:	/* VS_INT_STOP_Y__VS_INT_START_X */
-+    case 0x84:	/* VS_EXT_STOP_X__VS_EXT_START_Y */
-+    case 0x88:	/* VS_EXT_STOP_Y */
-+    case 0x90:	/* AVID_START_STOP_X */
-+    case 0x94:	/* AVID_START_STOP_Y */
-+    case 0xa0:	/* FID_INT_START_X__FID_INT_START_Y */
-+    case 0xa4:	/* FID_INT_OFFSET_Y__FID_EXT_START_X */
-+    case 0xa8:	/* FID_EXT_START_Y__FID_EXT_OFFSET_Y */
-+    case 0xb0:	/* TVDETGP_INT_START_STOP_X */
-+    case 0xb4:	/* TVDETGP_INT_START_STOP_Y */
-+    case 0xb8:	/* GEN_CTRL */
-+    case 0xc4:	/* DAC_TST__DAC_A */
-+    case 0xc8:	/* DAC_B__DAC_C */
-+        return 0;
-+
-+    default:
-+        break;
-+    }
-+    OMAP_BAD_REG(addr);
-+    return 0;
-+}
-+
-+static void omap_venc_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
-+    int offset = addr - s->venc_base;
-+
-+    switch (offset) {
-+    case 0x08:	/* F_CONTROL */
-+    case 0x10:	/* VIDOUT_CTRL */
-+    case 0x14:	/* SYNC_CTRL */
-+    case 0x1c:	/* LLEN */
-+    case 0x20:	/* FLENS */
-+    case 0x24:	/* HFLTR_CTRL */
-+    case 0x28:	/* CC_CARR_WSS_CARR */
-+    case 0x2c:	/* C_PHASE */
-+    case 0x30:	/* GAIN_U */
-+    case 0x34:	/* GAIN_V */
-+    case 0x38:	/* GAIN_Y */
-+    case 0x3c:	/* BLACK_LEVEL */
-+    case 0x40:	/* BLANK_LEVEL */
-+    case 0x44:	/* X_COLOR */
-+    case 0x48:	/* M_CONTROL */
-+    case 0x4c:	/* BSTAMP_WSS_DATA */
-+    case 0x50:	/* S_CARR */
-+    case 0x54:	/* LINE21 */
-+    case 0x58:	/* LN_SEL */
-+    case 0x5c:	/* L21__WC_CTL */
-+    case 0x60:	/* HTRIGGER_VTRIGGER */
-+    case 0x64:	/* SAVID__EAVID */
-+    case 0x68:	/* FLEN__FAL */
-+    case 0x6c:	/* LAL__PHASE_RESET */
-+    case 0x70:	/* HS_INT_START_STOP_X */
-+    case 0x74:	/* HS_EXT_START_STOP_X */
-+    case 0x78:	/* VS_INT_START_X */
-+    case 0x7c:	/* VS_INT_STOP_X__VS_INT_START_Y */
-+    case 0x80:	/* VS_INT_STOP_Y__VS_INT_START_X */
-+    case 0x84:	/* VS_EXT_STOP_X__VS_EXT_START_Y */
-+    case 0x88:	/* VS_EXT_STOP_Y */
-+    case 0x90:	/* AVID_START_STOP_X */
-+    case 0x94:	/* AVID_START_STOP_Y */
-+    case 0xa0:	/* FID_INT_START_X__FID_INT_START_Y */
-+    case 0xa4:	/* FID_INT_OFFSET_Y__FID_EXT_START_X */
-+    case 0xa8:	/* FID_EXT_START_Y__FID_EXT_OFFSET_Y */
-+    case 0xb0:	/* TVDETGP_INT_START_STOP_X */
-+    case 0xb4:	/* TVDETGP_INT_START_STOP_Y */
-+    case 0xb8:	/* GEN_CTRL */
-+    case 0xc4:	/* DAC_TST__DAC_A */
-+    case 0xc8:	/* DAC_B__DAC_C */
-+        break;
-+
-+    default:
-+        OMAP_BAD_REG(addr);
-+    }
-+}
-+
-+static CPUReadMemoryFunc *omap_venc1_readfn[] = {
-+    omap_badwidth_read32,
-+    omap_badwidth_read32,
-+    omap_venc_read,
-+};
-+
-+static CPUWriteMemoryFunc *omap_venc1_writefn[] = {
-+    omap_badwidth_write32,
-+    omap_badwidth_write32,
-+    omap_venc_write,
-+};
-+
-+static uint32_t omap_im3_read(void *opaque, target_phys_addr_t addr)
-+{
-+    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
-+    int offset = addr - s->im3_base;
-+
-+    switch (offset) {
-+    case 0x0a8:	/* SBIMERRLOGA */
-+    case 0x0b0:	/* SBIMERRLOG */
-+    case 0x190:	/* SBIMSTATE */
-+    case 0x198:	/* SBTMSTATE_L */
-+    case 0x19c:	/* SBTMSTATE_H */
-+    case 0x1a8:	/* SBIMCONFIG_L */
-+    case 0x1ac:	/* SBIMCONFIG_H */
-+    case 0x1f8:	/* SBID_L */
-+    case 0x1fc:	/* SBID_H */
-+        return 0;
-+
-+    default:
-+        break;
-+    }
-+    OMAP_BAD_REG(addr);
-+    return 0;
-+}
-+
-+static void omap_im3_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct omap_dss_s *s = (struct omap_dss_s *) opaque;
-+    int offset = addr - s->im3_base;
-+
-+    switch (offset) {
-+    case 0x0b0:	/* SBIMERRLOG */
-+    case 0x190:	/* SBIMSTATE */
-+    case 0x198:	/* SBTMSTATE_L */
-+    case 0x19c:	/* SBTMSTATE_H */
-+    case 0x1a8:	/* SBIMCONFIG_L */
-+    case 0x1ac:	/* SBIMCONFIG_H */
-+        break;
-+
-+    default:
-+        OMAP_BAD_REG(addr);
-+    }
-+}
-+
-+static CPUReadMemoryFunc *omap_im3_readfn[] = {
-+    omap_badwidth_read32,
-+    omap_badwidth_read32,
-+    omap_im3_read,
-+};
-+
-+static CPUWriteMemoryFunc *omap_im3_writefn[] = {
-+    omap_badwidth_write32,
-+    omap_badwidth_write32,
-+    omap_im3_write,
-+};
-+
-+struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
-+                target_phys_addr_t l3_base, DisplayState *ds,
-+                qemu_irq irq, qemu_irq drq,
-+                omap_clk fck1, omap_clk fck2, omap_clk ck54m,
-+                omap_clk ick1, omap_clk ick2)
-+{
-+    int iomemtype[5];
-+    struct omap_dss_s *s = (struct omap_dss_s *)
-+            qemu_mallocz(sizeof(struct omap_dss_s));
-+
-+    s->irq = irq;
-+    s->drq = drq;
-+    s->state = ds;
-+    omap_dss_reset(s);
-+
-+    iomemtype[0] = cpu_register_io_memory(0, omap_diss1_readfn,
-+                    omap_diss1_writefn, s);
-+    iomemtype[1] = cpu_register_io_memory(0, omap_disc1_readfn,
-+                    omap_disc1_writefn, s);
-+    iomemtype[2] = cpu_register_io_memory(0, omap_rfbi1_readfn,
-+                    omap_rfbi1_writefn, s);
-+    iomemtype[3] = cpu_register_io_memory(0, omap_venc1_readfn,
-+                    omap_venc1_writefn, s);
-+    iomemtype[4] = cpu_register_io_memory(0, omap_im3_readfn,
-+                    omap_im3_writefn, s);
-+    s->diss_base = omap_l4_attach(ta, 0, iomemtype[0]);
-+    s->disc_base = omap_l4_attach(ta, 1, iomemtype[1]);
-+    s->rfbi_base = omap_l4_attach(ta, 2, iomemtype[2]);
-+    s->venc_base = omap_l4_attach(ta, 3, iomemtype[3]);
-+    s->im3_base = l3_base;
-+    cpu_register_physical_memory(s->im3_base, 0x1000, iomemtype[4]);
-+
-+#if 0
-+    if (ds)
-+        graphic_console_init(ds, omap_update_display,
-+                        omap_invalidate_display, omap_screen_dump, s);
-+#endif
-+
-+    return s;
-+}
-+
-+void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip)
-+{
-+    if (cs < 0 || cs > 1)
-+        cpu_abort(cpu_single_env, "%s: wrong CS %i\n", __FUNCTION__, cs);
-+    s->rfbi.chip[cs] = chip;
-+}
-diff --git a/hw/omap_i2c.c b/hw/omap_i2c.c
-index de63309..9915676 100644
---- a/hw/omap_i2c.c
-+++ b/hw/omap_i2c.c
-@@ -150,6 +150,8 @@ static void omap_i2c_fifo_run(struct omap_i2c_s *s)
-             }
-             if (ack && s->count_cur)
-                 s->stat |= 1 << 4;				/* XRDY */
-+            else
-+                s->stat &= ~(1 << 4);				/* XRDY */
-             if (!s->count_cur) {
-                 s->stat |= 1 << 2;				/* ARDY */
-                 s->control &= ~(1 << 10);			/* MST */
-@@ -161,6 +163,8 @@ static void omap_i2c_fifo_run(struct omap_i2c_s *s)
-             }
-             if (s->rxlen)
-                 s->stat |= 1 << 3;				/* RRDY */
-+            else
-+                s->stat &= ~(1 << 3);				/* RRDY */
-         }
-         if (!s->count_cur) {
-             if ((s->control >> 1) & 1) {			/* STP */
-@@ -321,7 +325,8 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
-             return;
-         }
- 
--        s->stat &= ~(value & 0x3f);
-+        /* RRDY and XRDY are reset by hardware. (in all versions???) */
-+        s->stat &= ~(value & 0x27);
-         omap_i2c_interrupts_update(s);
-         break;
- 
-@@ -376,11 +381,13 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
-             break;
-         }
-         if ((value & (1 << 15)) && !(value & (1 << 10))) {	/* MST */
--            printf("%s: I^2C slave mode not supported\n", __FUNCTION__);
-+            fprintf(stderr, "%s: I^2C slave mode not supported\n",
-+                            __FUNCTION__);
-             break;
-         }
-         if ((value & (1 << 15)) && value & (1 << 8)) {		/* XA */
--            printf("%s: 10-bit addressing mode not supported\n", __FUNCTION__);
-+            fprintf(stderr, "%s: 10-bit addressing mode not supported\n",
-+                            __FUNCTION__);
-             break;
-         }
-         if ((value & (1 << 15)) && value & (1 << 0)) {		/* STT */
-@@ -427,7 +434,7 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
-                 omap_i2c_interrupts_update(s);
-             }
-         if (value & (1 << 15))					/* ST_EN */
--            printf("%s: System Test not supported\n", __FUNCTION__);
-+            fprintf(stderr, "%s: System Test not supported\n", __FUNCTION__);
-         break;
- 
-     default:
-diff --git a/hw/omap_mmc.c b/hw/omap_mmc.c
-index 6fbbb84..e46289a 100644
---- a/hw/omap_mmc.c
-+++ b/hw/omap_mmc.c
-@@ -26,19 +26,24 @@ struct omap_mmc_s {
-     target_phys_addr_t base;
-     qemu_irq irq;
-     qemu_irq *dma;
-+    qemu_irq coverswitch;
-     omap_clk clk;
-     SDState *card;
-     uint16_t last_cmd;
-     uint16_t sdio;
-     uint16_t rsp[8];
-     uint32_t arg;
-+    int lines;
-     int dw;
-     int mode;
-     int enable;
-+    int be;
-+    int rev;
-     uint16_t status;
-     uint16_t mask;
-     uint8_t cto;
-     uint16_t dto;
-+    int clkdiv;
-     uint16_t fifo[32];
-     int fifo_start;
-     int fifo_len;
-@@ -53,6 +58,11 @@ struct omap_mmc_s {
- 
-     int ddir;
-     int transfer;
-+
-+    int cdet_wakeup;
-+    int cdet_enable;
-+    int cdet_state;
-+    qemu_irq cdet;
- };
- 
- static void omap_mmc_interrupts_update(struct omap_mmc_s *s)
-@@ -107,6 +117,11 @@ static void omap_mmc_command(struct omap_mmc_s *host, int cmd, int dir,
-     struct sd_request_s request;
-     uint8_t response[16];
- 
-+    if (init && cmd == 0) {
-+        host->status |= 0x0001;
-+        return;
-+    }
-+
-     if (resptype == sd_r1 && busy)
-         resptype = sd_r1b;
- 
-@@ -265,6 +280,34 @@ static void omap_mmc_update(void *opaque)
-     omap_mmc_interrupts_update(s);
- }
- 
-+void omap_mmc_reset(struct omap_mmc_s *host)
-+{
-+    host->last_cmd = 0;
-+    memset(host->rsp, 0, sizeof(host->rsp));
-+    host->arg = 0;
-+    host->dw = 0;
-+    host->mode = 0;
-+    host->enable = 0;
-+    host->status = 0;
-+    host->mask = 0;
-+    host->cto = 0;
-+    host->dto = 0;
-+    host->fifo_len = 0;
-+    host->blen = 0;
-+    host->blen_counter = 0;
-+    host->nblk = 0;
-+    host->nblk_counter = 0;
-+    host->tx_dma = 0;
-+    host->rx_dma = 0;
-+    host->ae_level = 0x00;
-+    host->af_level = 0x1f;
-+    host->transfer = 0;
-+    host->cdet_wakeup = 0;
-+    host->cdet_enable = 0;
-+    qemu_set_irq(host->coverswitch, host->cdet_state);
-+    host->clkdiv = 0;
-+}
-+
- static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset)
- {
-     uint16_t i;
-@@ -282,7 +325,8 @@ static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset)
-         return s->arg >> 16;
- 
-     case 0x0c:	/* MMC_CON */
--        return (s->dw << 15) | (s->mode << 12) | (s->enable << 11);
-+        return (s->dw << 15) | (s->mode << 12) | (s->enable << 11) | 
-+                (s->be << 10) | s->clkdiv;
- 
-     case 0x10:	/* MMC_STAT */
-         return s->status;
-@@ -324,12 +368,12 @@ static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset)
-     case 0x30:	/* MMC_SPI */
-         return 0x0000;
-     case 0x34:	/* MMC_SDIO */
--        return s->sdio;
-+        return (s->cdet_wakeup << 2) | (s->cdet_enable) | s->sdio;
-     case 0x38:	/* MMC_SYST */
-         return 0x0000;
- 
-     case 0x3c:	/* MMC_REV */
--        return 0x0001;
-+        return s->rev;
- 
-     case 0x40:	/* MMC_RSP0 */
-     case 0x44:	/* MMC_RSP1 */
-@@ -340,6 +384,13 @@ static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset)
-     case 0x58:	/* MMC_RSP6 */
-     case 0x5c:	/* MMC_RSP7 */
-         return s->rsp[(offset - 0x40) >> 2];
-+
-+    /* OMAP2-specific */
-+    case 0x60:	/* MMC_IOSR */
-+    case 0x64:	/* MMC_SYSC */
-+        return 0;
-+    case 0x68:	/* MMC_SYSS */
-+        return 1;						/* RSTD */
-     }
- 
-     OMAP_BAD_REG(offset);
-@@ -383,10 +434,16 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset,
-         s->dw = (value >> 15) & 1;
-         s->mode = (value >> 12) & 3;
-         s->enable = (value >> 11) & 1;
-+        s->be = (value >> 10) & 1;
-+        s->clkdiv = (value >> 0) & (s->rev >= 2 ? 0x3ff : 0xff);
-         if (s->mode != 0)
-             printf("SD mode %i unimplemented!\n", s->mode);
--        if (s->dw != 0)
-+        if (s->be != 0)
-+            printf("SD FIFO byte sex unimplemented!\n");
-+        if (s->dw != 0 && s->lines < 4)
-             printf("4-bit SD bus enabled\n");
-+        if (!s->enable)
-+            omap_mmc_reset(s);
-         break;
- 
-     case 0x10:	/* MMC_STAT */
-@@ -395,13 +452,13 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset,
-         break;
- 
-     case 0x14:	/* MMC_IE */
--        s->mask = value;
-+        s->mask = value & 0x7fff;
-         omap_mmc_interrupts_update(s);
-         break;
- 
-     case 0x18:	/* MMC_CTO */
-         s->cto = value & 0xff;
--        if (s->cto > 0xfd)
-+        if (s->cto > 0xfd && s->rev <= 1)
-             printf("MMC: CTO of 0xff and 0xfe cannot be used!\n");
-         break;
- 
-@@ -446,10 +503,12 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset,
-         break;
- 
-     /* SPI, SDIO and TEST modes unimplemented */
--    case 0x30:	/* MMC_SPI */
-+    case 0x30:	/* MMC_SPI (OMAP1 only) */
-         break;
-     case 0x34:	/* MMC_SDIO */
--        s->sdio = value & 0x2020;
-+        s->sdio = value & (s->rev >= 2 ? 0xfbf3 : 0x2020);
-+        s->cdet_wakeup = (value >> 9) & 1;
-+        s->cdet_enable = (value >> 2) & 1;
-         break;
-     case 0x38:	/* MMC_SYST */
-         break;
-@@ -466,6 +525,19 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset,
-         OMAP_RO_REG(offset);
-         break;
- 
-+    /* OMAP2-specific */
-+    case 0x60:	/* MMC_IOSR */
-+        if (value & 0xf)
-+            printf("MMC: SDIO bits used!\n");
-+        break;
-+    case 0x64:	/* MMC_SYSC */
-+        if (value & (1 << 2))					/* SRTS */
-+            omap_mmc_reset(s);
-+        break;
-+    case 0x68:	/* MMC_SYSS */
-+        OMAP_RO_REG(offset);
-+        break;
-+
-     default:
-         OMAP_BAD_REG(offset);
-     }
-@@ -483,28 +555,21 @@ static CPUWriteMemoryFunc *omap_mmc_writefn[] = {
-     omap_badwidth_write16,
- };
- 
--void omap_mmc_reset(struct omap_mmc_s *host)
-+static void omap_mmc_cover_cb(void *opaque, int line, int level)
- {
--    host->last_cmd = 0;
--    memset(host->rsp, 0, sizeof(host->rsp));
--    host->arg = 0;
--    host->dw = 0;
--    host->mode = 0;
--    host->enable = 0;
--    host->status = 0;
--    host->mask = 0;
--    host->cto = 0;
--    host->dto = 0;
--    host->fifo_len = 0;
--    host->blen = 0;
--    host->blen_counter = 0;
--    host->nblk = 0;
--    host->nblk_counter = 0;
--    host->tx_dma = 0;
--    host->rx_dma = 0;
--    host->ae_level = 0x00;
--    host->af_level = 0x1f;
--    host->transfer = 0;
-+    struct omap_mmc_s *host = (struct omap_mmc_s *) opaque;
-+
-+    if (!host->cdet_state && level) {
-+        host->status |= 0x0002;
-+        omap_mmc_interrupts_update(host);
-+        if (host->cdet_wakeup)
-+            /* TODO: Assert wake-up */;
-+    }
-+
-+    if (host->cdet_state != level) {
-+        qemu_set_irq(host->coverswitch, level);
-+        host->cdet_state = level;
-+    }
- }
- 
- struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
-@@ -519,6 +584,10 @@ struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
-     s->base = base;
-     s->dma = dma;
-     s->clk = clk;
-+    s->lines = 1;	/* TODO: needs to be settable per-board */
-+    s->rev = 1;
-+
-+    omap_mmc_reset(s);
- 
-     iomemtype = cpu_register_io_memory(0, omap_mmc_readfn,
-                     omap_mmc_writefn, s);
-@@ -530,7 +599,46 @@ struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
-     return s;
- }
- 
-+struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
-+                BlockDriverState *bd, qemu_irq irq, qemu_irq dma[],
-+                omap_clk fclk, omap_clk iclk)
-+{
-+    int iomemtype;
-+    struct omap_mmc_s *s = (struct omap_mmc_s *)
-+            qemu_mallocz(sizeof(struct omap_mmc_s));
-+
-+    s->irq = irq;
-+    s->dma = dma;
-+    s->clk = fclk;
-+    s->lines = 4;
-+    s->rev = 2;
-+
-+    omap_mmc_reset(s);
-+
-+    iomemtype = cpu_register_io_memory(0, omap_mmc_readfn,
-+                    omap_mmc_writefn, s);
-+    s->base = omap_l4_attach(ta, 0, iomemtype);
-+
-+    /* Instantiate the storage */
-+    s->card = sd_init(bd, 0);
-+
-+    s->cdet = qemu_allocate_irqs(omap_mmc_cover_cb, s, 1)[0];
-+    sd_set_cb(s->card, 0, s->cdet);
-+
-+    return s;
-+}
-+
- void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover)
- {
--    sd_set_cb(s->card, ro, cover);
-+    if (s->cdet) {
-+        sd_set_cb(s->card, ro, s->cdet);
-+        s->coverswitch = cover;
-+        qemu_set_irq(cover, s->cdet_state);
-+    } else
-+        sd_set_cb(s->card, ro, cover);
-+}
-+
-+void omap_mmc_enable(struct omap_mmc_s *s, int enable)
-+{
-+    sd_enable(s->card, enable);
- }
-diff --git a/hw/onenand.c b/hw/onenand.c
-new file mode 100644
-index 0000000..549d392
---- /dev/null
-+++ b/hw/onenand.c
-@@ -0,0 +1,642 @@
-+/*
-+ * OneNAND flash memories emulation.
-+ *
-+ * Copyright (C) 2008 Nokia Corporation
-+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation; either version 2 of
-+ * the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-+ * MA 02111-1307 USA
-+ */
-+
-+#include "qemu-common.h"
-+#include "flash.h"
-+#include "irq.h"
-+#include "sysemu.h"
-+#include "block.h"
-+
-+/* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */
-+#define PAGE_SHIFT	11
-+
-+/* Fixed */
-+#define BLOCK_SHIFT	(PAGE_SHIFT + 6)
-+
-+struct onenand_s {
-+    uint32_t id;
-+    int shift;
-+    target_phys_addr_t base;
-+    qemu_irq intr;
-+    qemu_irq rdy;
-+    BlockDriverState *bdrv;
-+    BlockDriverState *bdrv_cur;
-+    uint8_t *image;
-+    uint8_t *otp;
-+    uint8_t *current;
-+    ram_addr_t ram;
-+    uint8_t *boot[2];
-+    uint8_t *data[2][2];
-+    int iomemtype;
-+    int cycle;
-+    int otpmode;
-+
-+    uint16_t addr[8];
-+    uint16_t unladdr[8];
-+    int bufaddr;
-+    int count;
-+    uint16_t command;
-+    uint16_t config[2];
-+    uint16_t status;
-+    uint16_t intstatus;
-+    uint16_t wpstatus;
-+
-+    struct ecc_state_s ecc;
-+
-+    int density_mask;
-+    int secs;
-+    int secs_cur;
-+    int blocks;
-+    uint8_t *blockwp;
-+};
-+
-+enum {
-+    ONEN_BUF_BLOCK = 0,
-+    ONEN_BUF_BLOCK2 = 1,
-+    ONEN_BUF_DEST_BLOCK = 2,
-+    ONEN_BUF_DEST_PAGE = 3,
-+    ONEN_BUF_PAGE = 7,
-+};
-+
-+enum {
-+    ONEN_ERR_CMD = 1 << 10,
-+    ONEN_ERR_ERASE = 1 << 11,
-+    ONEN_ERR_PROG = 1 << 12,
-+    ONEN_ERR_LOAD = 1 << 13,
-+};
-+
-+enum {
-+    ONEN_INT_RESET = 1 << 4,
-+    ONEN_INT_ERASE = 1 << 5,
-+    ONEN_INT_PROG = 1 << 6,
-+    ONEN_INT_LOAD = 1 << 7,
-+    ONEN_INT = 1 << 15,
-+};
-+
-+enum {
-+    ONEN_LOCK_LOCKTIGHTEN = 1 << 0,
-+    ONEN_LOCK_LOCKED = 1 << 1,
-+    ONEN_LOCK_UNLOCKED = 1 << 2,
-+};
-+
-+void onenand_base_update(void *opaque, target_phys_addr_t new)
-+{
-+    struct onenand_s *s = (struct onenand_s *) opaque;
-+
-+    s->base = new;
-+
-+    /* XXX: We should use IO_MEM_ROMD but we broke it earlier...
-+     * Both 0x0000 ... 0x01ff and 0x8000 ... 0x800f can be used to
-+     * write boot commands.  Also take note of the BWPS bit.  */
-+    cpu_register_physical_memory(s->base + (0x0000 << s->shift),
-+                    0x0200 << s->shift, s->iomemtype);
-+    cpu_register_physical_memory(s->base + (0x0200 << s->shift),
-+                    0xbe00 << s->shift,
-+                    (s->ram +(0x0200 << s->shift)) | IO_MEM_RAM);
-+    if (s->iomemtype)
-+        cpu_register_physical_memory(s->base + (0xc000 << s->shift),
-+                        0x4000 << s->shift, s->iomemtype);
-+}
-+
-+void onenand_base_unmap(void *opaque)
-+{
-+    struct onenand_s *s = (struct onenand_s *) opaque;
-+
-+    cpu_register_physical_memory(s->base,
-+                    0x10000 << s->shift, IO_MEM_UNASSIGNED);
-+}
-+
-+static void onenand_intr_update(struct onenand_s *s)
-+{
-+    qemu_set_irq(s->intr, ((s->intstatus >> 15) ^ (~s->config[0] >> 6)) & 1);
-+}
-+
-+/* Hot reset (Reset OneNAND command) or warm reset (RP pin low) */
-+static void onenand_reset(struct onenand_s *s, int cold)
-+{
-+    memset(&s->addr, 0, sizeof(s->addr));
-+    s->command = 0;
-+    s->count = 1;
-+    s->bufaddr = 0;
-+    s->config[0] = 0x40c0;
-+    s->config[1] = 0x0000;
-+    onenand_intr_update(s);
-+    qemu_irq_raise(s->rdy);
-+    s->status = 0x0000;
-+    s->intstatus = cold ? 0x8080 : 0x8010;
-+    s->unladdr[0] = 0;
-+    s->unladdr[1] = 0;
-+    s->wpstatus = 0x0002;
-+    s->cycle = 0;
-+    s->otpmode = 0;
-+    s->bdrv_cur = s->bdrv;
-+    s->current = s->image;
-+    s->secs_cur = s->secs;
-+
-+    if (cold) {
-+        /* Lock the whole flash */
-+        memset(s->blockwp, ONEN_LOCK_LOCKED, s->blocks);
-+
-+        if (s->bdrv && bdrv_read(s->bdrv, 0, s->boot[0], 8) < 0)
-+            cpu_abort(cpu_single_env, "%s: Loading the BootRAM failed.\n",
-+                            __FUNCTION__);
-+    }
-+}
-+
-+static inline int onenand_load_main(struct onenand_s *s, int sec, int secn,
-+                void *dest)
-+{
-+    if (s->bdrv_cur)
-+        return bdrv_read(s->bdrv_cur, sec, dest, secn) < 0;
-+    else if (sec + secn > s->secs_cur)
-+        return 1;
-+
-+    memcpy(dest, s->current + (sec << 9), secn << 9);
-+
-+    return 0;
-+}
-+
-+static inline int onenand_prog_main(struct onenand_s *s, int sec, int secn,
-+                void *src)
-+{
-+    if (s->bdrv_cur)
-+        return bdrv_write(s->bdrv_cur, sec, src, secn) < 0;
-+    else if (sec + secn > s->secs_cur)
-+        return 1;
-+
-+    memcpy(s->current + (sec << 9), src, secn << 9);
-+
-+    return 0;
-+}
-+
-+static inline int onenand_load_spare(struct onenand_s *s, int sec, int secn,
-+                void *dest)
-+{
-+    uint8_t buf[512];
-+
-+    if (s->bdrv_cur) {
-+        if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0)
-+            return 1;
-+        memcpy(dest, buf + ((sec & 31) << 4), secn << 4);
-+    } else if (sec + secn > s->secs_cur)
-+        return 1;
-+    else
-+        memcpy(dest, s->current + (s->secs_cur << 9) + (sec << 4), secn << 4);
-+ 
-+    return 0;
-+}
-+
-+static inline int onenand_prog_spare(struct onenand_s *s, int sec, int secn,
-+                void *src)
-+{
-+    uint8_t buf[512];
-+
-+    if (s->bdrv_cur) {
-+        if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0)
-+            return 1;
-+        memcpy(buf + ((sec & 31) << 4), src, secn << 4);
-+        return bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0;
-+    } else if (sec + secn > s->secs_cur)
-+        return 1;
-+
-+    memcpy(s->current + (s->secs_cur << 9) + (sec << 4), src, secn << 4);
-+ 
-+    return 0;
-+}
-+
-+static inline int onenand_erase(struct onenand_s *s, int sec, int num)
-+{
-+    /* TODO: optimise */
-+    uint8_t buf[512];
-+
-+    memset(buf, 0xff, sizeof(buf));
-+    for (; num > 0; num --, sec ++) {
-+        if (onenand_prog_main(s, sec, 1, buf))
-+            return 1;
-+        if (onenand_prog_spare(s, sec, 1, buf))
-+            return 1;
-+    }
-+
-+    return 0;
-+}
-+
-+static void onenand_command(struct onenand_s *s, int cmd)
-+{
-+    int b;
-+    int sec;
-+    void *buf;
-+#define SETADDR(block, page)			\
-+    sec = (s->addr[page] & 3) +			\
-+            ((((s->addr[page] >> 2) & 0x3f) +	\
-+              (((s->addr[block] & 0xfff) |	\
-+                (s->addr[block] >> 15 ?		\
-+                 s->density_mask : 0)) << 6)) << (PAGE_SHIFT - 9));
-+#define SETBUF_M()				\
-+    buf = (s->bufaddr & 8) ?			\
-+            s->data[(s->bufaddr >> 2) & 1][0] : s->boot[0];	\
-+    buf += (s->bufaddr & 3) << 9;
-+#define SETBUF_S()				\
-+    buf = (s->bufaddr & 8) ?			\
-+            s->data[(s->bufaddr >> 2) & 1][1] : s->boot[1];	\
-+    buf += (s->bufaddr & 3) << 4;
-+
-+    switch (cmd) {
-+    case 0x00:	/* Load single/multiple sector data unit into buffer */
-+        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
-+
-+        SETBUF_M()
-+        if (onenand_load_main(s, sec, s->count, buf))
-+            s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
-+
-+#if 0
-+        SETBUF_S()
-+        if (onenand_load_spare(s, sec, s->count, buf))
-+            s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
-+#endif
-+
-+        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
-+         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
-+         * then we need two split the read/write into two chunks.
-+         */
-+        s->intstatus |= ONEN_INT | ONEN_INT_LOAD;
-+        break;
-+    case 0x13:	/* Load single/multiple spare sector into buffer */
-+        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
-+
-+        SETBUF_S()
-+        if (onenand_load_spare(s, sec, s->count, buf))
-+            s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
-+
-+        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
-+         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
-+         * then we need two split the read/write into two chunks.
-+         */
-+        s->intstatus |= ONEN_INT | ONEN_INT_LOAD;
-+        break;
-+    case 0x80:	/* Program single/multiple sector data unit from buffer */
-+        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
-+
-+        SETBUF_M()
-+        if (onenand_prog_main(s, sec, s->count, buf))
-+            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
-+
-+#if 0
-+        SETBUF_S()
-+        if (onenand_prog_spare(s, sec, s->count, buf))
-+            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
-+#endif
-+
-+        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
-+         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
-+         * then we need two split the read/write into two chunks.
-+         */
-+        s->intstatus |= ONEN_INT | ONEN_INT_PROG;
-+        break;
-+    case 0x1a:	/* Program single/multiple spare area sector from buffer */
-+        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
-+
-+        SETBUF_S()
-+        if (onenand_prog_spare(s, sec, s->count, buf))
-+            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
-+
-+        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
-+         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
-+         * then we need two split the read/write into two chunks.
-+         */
-+        s->intstatus |= ONEN_INT | ONEN_INT_PROG;
-+        break;
-+    case 0x1b:	/* Copy-back program */
-+        SETBUF_S()
-+
-+        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
-+        if (onenand_load_main(s, sec, s->count, buf))
-+            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
-+
-+        SETADDR(ONEN_BUF_DEST_BLOCK, ONEN_BUF_DEST_PAGE)
-+        if (onenand_prog_main(s, sec, s->count, buf))
-+            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
-+
-+        /* TODO: spare areas */
-+
-+        s->intstatus |= ONEN_INT | ONEN_INT_PROG;
-+        break;
-+
-+    case 0x23:	/* Unlock NAND array block(s) */
-+        s->intstatus |= ONEN_INT;
-+
-+        /* XXX the previous (?) area should be locked automatically */
-+        for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
-+            if (b >= s->blocks) {
-+                s->status |= ONEN_ERR_CMD;
-+                break;
-+            }
-+            if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
-+                break;
-+
-+            s->wpstatus = s->blockwp[b] = ONEN_LOCK_UNLOCKED;
-+        }
-+        break;
-+    case 0x2a:	/* Lock NAND array block(s) */
-+        s->intstatus |= ONEN_INT;
-+
-+        for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
-+            if (b >= s->blocks) {
-+                s->status |= ONEN_ERR_CMD;
-+                break;
-+            }
-+            if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
-+                break;
-+
-+            s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKED;
-+        }
-+        break;
-+    case 0x2c:	/* Lock-tight NAND array block(s) */
-+        s->intstatus |= ONEN_INT;
-+
-+        for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
-+            if (b >= s->blocks) {
-+                s->status |= ONEN_ERR_CMD;
-+                break;
-+            }
-+            if (s->blockwp[b] == ONEN_LOCK_UNLOCKED)
-+                continue;
-+
-+            s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKTIGHTEN;
-+        }
-+        break;
-+
-+    case 0x71:	/* Erase-Verify-Read */
-+        s->intstatus |= ONEN_INT;
-+        break;
-+    case 0x95:	/* Multi-block erase */
-+        qemu_irq_pulse(s->intr);
-+        /* Fall through.  */
-+    case 0x94:	/* Block erase */
-+        sec = ((s->addr[ONEN_BUF_BLOCK] & 0xfff) |
-+                        (s->addr[ONEN_BUF_BLOCK] >> 15 ? s->density_mask : 0))
-+                << (BLOCK_SHIFT - 9);
-+        if (onenand_erase(s, sec, 1 << (BLOCK_SHIFT - 9)))
-+            s->status |= ONEN_ERR_CMD | ONEN_ERR_ERASE;
-+
-+        s->intstatus |= ONEN_INT | ONEN_INT_ERASE;
-+        break;
-+    case 0xb0:	/* Erase suspend */
-+        break;
-+    case 0x30:	/* Erase resume */
-+        s->intstatus |= ONEN_INT | ONEN_INT_ERASE;
-+        break;
-+
-+    case 0xf0:	/* Reset NAND Flash core */
-+        onenand_reset(s, 0);
-+        break;
-+    case 0xf3:	/* Reset OneNAND */
-+        onenand_reset(s, 0);
-+        break;
-+
-+    case 0x65:	/* OTP Access */
-+        s->intstatus |= ONEN_INT;
-+        s->bdrv_cur = 0;
-+        s->current = s->otp;
-+        s->secs_cur = 1 << (BLOCK_SHIFT - 9);
-+        s->addr[ONEN_BUF_BLOCK] = 0;
-+        s->otpmode = 1;
-+        break;
-+
-+    default:
-+        s->status |= ONEN_ERR_CMD;
-+        s->intstatus |= ONEN_INT;
-+        fprintf(stderr, "%s: unknown OneNAND command %x\n",
-+                        __FUNCTION__, cmd);
-+    }
-+
-+    onenand_intr_update(s);
-+}
-+
-+static uint32_t onenand_read(void *opaque, target_phys_addr_t addr)
-+{
-+    struct onenand_s *s = (struct onenand_s *) opaque;
-+    int offset = (addr - s->base) >> s->shift;
-+
-+    switch (offset) {
-+    case 0x0000 ... 0xc000:
-+        return lduw_le_p(s->boot[0] + (addr - s->base));
-+
-+    case 0xf000:	/* Manufacturer ID */
-+        return (s->id >> 16) & 0xff;
-+    case 0xf001:	/* Device ID */
-+        return (s->id >>  8) & 0xff;
-+    /* TODO: get the following values from a real chip!  */
-+    case 0xf002:	/* Version ID */
-+        return (s->id >>  0) & 0xff;
-+    case 0xf003:	/* Data Buffer size */
-+        return 1 << PAGE_SHIFT;
-+    case 0xf004:	/* Boot Buffer size */
-+        return 0x200;
-+    case 0xf005:	/* Amount of buffers */
-+        return 1 | (2 << 8);
-+    case 0xf006:	/* Technology */
-+        return 0;
-+
-+    case 0xf100 ... 0xf107:	/* Start addresses */
-+        return s->addr[offset - 0xf100];
-+
-+    case 0xf200:	/* Start buffer */
-+        return (s->bufaddr << 8) | ((s->count - 1) & (1 << (PAGE_SHIFT - 10)));
-+
-+    case 0xf220:	/* Command */
-+        return s->command;
-+    case 0xf221:	/* System Configuration 1 */
-+        return s->config[0] & 0xffe0;
-+    case 0xf222:	/* System Configuration 2 */
-+        return s->config[1];
-+
-+    case 0xf240:	/* Controller Status */
-+        return s->status;
-+    case 0xf241:	/* Interrupt */
-+        return s->intstatus;
-+    case 0xf24c:	/* Unlock Start Block Address */
-+        return s->unladdr[0];
-+    case 0xf24d:	/* Unlock End Block Address */
-+        return s->unladdr[1];
-+    case 0xf24e:	/* Write Protection Status */
-+        return s->wpstatus;
-+
-+    case 0xff00:	/* ECC Status */
-+        return 0x00;
-+    case 0xff01:	/* ECC Result of main area data */
-+    case 0xff02:	/* ECC Result of spare area data */
-+    case 0xff03:	/* ECC Result of main area data */
-+    case 0xff04:	/* ECC Result of spare area data */
-+        cpu_abort(cpu_single_env, "%s: imeplement ECC\n", __FUNCTION__);
-+        return 0x0000;
-+    }
-+
-+    fprintf(stderr, "%s: unknown OneNAND register %x\n",
-+                    __FUNCTION__, offset);
-+    return 0;
-+}
-+
-+static void onenand_write(void *opaque, target_phys_addr_t addr,
-+                uint32_t value)
-+{
-+    struct onenand_s *s = (struct onenand_s *) opaque;
-+    int offset = (addr - s->base) >> s->shift;
-+    int sec;
-+
-+    switch (offset) {
-+    case 0x0000 ... 0x01ff:
-+    case 0x8000 ... 0x800f:
-+        if (s->cycle) {
-+            s->cycle = 0;
-+
-+            if (value == 0x0000) {
-+                SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
-+                onenand_load_main(s, sec,
-+                                1 << (PAGE_SHIFT - 9), s->data[0][0]);
-+                s->addr[ONEN_BUF_PAGE] += 4;
-+                s->addr[ONEN_BUF_PAGE] &= 0xff;
-+            }
-+            break;
-+        }
-+
-+        switch (value) {
-+        case 0x00f0:	/* Reset OneNAND */
-+            onenand_reset(s, 0);
-+            break;
-+
-+        case 0x00e0:	/* Load Data into Buffer */
-+            s->cycle = 1;
-+            break;
-+
-+        case 0x0090:	/* Read Identification Data */
-+            memset(s->boot[0], 0, 3 << s->shift);
-+            s->boot[0][0 << s->shift] = (s->id >> 16) & 0xff;
-+            s->boot[0][1 << s->shift] = (s->id >>  8) & 0xff;
-+            s->boot[0][2 << s->shift] = s->wpstatus & 0xff;
-+            break;
-+
-+        default:
-+            fprintf(stderr, "%s: unknown OneNAND boot command %x\n",
-+                            __FUNCTION__, value);
-+        }
-+        break;
-+
-+    case 0xf100 ... 0xf107:	/* Start addresses */
-+        s->addr[offset - 0xf100] = value;
-+        break;
-+
-+    case 0xf200:	/* Start buffer */
-+        s->bufaddr = (value >> 8) & 0xf;
-+        if (PAGE_SHIFT == 11)
-+            s->count = (value & 3) ?: 4;
-+        else if (PAGE_SHIFT == 10)
-+            s->count = (value & 1) ?: 2;
-+        break;
-+
-+    case 0xf220:	/* Command */
-+        if (s->intstatus & (1 << 15))
-+            break;
-+        s->command = value;
-+        onenand_command(s, s->command);
-+        break;
-+    case 0xf221:	/* System Configuration 1 */
-+        s->config[0] = value;
-+        onenand_intr_update(s);
-+        qemu_set_irq(s->rdy, (s->config[0] >> 7) & 1);
-+        break;
-+    case 0xf222:	/* System Configuration 2 */
-+        s->config[1] = value;
-+        break;
-+
-+    case 0xf241:	/* Interrupt */
-+        s->intstatus &= value;
-+        if ((1 << 15) & ~s->intstatus)
-+            s->status &= ~(ONEN_ERR_CMD | ONEN_ERR_ERASE |
-+                            ONEN_ERR_PROG | ONEN_ERR_LOAD);
-+        onenand_intr_update(s);
-+        break;
-+    case 0xf24c:	/* Unlock Start Block Address */
-+        s->unladdr[0] = value & (s->blocks - 1);
-+        /* For some reason we have to set the end address to by default
-+         * be same as start because the software forgets to write anything
-+         * in there.  */
-+        s->unladdr[1] = value & (s->blocks - 1);
-+        break;
-+    case 0xf24d:	/* Unlock End Block Address */
-+        s->unladdr[1] = value & (s->blocks - 1);
-+        break;
-+
-+    default:
-+        fprintf(stderr, "%s: unknown OneNAND register %x\n",
-+                        __FUNCTION__, offset);
-+    }
-+}
-+
-+static CPUReadMemoryFunc *onenand_readfn[] = {
-+    onenand_read,	/* TODO */
-+    onenand_read,
-+    onenand_read,
-+};
-+
-+static CPUWriteMemoryFunc *onenand_writefn[] = {
-+    onenand_write,	/* TODO */
-+    onenand_write,
-+    onenand_write,
-+};
-+
-+void *onenand_init(uint32_t id, int regshift, qemu_irq irq)
-+{
-+    struct onenand_s *s = (struct onenand_s *) qemu_mallocz(sizeof(*s));
-+    int bdrv_index = drive_get_index(IF_MTD, 0, 0);
-+    uint32_t size = 1 << (24 + ((id >> 12) & 7));
-+    void *ram;
-+
-+    s->shift = regshift;
-+    s->intr = irq;
-+    s->rdy = 0;
-+    s->id = id;
-+    s->blocks = size >> BLOCK_SHIFT;
-+    s->secs = size >> 9;
-+    s->blockwp = qemu_malloc(s->blocks);
-+    s->density_mask = (id & (1 << 11)) ? (1 << (6 + ((id >> 12) & 7))) : 0;
-+    s->iomemtype = cpu_register_io_memory(0, onenand_readfn,
-+                    onenand_writefn, s);
-+    if (bdrv_index == -1)
-+        s->image = memset(qemu_malloc(size + (size >> 5)),
-+                        0xff, size + (size >> 5));
-+    else
-+        s->bdrv = drives_table[bdrv_index].bdrv;
-+    s->otp = memset(qemu_malloc((64 + 2) << PAGE_SHIFT),
-+                    0xff, (64 + 2) << PAGE_SHIFT);
-+    s->ram = qemu_ram_alloc(0xc000 << s->shift);
-+    ram = phys_ram_base + s->ram;
-+    s->boot[0] = ram + (0x0000 << s->shift);
-+    s->boot[1] = ram + (0x8000 << s->shift);
-+    s->data[0][0] = ram + ((0x0200 + (0 << (PAGE_SHIFT - 1))) << s->shift);
-+    s->data[0][1] = ram + ((0x8010 + (0 << (PAGE_SHIFT - 6))) << s->shift);
-+    s->data[1][0] = ram + ((0x0200 + (1 << (PAGE_SHIFT - 1))) << s->shift);
-+    s->data[1][1] = ram + ((0x8010 + (1 << (PAGE_SHIFT - 6))) << s->shift);
-+
-+    onenand_reset(s, 1);
-+
-+    return s;
-+}
-diff --git a/hw/palm.c b/hw/palm.c
-index 9400ea7..8b767e2 100644
---- a/hw/palm.c
-+++ b/hw/palm.c
-@@ -25,6 +25,7 @@
- #include "omap.h"
- #include "boards.h"
- #include "arm-misc.h"
-+#include "devices.h"
- 
- static uint32_t static_readb(void *opaque, target_phys_addr_t offset)
- {
-@@ -32,12 +33,14 @@ static uint32_t static_readb(void *opaque, target_phys_addr_t offset)
-     return *val >> ((offset & 3) << 3);
- }
- 
--static uint32_t static_readh(void *opaque, target_phys_addr_t offset) {
-+static uint32_t static_readh(void *opaque, target_phys_addr_t offset)
-+{
-     uint32_t *val = (uint32_t *) opaque;
-     return *val >> ((offset & 1) << 3);
- }
- 
--static uint32_t static_readw(void *opaque, target_phys_addr_t offset) {
-+static uint32_t static_readw(void *opaque, target_phys_addr_t offset)
-+{
-     uint32_t *val = (uint32_t *) opaque;
-     return *val >> ((offset & 0) << 3);
- }
-@@ -183,6 +186,12 @@ static void palmte_gpio_setup(struct omap_mpu_state_s *cpu)
-     qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[11]);
- }
- 
-+static struct arm_boot_info palmte_binfo = {
-+    .loader_start = OMAP_EMIFF_BASE,
-+    .ram_size = 0x02000000,
-+    .board_id = 0x331,
-+};
-+
- static void palmte_init(int ram_size, int vga_ram_size,
-                 const char *boot_device, DisplayState *ds,
-                 const char *kernel_filename, const char *kernel_cmdline,
-@@ -190,7 +199,7 @@ static void palmte_init(int ram_size, int vga_ram_size,
- {
-     struct omap_mpu_state_s *cpu;
-     int flash_size = 0x00800000;
--    int sdram_size = 0x02000000;
-+    int sdram_size = palmte_binfo.ram_size;
-     int io;
-     static uint32_t cs0val = 0xffffffff;
-     static uint32_t cs1val = 0x0000e1a0;
-@@ -250,10 +259,12 @@ static void palmte_init(int ram_size, int vga_ram_size,
-     /* Load the kernel.  */
-     if (kernel_filename) {
-         /* Start at bootloader.  */
--        cpu->env->regs[15] = OMAP_EMIFF_BASE;
-+        cpu->env->regs[15] = palmte_binfo.loader_start;
- 
--        arm_load_kernel(cpu->env, sdram_size, kernel_filename, kernel_cmdline,
--                        initrd_filename, 0x331, OMAP_EMIFF_BASE);
-+        palmte_binfo.kernel_filename = kernel_filename;
-+        palmte_binfo.kernel_cmdline = kernel_cmdline;
-+        palmte_binfo.initrd_filename = initrd_filename;
-+        arm_load_kernel(cpu->env, &palmte_binfo);
-     }
- 
-     dpy_resize(ds, 320, 320);
-diff --git a/hw/realview.c b/hw/realview.c
-index 29579d8..acf3b9e 100644
---- a/hw/realview.c
-+++ b/hw/realview.c
-@@ -18,6 +18,11 @@
- 
- /* Board init.  */
- 
-+static struct arm_boot_info realview_binfo = {
-+    .loader_start = 0x0,
-+    .board_id = 0x33b,
-+};
-+
- static void realview_init(int ram_size, int vga_ram_size,
-                      const char *boot_device, DisplayState *ds,
-                      const char *kernel_filename, const char *kernel_cmdline,
-@@ -177,8 +182,12 @@ static void realview_init(int ram_size, int vga_ram_size,
-     /* 0x68000000 PCI mem 1.  */
-     /* 0x6c000000 PCI mem 2.  */
- 
--    arm_load_kernel(first_cpu, ram_size, kernel_filename, kernel_cmdline,
--                    initrd_filename, 0x33b, 0x0);
-+    realview_binfo.ram_size = ram_size;
-+    realview_binfo.kernel_filename = kernel_filename;
-+    realview_binfo.kernel_cmdline = kernel_cmdline;
-+    realview_binfo.initrd_filename = initrd_filename;
-+    realview_binfo.nb_cpus = ncpu;
-+    arm_load_kernel(first_cpu, &realview_binfo);
- 
-     /* ??? Hack to map an additional page of ram for the secondary CPU
-        startup code.  I guess this works on real hardware because the
-diff --git a/hw/sd.c b/hw/sd.c
-index 1f71d85..de7dd89 100644
---- a/hw/sd.c
-+++ b/hw/sd.c
-@@ -37,7 +37,7 @@
- 
- #ifdef DEBUG_SD
- #define DPRINTF(fmt, args...) \
--do { printf("SD: " fmt , ##args); } while (0)
-+do { fprintf(stderr, "SD: " fmt , ##args); } while (0)
- #else
- #define DPRINTF(fmt, args...) do {} while(0)
- #endif
-@@ -99,6 +99,8 @@ struct SDState {
-     qemu_irq inserted_cb;
-     BlockDriverState *bdrv;
-     uint8_t *buf;
-+
-+    int enable;
- };
- 
- static void sd_set_status(SDState *sd)
-@@ -530,7 +532,7 @@ static void sd_lock_command(SDState *sd)
-         sd->card_status &= ~CARD_IS_LOCKED;
-         sd->pwd_len = 0;
-         /* Erasing the entire card here! */
--        printf("SD: Card force-erased by CMD42\n");
-+        fprintf(stderr, "SD: Card force-erased by CMD42\n");
-         return;
-     }
- 
-@@ -1076,7 +1078,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
-         return sd_r1;
- 
-     case 56:	/* CMD56:  GEN_CMD */
--        printf("SD: GEN_CMD 0x%08x\n", req.arg);
-+        fprintf(stderr, "SD: GEN_CMD 0x%08x\n", req.arg);
- 
-         switch (sd->state) {
-         case sd_transfer_state:
-@@ -1096,18 +1098,18 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
-     bad_cmd:
-         sd->card_status |= ILLEGAL_COMMAND;
- 
--        printf("SD: Unknown CMD%i\n", req.cmd);
-+        fprintf(stderr, "SD: Unknown CMD%i\n", req.cmd);
-         return sd_r0;
- 
-     unimplemented_cmd:
-         /* Commands that are recognised but not yet implemented in SPI mode.  */
-         sd->card_status |= ILLEGAL_COMMAND;
--        printf ("SD: CMD%i not implemented in SPI mode\n", req.cmd);
-+        fprintf(stderr, "SD: CMD%i not implemented in SPI mode\n", req.cmd);
-         return sd_r0;
-     }
- 
-     sd->card_status |= ILLEGAL_COMMAND;
--    printf("SD: CMD%i in a wrong state\n", req.cmd);
-+    fprintf(stderr, "SD: CMD%i in a wrong state\n", req.cmd);
-     return sd_r0;
- }
- 
-@@ -1217,7 +1219,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
-         return sd_normal_command(sd, req);
-     }
- 
--    printf("SD: ACMD%i in a wrong state\n", req.cmd);
-+    fprintf(stderr, "SD: ACMD%i in a wrong state\n", req.cmd);
-     return sd_r0;
- }
- 
-@@ -1227,7 +1229,7 @@ int sd_do_command(SDState *sd, struct sd_request_s *req,
-     sd_rsp_type_t rtype;
-     int rsplen;
- 
--    if (!bdrv_is_inserted(sd->bdrv)) {
-+    if (!bdrv_is_inserted(sd->bdrv) || !sd->enable) {
-         return 0;
-     }
- 
-@@ -1247,7 +1249,7 @@ int sd_do_command(SDState *sd, struct sd_request_s *req,
-                           sd_cmd_class[req->cmd] == 7 ||
-                           req->cmd == 16 || req->cmd == 55))) {
-             sd->card_status |= ILLEGAL_COMMAND;
--            printf("SD: Card is locked\n");
-+            fprintf(stderr, "SD: Card is locked\n");
-             return 0;
-         }
- 
-@@ -1321,7 +1323,7 @@ static void sd_blk_read(SDState *sd, uint32_t addr, uint32_t len)
-     uint32_t end = addr + len;
- 
-     if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) == -1) {
--        printf("sd_blk_read: read error on host side\n");
-+        fprintf(stderr, "sd_blk_read: read error on host side\n");
-         return;
-     }
- 
-@@ -1329,7 +1331,7 @@ static void sd_blk_read(SDState *sd, uint32_t addr, uint32_t len)
-         memcpy(sd->data, sd->buf + (addr & 511), 512 - (addr & 511));
- 
-         if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) == -1) {
--            printf("sd_blk_read: read error on host side\n");
-+            fprintf(stderr, "sd_blk_read: read error on host side\n");
-             return;
-         }
-         memcpy(sd->data + 512 - (addr & 511), sd->buf, end & 511);
-@@ -1343,28 +1345,28 @@ static void sd_blk_write(SDState *sd, uint32_t addr, uint32_t len)
- 
-     if ((addr & 511) || len < 512)
-         if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) == -1) {
--            printf("sd_blk_write: read error on host side\n");
-+            fprintf(stderr, "sd_blk_write: read error on host side\n");
-             return;
-         }
- 
-     if (end > (addr & ~511) + 512) {
-         memcpy(sd->buf + (addr & 511), sd->data, 512 - (addr & 511));
-         if (bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) == -1) {
--            printf("sd_blk_write: write error on host side\n");
-+            fprintf(stderr, "sd_blk_write: write error on host side\n");
-             return;
-         }
- 
-         if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) == -1) {
--            printf("sd_blk_write: read error on host side\n");
-+            fprintf(stderr, "sd_blk_write: read error on host side\n");
-             return;
-         }
-         memcpy(sd->buf, sd->data + 512 - (addr & 511), end & 511);
-         if (bdrv_write(sd->bdrv, end >> 9, sd->buf, 1) == -1)
--            printf("sd_blk_write: write error on host side\n");
-+            fprintf(stderr, "sd_blk_write: write error on host side\n");
-     } else {
-         memcpy(sd->buf + (addr & 511), sd->data, len);
-         if (!sd->bdrv || bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) == -1)
--            printf("sd_blk_write: write error on host side\n");
-+            fprintf(stderr, "sd_blk_write: write error on host side\n");
-     }
- }
- 
-@@ -1377,11 +1379,11 @@ void sd_write_data(SDState *sd, uint8_t value)
- {
-     int i;
- 
--    if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv))
-+    if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable)
-         return;
- 
-     if (sd->state != sd_receivingdata_state) {
--        printf("sd_write_data: not in Receiving-Data state\n");
-+        fprintf(stderr, "sd_write_data: not in Receiving-Data state\n");
-         return;
-     }
- 
-@@ -1489,7 +1491,7 @@ void sd_write_data(SDState *sd, uint8_t value)
-         break;
- 
-     default:
--        printf("sd_write_data: unknown command\n");
-+        fprintf(stderr, "sd_write_data: unknown command\n");
-         break;
-     }
- }
-@@ -1499,11 +1501,11 @@ uint8_t sd_read_data(SDState *sd)
-     /* TODO: Append CRCs */
-     uint8_t ret;
- 
--    if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv))
-+    if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable)
-         return 0x00;
- 
-     if (sd->state != sd_sendingdata_state) {
--        printf("sd_read_data: not in Sending-Data state\n");
-+        fprintf(stderr, "sd_read_data: not in Sending-Data state\n");
-         return 0x00;
-     }
- 
-@@ -1603,7 +1605,7 @@ uint8_t sd_read_data(SDState *sd)
-         break;
- 
-     default:
--        printf("sd_read_data: unknown command\n");
-+        fprintf(stderr, "sd_read_data: unknown command\n");
-         return 0x00;
-     }
- 
-@@ -1614,3 +1616,8 @@ int sd_data_ready(SDState *sd)
- {
-     return sd->state == sd_sendingdata_state;
- }
-+
-+void sd_enable(SDState *sd, int enable)
-+{
-+    sd->enable = enable;
-+}
-diff --git a/hw/sd.h b/hw/sd.h
-index 85f110f..cb7bc9c 100644
---- a/hw/sd.h
-+++ b/hw/sd.h
-@@ -74,6 +74,7 @@ void sd_write_data(SDState *sd, uint8_t value);
- uint8_t sd_read_data(SDState *sd);
- void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert);
- int sd_data_ready(SDState *sd);
-+void sd_enable(SDState *sd, int enable);
- 
- /* ssi-sd.c */
- int ssi_sd_xfer(void *opaque, int val);
-diff --git a/hw/spitz.c b/hw/spitz.c
-index 159c633..b059f9a 100644
---- a/hw/spitz.c
-+++ b/hw/spitz.c
-@@ -1180,12 +1180,17 @@ static void sl_bootparam_write(uint32_t ptr)
- /* Board init.  */
- enum spitz_model_e { spitz, akita, borzoi, terrier };
- 
-+static struct arm_boot_info spitz_binfo = {
-+    .loader_start = PXA2XX_SDRAM_BASE,
-+    .ram_size = 0x04000000,
-+};
-+
- static void spitz_common_init(int ram_size, int vga_ram_size,
-                 DisplayState *ds, const char *kernel_filename,
-                 const char *kernel_cmdline, const char *initrd_filename,
-                 const char *cpu_model, enum spitz_model_e model, int arm_id)
- {
--    uint32_t spitz_ram = 0x04000000;
-+    uint32_t spitz_ram = spitz_binfo.ram_size;
-     uint32_t spitz_rom = 0x00800000;
-     struct pxa2xx_state_s *cpu;
-     struct scoop_info_s *scp;
-@@ -1230,10 +1235,13 @@ static void spitz_common_init(int ram_size, int vga_ram_size,
-         spitz_microdrive_attach(cpu);
- 
-     /* Setup initial (reset) machine state */
--    cpu->env->regs[15] = PXA2XX_SDRAM_BASE;
-+    cpu->env->regs[15] = spitz_binfo.loader_start;
- 
--    arm_load_kernel(cpu->env, spitz_ram, kernel_filename, kernel_cmdline,
--                    initrd_filename, arm_id, PXA2XX_SDRAM_BASE);
-+    spitz_binfo.kernel_filename = kernel_filename;
-+    spitz_binfo.kernel_cmdline = kernel_cmdline;
-+    spitz_binfo.initrd_filename = initrd_filename;
-+    spitz_binfo.board_id = arm_id;
-+    arm_load_kernel(cpu->env, &spitz_binfo);
-     sl_bootparam_write(SL_PXA_PARAM_BASE - PXA2XX_SDRAM_BASE);
- }
- 
-diff --git a/hw/tmp105.c b/hw/tmp105.c
-new file mode 100644
-index 0000000..d9a3900
---- /dev/null
-+++ b/hw/tmp105.c
-@@ -0,0 +1,249 @@
-+/*
-+ * Texas Instruments TMP105 temperature sensor.
-+ *
-+ * Copyright (C) 2008 Nokia Corporation
-+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation; either version 2 of
-+ * the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-+ * MA 02111-1307 USA
-+ */
-+
-+#include "hw.h"
-+#include "i2c.h"
-+
-+struct tmp105_s {
-+    i2c_slave i2c;
-+    int len;
-+    uint8_t buf[2];
-+    qemu_irq pin;
-+
-+    uint8_t pointer;
-+    uint8_t config;
-+    int16_t temperature;
-+    int16_t limit[2];
-+    int faults;
-+    int alarm;
-+};
-+
-+static void tmp105_interrupt_update(struct tmp105_s *s)
-+{
-+    qemu_set_irq(s->pin, s->alarm ^ ((~s->config >> 2) & 1));	/* POL */
-+}
-+
-+static void tmp105_alarm_update(struct tmp105_s *s)
-+{
-+    if ((s->config >> 0) & 1) {					/* SD */
-+        if ((s->config >> 7) & 1)				/* OS */
-+            s->config &= ~(1 << 7);				/* OS */
-+        else
-+            return;
-+    }
-+
-+    if ((s->config >> 1) & 1) {					/* TM */
-+        if (s->temperature >= s->limit[1])
-+            s->alarm = 1;
-+        else if (s->temperature < s->limit[0])
-+            s->alarm = 1;
-+    } else {
-+        if (s->temperature >= s->limit[1])
-+            s->alarm = 1;
-+        else if (s->temperature < s->limit[0])
-+            s->alarm = 0;
-+    }
-+
-+    tmp105_interrupt_update(s);
-+}
-+
-+/* Units are 0.001 centigrades relative to 0 C.  */
-+void tmp105_set(i2c_slave *i2c, int temp)
-+{
-+    struct tmp105_s *s = (struct tmp105_s *) i2c;
-+
-+    if (temp >= 128000 || temp < -128000) {
-+        fprintf(stderr, "%s: values is out of range (%i.%03i C)\n",
-+                        __FUNCTION__, temp / 1000, temp % 1000);
-+        exit(-1);
-+    }
-+
-+    s->temperature = ((int16_t) (temp * 0x800 / 128000)) << 4;
-+
-+    tmp105_alarm_update(s);
-+}
-+
-+static const int tmp105_faultq[4] = { 1, 2, 4, 6 };
-+
-+static void tmp105_read(struct tmp105_s *s)
-+{
-+    s->len = 0;
-+
-+    if ((s->config >> 1) & 1) {					/* TM */
-+        s->alarm = 0;
-+        tmp105_interrupt_update(s);
-+    }
-+
-+    switch (s->pointer & 3) {
-+    case 0:	/* Temperature */
-+        s->buf[s->len ++] = (((uint16_t) s->temperature) >> 8);
-+        s->buf[s->len ++] = (((uint16_t) s->temperature) >> 0) &
-+                (0xf0 << ((~s->config >> 5) & 3));		/* R */
-+        break;
-+
-+    case 1:	/* Configuration */
-+        s->buf[s->len ++] = s->config;
-+        break;
-+
-+    case 2:	/* T_LOW */
-+        s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 8;
-+        s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 0;
-+        break;
-+
-+    case 3:	/* T_HIGH */
-+        s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 8;
-+        s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 0;
-+        break;
-+    }
-+}
-+
-+static void tmp105_write(struct tmp105_s *s)
-+{
-+    switch (s->pointer & 3) {
-+    case 0:	/* Temperature */
-+        break;
-+
-+    case 1:	/* Configuration */
-+        if (s->buf[0] & ~s->config & (1 << 0))			/* SD */
-+            printf("%s: TMP105 shutdown\n", __FUNCTION__);
-+        s->config = s->buf[0];
-+        s->faults = tmp105_faultq[(s->config >> 3) & 3];	/* F */
-+        tmp105_alarm_update(s);
-+        break;
-+
-+    case 2:	/* T_LOW */
-+    case 3:	/* T_HIGH */
-+        if (s->len >= 3)
-+            s->limit[s->pointer & 1] = (int16_t)
-+                    ((((uint16_t) s->buf[0]) << 8) | s->buf[1]);
-+        tmp105_alarm_update(s);
-+        break;
-+    }
-+}
-+
-+static int tmp105_rx(i2c_slave *i2c)
-+{
-+    struct tmp105_s *s = (struct tmp105_s *) i2c;
-+
-+    if (s->len < 2)
-+        return s->buf[s->len ++];
-+    else
-+        return 0xff;
-+}
-+
-+static int tmp105_tx(i2c_slave *i2c, uint8_t data)
-+{
-+    struct tmp105_s *s = (struct tmp105_s *) i2c;
-+
-+    if (!s->len ++)
-+        s->pointer = data;
-+    else {
-+        if (s->len <= 2)
-+            s->buf[s->len - 1] = data;
-+        tmp105_write(s);
-+    }
-+
-+    return 0;
-+}
-+
-+static void tmp105_event(i2c_slave *i2c, enum i2c_event event)
-+{
-+    struct tmp105_s *s = (struct tmp105_s *) i2c;
-+
-+    if (event == I2C_START_RECV)
-+        tmp105_read(s);
-+
-+    s->len = 0;
-+}
-+
-+static void tmp105_save(QEMUFile *f, void *opaque)
-+{
-+    struct tmp105_s *s = (struct tmp105_s *) opaque;
-+
-+    qemu_put_byte(f, s->len);
-+    qemu_put_8s(f, &s->buf[0]);
-+    qemu_put_8s(f, &s->buf[1]);
-+
-+    qemu_put_8s(f, &s->pointer);
-+    qemu_put_8s(f, &s->config);
-+    qemu_put_be16s(f, &s->temperature);
-+    qemu_put_be16s(f, &s->limit[0]);
-+    qemu_put_be16s(f, &s->limit[1]);
-+    qemu_put_byte(f, s->alarm);
-+    s->faults = tmp105_faultq[(s->config >> 3) & 3];		/* F */
-+
-+    i2c_slave_save(f, &s->i2c);
-+}
-+
-+static int tmp105_load(QEMUFile *f, void *opaque, int version_id)
-+{
-+    struct tmp105_s *s = (struct tmp105_s *) opaque;
-+
-+    s->len = qemu_get_byte(f);
-+    qemu_get_8s(f, &s->buf[0]);
-+    qemu_get_8s(f, &s->buf[1]);
-+
-+    qemu_get_8s(f, &s->pointer);
-+    qemu_get_8s(f, &s->config);
-+    qemu_get_be16s(f, &s->temperature);
-+    qemu_get_be16s(f, &s->limit[0]);
-+    qemu_get_be16s(f, &s->limit[1]);
-+    s->alarm = qemu_get_byte(f);
-+
-+    tmp105_interrupt_update(s);
-+
-+    i2c_slave_load(f, &s->i2c);
-+    return 0;
-+}
-+
-+void tmp105_reset(i2c_slave *i2c)
-+{
-+    struct tmp105_s *s = (struct tmp105_s *) i2c;
-+
-+    s->temperature = 0;
-+    s->pointer = 0;
-+    s->config = 0;
-+    s->faults = tmp105_faultq[(s->config >> 3) & 3];
-+    s->alarm = 0;
-+
-+    tmp105_interrupt_update(s);
-+}
-+
-+static int tmp105_iid = 0;
-+
-+struct i2c_slave *tmp105_init(i2c_bus *bus, qemu_irq alarm)
-+{
-+    struct tmp105_s *s = (struct tmp105_s *)
-+            i2c_slave_init(bus, 0, sizeof(struct tmp105_s));
-+
-+    s->i2c.event = tmp105_event;
-+    s->i2c.recv = tmp105_rx;
-+    s->i2c.send = tmp105_tx;
-+    s->pin = alarm;
-+
-+    tmp105_reset(&s->i2c);
-+
-+    register_savevm("TMP105", tmp105_iid ++, 0,
-+                    tmp105_save, tmp105_load, s);
-+
-+    return &s->i2c;
-+}
-diff --git a/hw/tsc210x.c b/hw/tsc210x.c
-index 96956a4..1654b8b 100644
---- a/hw/tsc210x.c
-+++ b/hw/tsc210x.c
-@@ -2,6 +2,7 @@
-  * TI TSC2102 (touchscreen/sensors/audio controller) emulator.
-  *
-  * Copyright (c) 2006 Andrzej Zaborowski  <balrog@zabor.org>
-+ * Copyright (C) 2008 Nokia Corporation
-  *
-  * This program is free software; you can redistribute it and/or
-  * modify it under the terms of the GNU General Public License as
-@@ -35,12 +36,15 @@
- 
- struct tsc210x_state_s {
-     qemu_irq pint;
-+    qemu_irq kbint;
-+    qemu_irq davint;
-     QEMUTimer *timer;
-     QEMUSoundCard card;
-     struct uwire_slave_s chip;
-     struct i2s_codec_s codec;
-     uint8_t in_fifo[16384];
-     uint8_t out_fifo[16384];
-+    uint16_t model;
- 
-     int x, y;
-     int pressure;
-@@ -64,7 +68,7 @@ struct tsc210x_state_s {
-     uint16_t audio_ctrl1;
-     uint16_t audio_ctrl2;
-     uint16_t audio_ctrl3;
--    uint16_t pll[2];
-+    uint16_t pll[3];
-     uint16_t volume;
-     int64_t volume_change;
-     int softstep;
-@@ -78,6 +82,17 @@ struct tsc210x_state_s {
-     int i2s_rx_rate;
-     int i2s_tx_rate;
-     AudioState *audio;
-+
-+    int tr[8];
-+
-+    struct {
-+        uint16_t down;
-+        uint16_t mask;
-+        int scan;
-+        int debounce;
-+        int mode;
-+        int intr;
-+    } kb;
- };
- 
- static const int resolution[4] = { 12, 8, 10, 12 };
-@@ -118,17 +133,10 @@ static const uint16_t mode_regs[16] = {
-     0x0000,	/* Y+, X- drivers */
- };
- 
--/*
-- * Convert screen coordinates to arbitrary values that the
-- * touchscreen in my Palm Tungsten E device returns.
-- * This shouldn't really matter (because the guest system
-- * should calibrate the touchscreen anyway), but let's
-- * imitate some real hardware.
-- */
--#define X_TRANSFORM(value)		\
--    ((3850 - ((int) (value) * (3850 - 250) / 32768)) << 4)
--#define Y_TRANSFORM(value)		\
--    ((150 + ((int) (value) * (3037 - 150) / 32768)) << 4)
-+#define X_TRANSFORM(s)			\
-+    ((s->y * s->tr[0] - s->x * s->tr[1]) / s->tr[2] + s->tr[3])
-+#define Y_TRANSFORM(s)			\
-+    ((s->y * s->tr[4] - s->x * s->tr[5]) / s->tr[6] + s->tr[7])
- #define Z1_TRANSFORM(s)			\
-     ((400 - ((s)->x >> 7) + ((s)->pressure << 10)) << 4)
- #define Z2_TRANSFORM(s)			\
-@@ -161,6 +169,7 @@ static void tsc210x_reset(struct tsc210x_state_s *s)
-     s->audio_ctrl3 = 0x0000;
-     s->pll[0] = 0x1004;
-     s->pll[1] = 0x0000;
-+    s->pll[2] = 0x1fff;
-     s->volume = 0xffff;
-     s->dac_power = 0x8540;
-     s->softstep = 1;
-@@ -190,7 +199,15 @@ static void tsc210x_reset(struct tsc210x_state_s *s)
-     s->i2s_tx_rate = 0;
-     s->i2s_rx_rate = 0;
- 
-+    s->kb.scan = 1;
-+    s->kb.debounce = 0;
-+    s->kb.mask = 0x0000;
-+    s->kb.mode = 3;
-+    s->kb.intr = 0;
-+
-     qemu_set_irq(s->pint, !s->irq);
-+    qemu_set_irq(s->davint, !s->dav);
-+    qemu_irq_raise(s->kbint);
- }
- 
- struct tsc210x_rate_info_s {
-@@ -344,13 +361,13 @@ static uint16_t tsc2102_data_register_read(struct tsc210x_state_s *s, int reg)
-     switch (reg) {
-     case 0x00:	/* X */
-         s->dav &= 0xfbff;
--        return TSC_CUT_RESOLUTION(X_TRANSFORM(s->x), s->precision) +
-+        return TSC_CUT_RESOLUTION(X_TRANSFORM(s), s->precision) +
-                 (s->noise & 3);
- 
-     case 0x01:	/* Y */
-         s->noise ++;
-         s->dav &= 0xfdff;
--        return TSC_CUT_RESOLUTION(Y_TRANSFORM(s->y), s->precision) ^
-+        return TSC_CUT_RESOLUTION(Y_TRANSFORM(s), s->precision) ^
-                 (s->noise & 3);
- 
-     case 0x02:	/* Z1 */
-@@ -364,6 +381,14 @@ static uint16_t tsc2102_data_register_read(struct tsc210x_state_s *s, int reg)
-                 (s->noise & 3);
- 
-     case 0x04:	/* KPData */
-+        if ((s->model & 0xff00) == 0x2300) {
-+            if (s->kb.intr && (s->kb.mode & 2)) {
-+                s->kb.intr = 0;
-+                qemu_irq_raise(s->kbint);
-+            }
-+            return s->kb.down;
-+        }
-+
-         return 0xffff;
- 
-     case 0x05:	/* BAT1 */
-@@ -414,9 +439,19 @@ static uint16_t tsc2102_control_register_read(
-         return (s->pressure << 15) | ((!s->busy) << 14) |
-                 (s->nextfunction << 10) | (s->nextprecision << 8) | s->filter; 
- 
--    case 0x01:	/* Status */
--        return (s->pin_func << 14) | ((!s->enabled) << 13) |
--                (s->host_mode << 12) | ((!!s->dav) << 11) | s->dav;
-+    case 0x01:	/* Status / Keypad Control */
-+        if ((s->model & 0xff00) == 0x2100)
-+            return (s->pin_func << 14) | ((!s->enabled) << 13) |
-+                    (s->host_mode << 12) | ((!!s->dav) << 11) | s->dav;
-+        else
-+            return (s->kb.intr << 15) | ((s->kb.scan || !s->kb.down) << 14) |
-+                    (s->kb.debounce << 11);
-+
-+    case 0x02:	/* DAC Control */
-+        if ((s->model & 0xff00) == 0x2300)
-+            return s->dac_power & 0x8000;
-+        else
-+            goto bad_reg;
- 
-     case 0x03:	/* Reference */
-         return s->ref;
-@@ -427,7 +462,18 @@ static uint16_t tsc2102_control_register_read(
-     case 0x05:	/* Configuration */
-         return s->timing;
- 
-+    case 0x06:	/* Secondary configuration */
-+        if ((s->model & 0xff00) == 0x2100)
-+            goto bad_reg;
-+        return ((!s->dav) << 15) | ((s->kb.mode & 1) << 14) | s->pll[2];
-+
-+    case 0x10:	/* Keypad Mask */
-+        if ((s->model & 0xff00) == 0x2100)
-+            goto bad_reg;
-+        return s->kb.mask;
-+
-     default:
-+    bad_reg:
- #ifdef TSC_VERBOSE
-         fprintf(stderr, "tsc2102_control_register_read: "
-                         "no such register: 0x%02x\n", reg);
-@@ -556,10 +602,27 @@ static void tsc2102_control_register_write(
-         s->filter = value & 0xff;
-         return;
- 
--    case 0x01:	/* Status */
--        s->pin_func = value >> 14;
-+    case 0x01:	/* Status / Keypad Control */
-+        if ((s->model & 0xff00) == 0x2100)
-+            s->pin_func = value >> 14;
-+	else {
-+            s->kb.scan = (value >> 14) & 1;
-+            s->kb.debounce = (value >> 11) & 7;
-+            if (s->kb.intr && s->kb.scan) {
-+                s->kb.intr = 0;
-+                qemu_irq_raise(s->kbint);
-+            }
-+        }
-         return;
+diff -urN 4242/cpu-all.h qemu-omap/cpu-all.h
+--- 4242/cpu-all.h	2008-04-24 21:26:19.000000000 +0100
++++ qemu-omap/cpu-all.h	2008-04-23 09:57:55.000000000 +0100
+@@ -816,7 +816,7 @@
+ /* physical memory access */
+ #define TLB_INVALID_MASK   (1 << 3)
+ #define IO_MEM_SHIFT       4
+-#define IO_MEM_NB_ENTRIES  (1 << (TARGET_PAGE_BITS  - IO_MEM_SHIFT))
++#define IO_MEM_NB_ENTRIES  (16 << (TARGET_PAGE_BITS  - IO_MEM_SHIFT))
  
-+    case 0x02:	/* DAC Control */
-+        if ((s->model & 0xff00) == 0x2300) {
-+            s->dac_power &= 0x7fff;
-+            s->dac_power |= 0x8000 & value;
-+        } else
-+            goto bad_reg;
-+        break;
-+
-     case 0x03:	/* Reference */
-         s->ref = value & 0x1f;
-         return;
-@@ -586,7 +649,21 @@ static void tsc2102_control_register_write(
+ #define IO_MEM_RAM         (0 << IO_MEM_SHIFT) /* hardcoded offset */
+ #define IO_MEM_ROM         (1 << IO_MEM_SHIFT) /* hardcoded offset */
+diff -urN 4242/exec.c qemu-omap/exec.c
+--- 4242/exec.c	2008-04-24 18:11:49.000000000 +0100
++++ qemu-omap/exec.c	2008-04-23 09:57:55.000000000 +0100
+@@ -1664,7 +1664,7 @@
+     {
+         if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
+             /* IO memory case */
+-            address = vaddr | pd;
++            address = vaddr | (pd & ~TARGET_PAGE_MASK);
+             addend = paddr;
+         } else {
+             /* standard memory */
+@@ -1698,7 +1698,9 @@
+         } else {
+             te->addr_read = -1;
+         }
+-        if (prot & PAGE_EXEC) {
++        if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
++            te->addr_code = pd;
++        } else if (prot & PAGE_EXEC) {
+             te->addr_code = address;
+         } else {
+             te->addr_code = -1;
+@@ -2493,7 +2495,9 @@
+     if (io_index <= 0) {
+         if (io_mem_nb >= IO_MEM_NB_ENTRIES)
+             return -1;
+-        io_index = io_mem_nb++;
++        do io_index = io_mem_nb++;
++        while (((io_index << IO_MEM_SHIFT) & ~TARGET_PAGE_MASK)
++               <= IO_MEM_NOTDIRTY);
+     } else {
+         if (io_index >= IO_MEM_NB_ENTRIES)
+             return -1;
+diff -urN 4242/hw/max7310.c qemu-omap/hw/max7310.c
+--- 4242/hw/max7310.c	2008-04-24 18:11:49.000000000 +0100
++++ qemu-omap/hw/max7310.c	2008-03-02 19:31:55.000000000 +0000
+@@ -134,8 +134,8 @@
+         s->i2c_command_byte = 1;
+         break;
+     case I2C_FINISH:
+-        if (s->len == 1)
+ #ifdef VERBOSE
++        if (s->len == 1)
+             printf("%s: message too short (%i bytes)\n", __FUNCTION__, s->len);
  #endif
-         return;
- 
-+    case 0x06:	/* Secondary configuration */
-+        if ((s->model & 0xff00) == 0x2100)
-+            goto bad_reg;
-+        s->kb.mode = value >> 14;
-+        s->pll[2] = value & 0x3ffff;
-+        return;
-+
-+    case 0x10:	/* Keypad Mask */
-+        if ((s->model & 0xff00) == 0x2100)
-+            goto bad_reg;
-+        s->kb.mask = value;
-+        return;
-+
-     default:
-+    bad_reg:
- #ifdef TSC_VERBOSE
-         fprintf(stderr, "tsc2102_control_register_write: "
-                         "no such register: 0x%02x\n", reg);
-@@ -785,7 +862,7 @@ static void tsc210x_pin_update(struct tsc210x_state_s *s)
-         return;
-     }
- 
--    if (!s->enabled || s->busy)
-+    if (!s->enabled || s->busy || s->dav)
-         return;
- 
-     s->busy = 1;
-@@ -805,6 +882,8 @@ static uint16_t tsc210x_read(struct tsc210x_state_s *s)
-     switch (s->page) {
-     case TSC_DATA_REGISTERS_PAGE:
-         ret = tsc2102_data_register_read(s, s->offset);
-+        if (!s->dav)
-+            qemu_irq_raise(s->davint);
          break;
-     case TSC_CONTROL_REGISTERS_PAGE:
-         ret = tsc2102_control_register_read(s, s->offset);
-@@ -859,6 +938,22 @@ static void tsc210x_write(struct tsc210x_state_s *s, uint16_t value)
-     }
+diff -urN 4242/hw/ndis.h qemu-omap/hw/ndis.h
+--- 4242/hw/ndis.h	1970-01-01 01:00:00.000000000 +0100
++++ qemu-omap/hw/ndis.h	2008-04-23 09:57:56.000000000 +0100
+@@ -0,0 +1,217 @@
++/*
++ * ndis.h 
++ * 
++ * ntddndis.h modified by Benedikt Spranger <b.spranger@pengutronix.de>
++ * 
++ * Thanks to the cygwin development team, 
++ * espacially to Casper S. Hornstrup <chorns@users.sourceforge.net>
++ * 
++ * THIS SOFTWARE IS NOT COPYRIGHTED
++ *
++ * This source code is offered for use in the public domain. You may
++ * use, modify or distribute it freely.
++ *
++ * This code is distributed in the hope that it will be useful but
++ * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
++ * DISCLAIMED. This includes but is not limited to warranties of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
++ *
++ */
++
++#ifndef _LINUX_NDIS_H
++#define _LINUX_NDIS_H
++
++
++#define NDIS_STATUS_MULTICAST_FULL	  0xC0010009
++#define NDIS_STATUS_MULTICAST_EXISTS      0xC001000A
++#define NDIS_STATUS_MULTICAST_NOT_FOUND   0xC001000B
++
++enum NDIS_DEVICE_POWER_STATE {
++	NdisDeviceStateUnspecified = 0,
++	NdisDeviceStateD0,
++	NdisDeviceStateD1,
++	NdisDeviceStateD2,
++	NdisDeviceStateD3,
++	NdisDeviceStateMaximum
++};
++
++struct NDIS_PM_WAKE_UP_CAPABILITIES {
++	enum NDIS_DEVICE_POWER_STATE  MinMagicPacketWakeUp;
++	enum NDIS_DEVICE_POWER_STATE  MinPatternWakeUp;
++	enum NDIS_DEVICE_POWER_STATE  MinLinkChangeWakeUp;
++};
++
++/* NDIS_PNP_CAPABILITIES.Flags constants */
++#define NDIS_DEVICE_WAKE_UP_ENABLE                0x00000001
++#define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE  0x00000002
++#define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE   0x00000004
++
++struct NDIS_PNP_CAPABILITIES {
++	__le32					Flags;
++	struct NDIS_PM_WAKE_UP_CAPABILITIES	WakeUpCapabilities;
++};
++
++struct NDIS_PM_PACKET_PATTERN {
++	__le32	Priority;
++	__le32	Reserved;
++	__le32	MaskSize;
++	__le32	PatternOffset;
++	__le32	PatternSize;
++	__le32	PatternFlags;
++};
++
++
++/* Required Object IDs (OIDs) */
++#define OID_GEN_SUPPORTED_LIST            0x00010101
++#define OID_GEN_HARDWARE_STATUS           0x00010102
++#define OID_GEN_MEDIA_SUPPORTED           0x00010103
++#define OID_GEN_MEDIA_IN_USE              0x00010104
++#define OID_GEN_MAXIMUM_LOOKAHEAD         0x00010105
++#define OID_GEN_MAXIMUM_FRAME_SIZE        0x00010106
++#define OID_GEN_LINK_SPEED                0x00010107
++#define OID_GEN_TRANSMIT_BUFFER_SPACE     0x00010108
++#define OID_GEN_RECEIVE_BUFFER_SPACE      0x00010109
++#define OID_GEN_TRANSMIT_BLOCK_SIZE       0x0001010A
++#define OID_GEN_RECEIVE_BLOCK_SIZE        0x0001010B
++#define OID_GEN_VENDOR_ID                 0x0001010C
++#define OID_GEN_VENDOR_DESCRIPTION        0x0001010D
++#define OID_GEN_CURRENT_PACKET_FILTER     0x0001010E
++#define OID_GEN_CURRENT_LOOKAHEAD         0x0001010F
++#define OID_GEN_DRIVER_VERSION            0x00010110
++#define OID_GEN_MAXIMUM_TOTAL_SIZE        0x00010111
++#define OID_GEN_PROTOCOL_OPTIONS          0x00010112
++#define OID_GEN_MAC_OPTIONS               0x00010113
++#define OID_GEN_MEDIA_CONNECT_STATUS      0x00010114
++#define OID_GEN_MAXIMUM_SEND_PACKETS      0x00010115
++#define OID_GEN_VENDOR_DRIVER_VERSION     0x00010116
++#define OID_GEN_SUPPORTED_GUIDS           0x00010117
++#define OID_GEN_NETWORK_LAYER_ADDRESSES   0x00010118
++#define OID_GEN_TRANSPORT_HEADER_OFFSET   0x00010119
++#define OID_GEN_MACHINE_NAME              0x0001021A
++#define OID_GEN_RNDIS_CONFIG_PARAMETER    0x0001021B
++#define OID_GEN_VLAN_ID                   0x0001021C
++
++/* Optional OIDs */
++#define OID_GEN_MEDIA_CAPABILITIES        0x00010201
++#define OID_GEN_PHYSICAL_MEDIUM           0x00010202
++
++/* Required statistics OIDs */
++#define OID_GEN_XMIT_OK                   0x00020101
++#define OID_GEN_RCV_OK                    0x00020102
++#define OID_GEN_XMIT_ERROR                0x00020103
++#define OID_GEN_RCV_ERROR                 0x00020104
++#define OID_GEN_RCV_NO_BUFFER             0x00020105
++
++/* Optional statistics OIDs */
++#define OID_GEN_DIRECTED_BYTES_XMIT       0x00020201
++#define OID_GEN_DIRECTED_FRAMES_XMIT      0x00020202
++#define OID_GEN_MULTICAST_BYTES_XMIT      0x00020203
++#define OID_GEN_MULTICAST_FRAMES_XMIT     0x00020204
++#define OID_GEN_BROADCAST_BYTES_XMIT      0x00020205
++#define OID_GEN_BROADCAST_FRAMES_XMIT     0x00020206
++#define OID_GEN_DIRECTED_BYTES_RCV        0x00020207
++#define OID_GEN_DIRECTED_FRAMES_RCV       0x00020208
++#define OID_GEN_MULTICAST_BYTES_RCV       0x00020209
++#define OID_GEN_MULTICAST_FRAMES_RCV      0x0002020A
++#define OID_GEN_BROADCAST_BYTES_RCV       0x0002020B
++#define OID_GEN_BROADCAST_FRAMES_RCV      0x0002020C
++#define OID_GEN_RCV_CRC_ERROR             0x0002020D
++#define OID_GEN_TRANSMIT_QUEUE_LENGTH     0x0002020E
++#define OID_GEN_GET_TIME_CAPS             0x0002020F
++#define OID_GEN_GET_NETCARD_TIME          0x00020210
++#define OID_GEN_NETCARD_LOAD              0x00020211
++#define OID_GEN_DEVICE_PROFILE            0x00020212
++#define OID_GEN_INIT_TIME_MS              0x00020213
++#define OID_GEN_RESET_COUNTS              0x00020214
++#define OID_GEN_MEDIA_SENSE_COUNTS        0x00020215
++#define OID_GEN_FRIENDLY_NAME             0x00020216
++#define OID_GEN_MINIPORT_INFO             0x00020217
++#define OID_GEN_RESET_VERIFY_PARAMETERS   0x00020218
++
++/* IEEE 802.3 (Ethernet) OIDs */
++#define NDIS_802_3_MAC_OPTION_PRIORITY    0x00000001
++
++#define OID_802_3_PERMANENT_ADDRESS       0x01010101
++#define OID_802_3_CURRENT_ADDRESS         0x01010102
++#define OID_802_3_MULTICAST_LIST          0x01010103
++#define OID_802_3_MAXIMUM_LIST_SIZE       0x01010104
++#define OID_802_3_MAC_OPTIONS             0x01010105
++#define OID_802_3_RCV_ERROR_ALIGNMENT     0x01020101
++#define OID_802_3_XMIT_ONE_COLLISION      0x01020102
++#define OID_802_3_XMIT_MORE_COLLISIONS    0x01020103
++#define OID_802_3_XMIT_DEFERRED           0x01020201
++#define OID_802_3_XMIT_MAX_COLLISIONS     0x01020202
++#define OID_802_3_RCV_OVERRUN             0x01020203
++#define OID_802_3_XMIT_UNDERRUN           0x01020204
++#define OID_802_3_XMIT_HEARTBEAT_FAILURE  0x01020205
++#define OID_802_3_XMIT_TIMES_CRS_LOST     0x01020206
++#define OID_802_3_XMIT_LATE_COLLISIONS    0x01020207
++
++/* OID_GEN_MINIPORT_INFO constants */
++#define NDIS_MINIPORT_BUS_MASTER                      0x00000001
++#define NDIS_MINIPORT_WDM_DRIVER                      0x00000002
++#define NDIS_MINIPORT_SG_LIST                         0x00000004
++#define NDIS_MINIPORT_SUPPORTS_MEDIA_QUERY            0x00000008
++#define NDIS_MINIPORT_INDICATES_PACKETS               0x00000010
++#define NDIS_MINIPORT_IGNORE_PACKET_QUEUE             0x00000020
++#define NDIS_MINIPORT_IGNORE_REQUEST_QUEUE            0x00000040
++#define NDIS_MINIPORT_IGNORE_TOKEN_RING_ERRORS        0x00000080
++#define NDIS_MINIPORT_INTERMEDIATE_DRIVER             0x00000100
++#define NDIS_MINIPORT_IS_NDIS_5                       0x00000200
++#define NDIS_MINIPORT_IS_CO                           0x00000400
++#define NDIS_MINIPORT_DESERIALIZE                     0x00000800
++#define NDIS_MINIPORT_REQUIRES_MEDIA_POLLING          0x00001000
++#define NDIS_MINIPORT_SUPPORTS_MEDIA_SENSE            0x00002000
++#define NDIS_MINIPORT_NETBOOT_CARD                    0x00004000
++#define NDIS_MINIPORT_PM_SUPPORTED                    0x00008000
++#define NDIS_MINIPORT_SUPPORTS_MAC_ADDRESS_OVERWRITE  0x00010000
++#define NDIS_MINIPORT_USES_SAFE_BUFFER_APIS           0x00020000
++#define NDIS_MINIPORT_HIDDEN                          0x00040000
++#define NDIS_MINIPORT_SWENUM                          0x00080000
++#define NDIS_MINIPORT_SURPRISE_REMOVE_OK              0x00100000
++#define NDIS_MINIPORT_NO_HALT_ON_SUSPEND              0x00200000
++#define NDIS_MINIPORT_HARDWARE_DEVICE                 0x00400000
++#define NDIS_MINIPORT_SUPPORTS_CANCEL_SEND_PACKETS    0x00800000
++#define NDIS_MINIPORT_64BITS_DMA                      0x01000000
++
++#define NDIS_MEDIUM_802_3		0x00000000
++#define NDIS_MEDIUM_802_5		0x00000001
++#define NDIS_MEDIUM_FDDI		0x00000002
++#define NDIS_MEDIUM_WAN			0x00000003
++#define NDIS_MEDIUM_LOCAL_TALK		0x00000004
++#define NDIS_MEDIUM_DIX			0x00000005
++#define NDIS_MEDIUM_ARCENT_RAW		0x00000006
++#define NDIS_MEDIUM_ARCENT_878_2	0x00000007
++#define NDIS_MEDIUM_ATM			0x00000008
++#define NDIS_MEDIUM_WIRELESS_LAN	0x00000009
++#define NDIS_MEDIUM_IRDA		0x0000000A
++#define NDIS_MEDIUM_BPC			0x0000000B
++#define NDIS_MEDIUM_CO_WAN		0x0000000C
++#define NDIS_MEDIUM_1394		0x0000000D
++
++#define NDIS_PACKET_TYPE_DIRECTED	0x00000001
++#define NDIS_PACKET_TYPE_MULTICAST	0x00000002
++#define NDIS_PACKET_TYPE_ALL_MULTICAST	0x00000004
++#define NDIS_PACKET_TYPE_BROADCAST	0x00000008
++#define NDIS_PACKET_TYPE_SOURCE_ROUTING	0x00000010
++#define NDIS_PACKET_TYPE_PROMISCUOUS	0x00000020
++#define NDIS_PACKET_TYPE_SMT		0x00000040
++#define NDIS_PACKET_TYPE_ALL_LOCAL	0x00000080
++#define NDIS_PACKET_TYPE_GROUP		0x00000100
++#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL	0x00000200
++#define NDIS_PACKET_TYPE_FUNCTIONAL	0x00000400
++#define NDIS_PACKET_TYPE_MAC_FRAME	0x00000800
++
++#define NDIS_MEDIA_STATE_CONNECTED	0x00000000
++#define NDIS_MEDIA_STATE_DISCONNECTED	0x00000001
++
++#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA     0x00000001
++#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED      0x00000002
++#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND      0x00000004
++#define NDIS_MAC_OPTION_NO_LOOPBACK             0x00000008
++#define NDIS_MAC_OPTION_FULL_DUPLEX             0x00000010
++#define NDIS_MAC_OPTION_EOTX_INDICATION         0x00000020
++#define NDIS_MAC_OPTION_8021P_PRIORITY          0x00000040
++#define NDIS_MAC_OPTION_RESERVED                0x80000000
++
++#endif /* _LINUX_NDIS_H */
+diff -urN 4242/hw/nseries.c qemu-omap/hw/nseries.c
+--- 4242/hw/nseries.c	2008-04-24 18:11:49.000000000 +0100
++++ qemu-omap/hw/nseries.c	2008-04-23 09:57:56.000000000 +0100
+@@ -602,6 +602,37 @@
+                     (void *) &config7, sizeof(config7));
  }
  
-+uint32_t tsc210x_txrx(void *opaque, uint32_t value)
-+{
-+    struct tsc210x_state_s *s = opaque;
-+    uint32_t ret = 0;
-+
-+    /* TODO: sequential reads etc - how do we make sure the host doesn't
-+     * unintentionally read out a conversion result from a register while
-+     * transmitting the command word of the next command?  */
-+    if (!value || (s->state && s->command))
-+        ret = tsc210x_read(s);
-+    if (value || (s->state && !s->command))
-+        tsc210x_write(s, value);
-+
-+    return ret;
-+}
++#if 0
++static uint32_t n800_pinout[104] = {
++    0x080f00d8, 0x00d40808, 0x03080808, 0x080800d0,
++    0x00dc0808, 0x0b0f0f00, 0x080800b4, 0x00c00808,
++    0x08080808, 0x180800c4, 0x00b80000, 0x08080808,
++    0x080800bc, 0x00cc0808, 0x08081818, 0x18180128,
++    0x01241800, 0x18181818, 0x000000f0, 0x01300000,
++    0x00001b0b, 0x1b0f0138, 0x00e0181b, 0x1b031b0b,
++    0x180f0078, 0x00740018, 0x0f0f0f1a, 0x00000080,
++    0x007c0000, 0x00000000, 0x00000088, 0x00840000,
++    0x00000000, 0x00000094, 0x00980300, 0x0f180003,
++    0x0000008c, 0x00900f0f, 0x0f0f1b00, 0x0f00009c,
++    0x01140000, 0x1b1b0f18, 0x0818013c, 0x01400008,
++    0x00001818, 0x000b0110, 0x010c1800, 0x0b030b0f,
++    0x181800f4, 0x00f81818, 0x00000018, 0x000000fc,
++    0x00401808, 0x00000000, 0x0f1b0030, 0x003c0008,
++    0x00000000, 0x00000038, 0x00340000, 0x00000000,
++    0x1a080070, 0x00641a1a, 0x08080808, 0x08080060,
++    0x005c0808, 0x08080808, 0x08080058, 0x00540808,
++    0x08080808, 0x0808006c, 0x00680808, 0x08080808,
++    0x000000a8, 0x00b00000, 0x08080808, 0x000000a0,
++    0x00a40000, 0x00000000, 0x08ff0050, 0x004c0808,
++    0xffffffff, 0xffff0048, 0x0044ffff, 0xffffffff,
++    0x000000ac, 0x01040800, 0x08080b0f, 0x18180100,
++    0x01081818, 0x0b0b1808, 0x1a0300e4, 0x012c0b1a,
++    0x02020018, 0x0b000134, 0x011c0800, 0x0b1b1b00,
++    0x0f0000c8, 0x00ec181b, 0x000f0f02, 0x00180118,
++    0x01200000, 0x0f0b1b1b, 0x0f0200e8, 0x0000020b,
++};
++#endif
 +
- static void tsc210x_timer_tick(void *opaque)
+ /* Setup sequence done by the bootloader */
+ static void n800_boot_init(void *opaque)
  {
-     struct tsc210x_state_s *s = opaque;
-@@ -871,6 +966,7 @@ static void tsc210x_timer_tick(void *opaque)
-     s->busy = 0;
-     s->dav |= mode_regs[s->function];
-     tsc210x_pin_update(s);
-+    qemu_irq_lower(s->davint);
- }
- 
- static void tsc210x_touchscreen_event(void *opaque,
-@@ -1001,6 +1097,7 @@ static int tsc210x_load(QEMUFile *f, void *opaque, int version_id)
- 
-     s->busy = qemu_timer_pending(s->timer);
-     qemu_set_irq(s->pint, !s->irq);
-+    qemu_set_irq(s->davint, !s->dav);
- 
-     return 0;
+@@ -942,3 +973,71 @@
+     "Nokia N800 aka. RX-34 tablet (OMAP2420)",
+     n800_init,
+ };
++
++#if 0
++/* cx3110x.c */
++#define CY_ARM_INT		0x00
++#define CY_ARM_INT_ENA		0x00
++#define CY_HOST_INT		0x00
++#define CY_HOST_INT_ENA		0x00
++#define CY_HOST_INT_ACK		0x00
++#define CY_GP1_COMM		0x00
++#define CY_GP2_COMM		0x00
++#define CY_DEV_CTRL_STA		0x00
++#define CY_DMA_DATA		0x00	/* 16-bit */
++#define CY_DMA_WR_CTRL		0x00	/* 16-bit */
++#define CY_DMA_WR_LEN		0x00	/* 16-bit */
++#define CY_DMA_WR_BASE		0x00
++#define CY_DMA_RD_CTRL		0x00	/* 16-bit */
++#define CY_DMA_RD_LEN		0x00	/* 16-bit */
++#define CY_DMA_RD_BASE		0x00
++
++HW:
++(spi bus 1.0)
++  tsc2005
++(spi bus 1.1)
++  lcd_mipid
++(spi bus 2.0)
++  cx3110x (WLAN)
++(spi somewhere?)
++  pc2400m (WiMAX)
++(i2c bus 0)
++  TLV320AIC33 (audio codec on i2c)
++  TCM825x (camera on i2c)
++  lp5521 (LED on i2c)
++  tsl2563 (light sensor, hwmon on i2c)
++  lm8323 (keypad on i2c)
++(i2c bus 1)
++  tmp105 (temperature sensor, hwmon on i2c)
++  menelaus (power on i2c)
++
++GPIO   0: out hi
++GPIO   8: in  hi
++GPIO   9: out hi
++GPIO  10: out lo
++GPIO  12: out lo
++GPIO  15: out lo
++GPIO  23: out hi
++GPIO  26: in  hi, irq-186 rising
++GPIO  53: out lo
++GPIO  58: in  hi, irq-218 low wakeup
++GPIO  62: out lo
++GPIO  64: out hi
++GPIO  65: in  hi
++GPIO  66: out lo
++GPIO  93: out lo
++GPIO  94: in  hi
++GPIO  95: out lo
++GPIO  96: out hi
++GPIO 101: out lo
++GPIO 102: in  hi, irq-262 bothedge
++GPIO 106: in  hi, irq-266 falling wakeup
++GPIO 107: in  hi, irq-267 bothedge
++GPIO 108: in  lo, irq-268 rising wakeup
++GPIO 109: in  hi, irq-269 falling wakeup
++GPIO 110: in  hi, irq-270 bothedge
++GPIO 111: in  lo, irq-271 rising
++GPIO 112: out hi
++GPIO 118: out hi
++GPIO 125: in  lo, irq-285 rising
++#endif
+diff -urN 4242/hw/omap2.c qemu-omap/hw/omap2.c
+--- 4242/hw/omap2.c	2008-04-24 18:11:49.000000000 +0100
++++ qemu-omap/hw/omap2.c	2008-04-23 09:57:56.000000000 +0100
+@@ -3675,152 +3675,152 @@
+                     omap_findclk(s, "dss_l4_iclk"));
+ 
+     /* All register mappings (includin those not currenlty implemented):
+-     * SystemControlMod	48000000 - 48000fff
+-     * SystemControlL4	48001000 - 48001fff
+-     * 32kHz Timer Mod	48004000 - 48004fff
+-     * 32kHz Timer L4	48005000 - 48005fff
+-     * PRCM ModA	48008000 - 480087ff
++     * SystemControlMod	48000000 - 48000fff (REV 0x00000010)
++     * SystemControlL4	48001000 - 48001fff (0x00200010, 0x01000200, 0x00000000)
++     * 32kHz Timer Mod	48004000 - 48004fff (REV 0x00000011)
++     * 32kHz Timer L4	48005000 - 48005fff (0x00200010, 0x01000200, 0x00000000)
++     * PRCM ModA	48008000 - 480087ff (REV 0x00000010)
+      * PRCM ModB	48008800 - 48008fff
+-     * PRCM L4		48009000 - 48009fff
+-     * TEST-BCM Mod	48012000 - 48012fff
+-     * TEST-BCM L4	48013000 - 48013fff
+-     * TEST-TAP Mod	48014000 - 48014fff
+-     * TEST-TAP L4	48015000 - 48015fff
+-     * GPIO1 Mod	48018000 - 48018fff
+-     * GPIO Top		48019000 - 48019fff
+-     * GPIO2 Mod	4801a000 - 4801afff
+-     * GPIO L4		4801b000 - 4801bfff
+-     * GPIO3 Mod	4801c000 - 4801cfff
+-     * GPIO4 Mod	4801e000 - 4801efff
+-     * WDTIMER1 Mod	48020000 - 48010fff
++     * PRCM L4		48009000 - 48009fff (0x00200010, 0x00000200, 0x00000000)
++     * TEST-BCM Mod	48012000 - 48012fff (REV 0x00000010)
++     * TEST-BCM L4	48013000 - 48013fff (0x00200010, 0x00000200, 0x00000000)
++     * TEST-TAP Mod	48014000 - 48014fff (REV 0x00000010)
++     * TEST-TAP L4	48015000 - 48015fff (0x00200010, 0x00000200, 0x00000000)
++     * GPIO1 Mod	48018000 - 48018fff (REV 0x00000018)
++     * GPIO Top		48019000 - 48019fff (REV 0x00000011)
++     * GPIO2 Mod	4801a000 - 4801afff (REV 0x00000018)
++     * GPIO L4		4801b000 - 4801bfff (0x00200010, 0x00000200, 0x00000000)
++     * GPIO3 Mod	4801c000 - 4801cfff (REV 0x00000018)
++     * GPIO4 Mod	4801e000 - 4801efff (REV 0x00000018)
++     * WDTIMER1 Mod	48020000 - 48010fff (REV Abort)
+      * WDTIMER Top	48021000 - 48011fff
+-     * WDTIMER2 Mod	48022000 - 48012fff
+-     * WDTIMER L4	48023000 - 48013fff
+-     * WDTIMER3 Mod	48024000 - 48014fff
+-     * WDTIMER3 L4	48025000 - 48015fff
+-     * WDTIMER4 Mod	48026000 - 48016fff
+-     * WDTIMER4 L4	48027000 - 48017fff
+-     * GPTIMER1 Mod	48028000 - 48018fff
+-     * GPTIMER1 L4	48029000 - 48019fff
+-     * GPTIMER2 Mod	4802a000 - 4801afff
+-     * GPTIMER2 L4	4802b000 - 4801bfff
++     * WDTIMER2 Mod	48022000 - 48012fff (REV 0x00000011)
++     * WDTIMER L4	48023000 - 48013fff (0x00200010, 0x00000200, 0x00000000)
++     * WDTIMER3 Mod	48024000 - 48014fff (REV 0x00000011)
++     * WDTIMER3 L4	48025000 - 48015fff (0x00200010, 0x00000200, 0x00000000)
++     * WDTIMER4 Mod	48026000 - 48016fff (REV 0x00000011)
++     * WDTIMER4 L4	48027000 - 48017fff (0x00200010, 0x00000200, 0x00000000)
++     * GPTIMER1 Mod	48028000 - 48018fff (REV 0x00000013)
++     * GPTIMER1 L4	48029000 - 48019fff (0x00200010, 0x00000200, 0x00000000)
++     * GPTIMER2 Mod	4802a000 - 4801afff (REV Abort)
++     * GPTIMER2 L4	4802b000 - 4801bfff (0x00200010, 0x00000200, 0x00000000)
+      * L4-Config AP	48040000 - 480407ff
+      * L4-Config IP	48040800 - 48040fff
+      * L4-Config LA	48041000 - 48041fff
+-     * ARM11ETB Mod	48048000 - 48049fff
+-     * ARM11ETB L4	4804a000 - 4804afff
+-     * DISPLAY Top	48050000 - 480503ff
+-     * DISPLAY DISPC	48050400 - 480507ff
+-     * DISPLAY RFBI	48050800 - 48050bff
+-     * DISPLAY VENC	48050c00 - 48050fff
+-     * DISPLAY L4	48051000 - 48051fff
+-     * CAMERA Top	48052000 - 480523ff
+-     * CAMERA core	48052400 - 480527ff
+-     * CAMERA DMA	48052800 - 48052bff
+-     * CAMERA MMU	48052c00 - 48052fff
+-     * CAMERA L4	48053000 - 48053fff
+-     * SDMA Mod		48056000 - 48056fff
+-     * SDMA L4		48057000 - 48057fff
+-     * SSI Top		48058000 - 48058fff
+-     * SSI GDD		48059000 - 48059fff
+-     * SSI Port1	4805a000 - 4805afff
+-     * SSI Port2	4805b000 - 4805bfff
+-     * SSI L4		4805c000 - 4805cfff
+-     * USB Mod		4805e000 - 480fefff
+-     * USB L4		4805f000 - 480fffff
+-     * WIN_TRACER1 Mod	48060000 - 48060fff
+-     * WIN_TRACER1 L4	48061000 - 48061fff
+-     * WIN_TRACER2 Mod	48062000 - 48062fff
+-     * WIN_TRACER2 L4	48063000 - 48063fff
+-     * WIN_TRACER3 Mod	48064000 - 48064fff
+-     * WIN_TRACER3 L4	48065000 - 48065fff
+-     * WIN_TRACER4 Top	48066000 - 480660ff
+-     * WIN_TRACER4 ETT	48066100 - 480661ff
+-     * WIN_TRACER4 WT	48066200 - 480662ff
+-     * WIN_TRACER4 L4	48067000 - 48067fff
+-     * XTI Mod		48068000 - 48068fff
+-     * XTI L4		48069000 - 48069fff
+-     * UART1 Mod	4806a000 - 4806afff
+-     * UART1 L4		4806b000 - 4806bfff
+-     * UART2 Mod	4806c000 - 4806cfff
+-     * UART2 L4		4806d000 - 4806dfff
+-     * UART3 Mod	4806e000 - 4806efff
+-     * UART3 L4		4806f000 - 4806ffff
+-     * I2C1 Mod		48070000 - 48070fff
+-     * I2C1 L4		48071000 - 48071fff
+-     * I2C2 Mod		48072000 - 48072fff
+-     * I2C2 L4		48073000 - 48073fff
+-     * McBSP1 Mod	48074000 - 48074fff
+-     * McBSP1 L4	48075000 - 48075fff
+-     * McBSP2 Mod	48076000 - 48076fff
+-     * McBSP2 L4	48077000 - 48077fff
+-     * GPTIMER3 Mod	48078000 - 48078fff
+-     * GPTIMER3 L4	48079000 - 48079fff
+-     * GPTIMER4 Mod	4807a000 - 4807afff
+-     * GPTIMER4 L4	4807b000 - 4807bfff
+-     * GPTIMER5 Mod	4807c000 - 4807cfff
+-     * GPTIMER5 L4	4807d000 - 4807dfff
+-     * GPTIMER6 Mod	4807e000 - 4807efff
+-     * GPTIMER6 L4	4807f000 - 4807ffff
+-     * GPTIMER7 Mod	48080000 - 48080fff
+-     * GPTIMER7 L4	48081000 - 48081fff
+-     * GPTIMER8 Mod	48082000 - 48082fff
+-     * GPTIMER8 L4	48083000 - 48083fff
+-     * GPTIMER9 Mod	48084000 - 48084fff
+-     * GPTIMER9 L4	48085000 - 48085fff
+-     * GPTIMER10 Mod	48086000 - 48086fff
+-     * GPTIMER10 L4	48087000 - 48087fff
+-     * GPTIMER11 Mod	48088000 - 48088fff
+-     * GPTIMER11 L4	48089000 - 48089fff
+-     * GPTIMER12 Mod	4808a000 - 4808afff
+-     * GPTIMER12 L4	4808b000 - 4808bfff
+-     * EAC Mod		48090000 - 48090fff
+-     * EAC L4		48091000 - 48091fff
+-     * FAC Mod		48092000 - 48092fff
+-     * FAC L4		48093000 - 48093fff
+-     * MAILBOX Mod	48094000 - 48094fff
+-     * MAILBOX L4	48095000 - 48095fff
+-     * SPI1 Mod		48098000 - 48098fff
+-     * SPI1 L4		48099000 - 48099fff
+-     * SPI2 Mod		4809a000 - 4809afff
+-     * SPI2 L4		4809b000 - 4809bfff
+-     * MMC/SDIO Mod	4809c000 - 4809cfff
+-     * MMC/SDIO L4	4809d000 - 4809dfff
+-     * MS_PRO Mod	4809e000 - 4809efff
+-     * MS_PRO L4	4809f000 - 4809ffff
+-     * RNG Mod		480a0000 - 480a0fff
+-     * RNG L4		480a1000 - 480a1fff
+-     * DES3DES Mod	480a2000 - 480a2fff
+-     * DES3DES L4	480a3000 - 480a3fff
+-     * SHA1MD5 Mod	480a4000 - 480a4fff
+-     * SHA1MD5 L4	480a5000 - 480a5fff
+-     * AES Mod		480a6000 - 480a6fff
+-     * AES L4		480a7000 - 480a7fff
+-     * PKA Mod		480a8000 - 480a9fff
+-     * PKA L4		480aa000 - 480aafff
+-     * MG Mod		480b0000 - 480b0fff
+-     * MG L4		480b1000 - 480b1fff
+-     * HDQ/1-wire Mod	480b2000 - 480b2fff
+-     * HDQ/1-wire L4	480b3000 - 480b3fff
+-     * MPU interrupt	480fe000 - 480fefff
+-     * IVA RAM		5c000000 - 5c01ffff
+-     * IVA ROM		5c020000 - 5c027fff
+-     * IMG_BUF_A	5c040000 - 5c040fff
+-     * IMG_BUF_B	5c042000 - 5c042fff
+-     * VLCDS		5c048000 - 5c0487ff
+-     * IMX_COEF		5c049000 - 5c04afff
+-     * IMX_CMD		5c051000 - 5c051fff
+-     * VLCDQ		5c053000 - 5c0533ff
+-     * VLCDH		5c054000 - 5c054fff
+-     * SEQ_CMD		5c055000 - 5c055fff
+-     * IMX_REG		5c056000 - 5c0560ff
+-     * VLCD_REG		5c056100 - 5c0561ff
+-     * SEQ_REG		5c056200 - 5c0562ff
+-     * IMG_BUF_REG	5c056300 - 5c0563ff
+-     * SEQIRQ_REG	5c056400 - 5c0564ff
+-     * OCP_REG		5c060000 - 5c060fff
+-     * SYSC_REG		5c070000 - 5c070fff
+-     * MMU_REG		5d000000 - 5d000fff
++     * ARM11ETB Mod	48048000 - 48049fff (REV 0x00000011)
++     * ARM11ETB L4	4804a000 - 4804afff (0x00200010, 0x00000200, 0x00000000)
++     * DISPLAY Top	48050000 - 480503ff (REV 0x00000003)
++     * DISPLAY DISPC	48050400 - 480507ff (REV 0x00000020)
++     * DISPLAY RFBI	48050800 - 48050bff (REV 0x00000010)
++     * DISPLAY VENC	48050c00 - 48050fff (REV Abort)
++     * DISPLAY L4	48051000 - 48051fff (0x00200010, 0x00000200, 0x00000100)
++     * CAMERA Top	48052000 - 480523ff (REV 0x00000020)
++     * CAMERA core	48052400 - 480527ff (REV 0x00000020)
++     * CAMERA DMA	48052800 - 48052bff (REV 0x00000020)
++     * CAMERA MMU	48052c00 - 48052fff (REV 0x00000010)
++     * CAMERA L4	48053000 - 48053fff (0x00200010, 0x00000200, 0x00000000)
++     * SDMA Mod		48056000 - 48056fff (REV 0x00000020)
++     * SDMA L4		48057000 - 48057fff (0x00200010, 0x00000200, 0x00000000)
++     * SSI Top		48058000 - 48058fff (REV Abort)
++     * SSI GDD		48059000 - 48059fff (REV Abort)
++     * SSI Port1	4805a000 - 4805afff (REV Abort)
++     * SSI Port2	4805b000 - 4805bfff (REV Abort)
++     * SSI L4		4805c000 - 4805cfff (0x00200010, 0x00000200, 0x00000100)
++     * USB Mod		4805e000 - 480fefff (REV Abort)
++     * USB L4		4805f000 - 480fffff (0x00200010, 0x01000200, 0x00000100)
++     * WIN_TRACER1 Mod	48060000 - 48060fff (REV 0x00000020)
++     * WIN_TRACER1 L4	48061000 - 48061fff (0x00200010, 0x00000200, 0x00000000)
++     * WIN_TRACER2 Mod	48062000 - 48062fff (REV 0x00000020)
++     * WIN_TRACER2 L4	48063000 - 48063fff (0x00200010, 0x00000200, 0x00000000)
++     * WIN_TRACER3 Mod	48064000 - 48064fff (REV 0x00000020)
++     * WIN_TRACER3 L4	48065000 - 48065fff (0x00200010, 0x00000200, 0x00000000)
++     * WIN_TRACER4 Top	48066000 - 480660ff (REV 0x00000011)
++     * WIN_TRACER4 ETT	48066100 - 480661ff (REV 0x00000011)
++     * WIN_TRACER4 WT	48066200 - 480662ff (REV 0x00000020)
++     * WIN_TRACER4 L4	48067000 - 48067fff (0x00200010, 0x00000200, 0x00000000)
++     * XTI Mod		48068000 - 48068fff (REV 0x00000010)
++     * XTI L4		48069000 - 48069fff (0x00200010, 0x00000200, 0x00000000)
++     * UART1 Mod	4806a000 - 4806afff (MVR Abort)
++     * UART1 L4		4806b000 - 4806bfff (0x00200010, 0x00000200, 0x00000000)
++     * UART2 Mod	4806c000 - 4806cfff (MVR Abort)
++     * UART2 L4		4806d000 - 4806dfff (0x00200010, 0x00000200, 0x00000000)
++     * UART3 Mod	4806e000 - 4806efff (MVR 0x20)
++     * UART3 L4		4806f000 - 4806ffff (0x00200010, 0x00000200, 0x00000000)
++     * I2C1 Mod		48070000 - 48070fff (REV 0x0034)
++     * I2C1 L4		48071000 - 48071fff (0x00200010, 0x01000200, 0x01000000)
++     * I2C2 Mod		48072000 - 48072fff (REV 0x0034)
++     * I2C2 L4		48073000 - 48073fff (0x00200010, 0x01000200, 0x01000000)
++     * McBSP1 Mod	48074000 - 48074fff (REV Abort)
++     * McBSP1 L4	48075000 - 48075fff (0x00200010, 0x01000200, 0x01000000)
++     * McBSP2 Mod	48076000 - 48076fff (REV Abort)
++     * McBSP2 L4	48077000 - 48077fff (0x00200010, 0x01000200, 0x01000000)
++     * GPTIMER3 Mod	48078000 - 48078fff (REV Abort)
++     * GPTIMER3 L4	48079000 - 48079fff (0x00200010, 0x00000200, 0x00000000)
++     * GPTIMER4 Mod	4807a000 - 4807afff (REV Abort)
++     * GPTIMER4 L4	4807b000 - 4807bfff (0x00200010, 0x00000200, 0x00000000)
++     * GPTIMER5 Mod	4807c000 - 4807cfff (REV Abort)
++     * GPTIMER5 L4	4807d000 - 4807dfff (0x00200010, 0x00000200, 0x00000000)
++     * GPTIMER6 Mod	4807e000 - 4807efff (REV Abort)
++     * GPTIMER6 L4	4807f000 - 4807ffff (0x00200010, 0x00000200, 0x00000000)
++     * GPTIMER7 Mod	48080000 - 48080fff (REV Abort)
++     * GPTIMER7 L4	48081000 - 48081fff (0x00200010, 0x00000200, 0x00000000)
++     * GPTIMER8 Mod	48082000 - 48082fff (REV Abort)
++     * GPTIMER8 L4	48083000 - 48083fff (0x00200010, 0x00000200, 0x00000000)
++     * GPTIMER9 Mod	48084000 - 48084fff (REV Abort)
++     * GPTIMER9 L4	48085000 - 48085fff (0x00200010, 0x00000200, 0x00000000)
++     * GPTIMER10 Mod	48086000 - 48086fff (REV Abort)
++     * GPTIMER10 L4	48087000 - 48087fff (0x00200010, 0x00000200, 0x00000000)
++     * GPTIMER11 Mod	48088000 - 48088fff (REV Abort)
++     * GPTIMER11 L4	48089000 - 48089fff (0x00200010, 0x00000200, 0x00000000)
++     * GPTIMER12 Mod	4808a000 - 4808afff (REV Abort)
++     * GPTIMER12 L4	4808b000 - 4808bfff (0x00200010, 0x00000200, 0x00000000)
++     * EAC Mod		48090000 - 48090fff (REV Abort)
++     * EAC L4		48091000 - 48091fff (0x00200010, 0x00000200, 0x00000000)
++     * FAC Mod		48092000 - 48092fff (REV Abort)
++     * FAC L4		48093000 - 48093fff (0x00200010, 0x00000200, 0x00000000)
++     * MAILBOX Mod	48094000 - 48094fff (REV 0x00000010)
++     * MAILBOX L4	48095000 - 48095fff (0x00200010, 0x00000200, 0x00000000)
++     * SPI1 Mod		48098000 - 48098fff (REV Abort)
++     * SPI1 L4		48099000 - 48099fff (0x00200010, 0x00000200, 0x00000000)
++     * SPI2 Mod		4809a000 - 4809afff (REV Abort)
++     * SPI2 L4		4809b000 - 4809bfff (0x00200010, 0x00000200, 0x00000000)
++     * MMC/SDIO Mod	4809c000 - 4809cfff (REV 0x0044)
++     * MMC/SDIO L4	4809d000 - 4809dfff (0x00200010, 0x01000200, 0x01000000)
++     * MS_PRO Mod	4809e000 - 4809efff (REV Abort)
++     * MS_PRO L4	4809f000 - 4809ffff (0x00200010, 0x01000200, 0x01000000)
++     * RNG Mod		480a0000 - 480a0fff (REV 0xFC066F93?)
++     * RNG L4		480a1000 - 480a1fff (0x00200010, 0x01000200, 0x00000000)
++     * DES3DES Mod	480a2000 - 480a2fff (REV 0x00000000?)
++     * DES3DES L4	480a3000 - 480a3fff (0x00200010, 0x01000200, 0x00000000)
++     * SHA1MD5 Mod	480a4000 - 480a4fff (REV 0x00000000?)
++     * SHA1MD5 L4	480a5000 - 480a5fff (0x00200010, 0x01000200, 0x00000000)
++     * AES Mod		480a6000 - 480a6fff (REV 0x00000000?)
++     * AES L4		480a7000 - 480a7fff (0x00200010, 0x00000200, 0x00000000)
++     * PKA Mod		480a8000 - 480a9fff (REV 0x00000000?)
++     * PKA L4		480aa000 - 480aafff (0x00200010, 0x00000200, 0x00000000)
++     * MG Mod		480b0000 - 480b0fff (REV Abort)
++     * MG L4		480b1000 - 480b1fff (0x00200010, 0x01000200, 0x01000000)
++     * HDQ/1-wire Mod	480b2000 - 480b2fff (REV 0x00000002)
++     * HDQ/1-wire L4	480b3000 - 480b3fff (0x00200010, 0x00000200, 0x00000000)
++     * MPU interrupt	480fe000 - 480fefff (REV 0x00000020)
++     * IVA RAM		5c000000 - 5c01ffff (REV Abort)
++     * IVA ROM		5c020000 - 5c027fff (REV Abort)
++     * IMG_BUF_A	5c040000 - 5c040fff (REV Abort)
++     * IMG_BUF_B	5c042000 - 5c042fff (REV Abort)
++     * VLCDS		5c048000 - 5c0487ff (REV Abort)
++     * IMX_COEF		5c049000 - 5c04afff (REV Abort)
++     * IMX_CMD		5c051000 - 5c051fff (REV Abort)
++     * VLCDQ		5c053000 - 5c0533ff (REV Abort)
++     * VLCDH		5c054000 - 5c054fff (REV Abort)
++     * SEQ_CMD		5c055000 - 5c055fff (REV Abort)
++     * IMX_REG		5c056000 - 5c0560ff (REV Abort)
++     * VLCD_REG		5c056100 - 5c0561ff (REV Abort)
++     * SEQ_REG		5c056200 - 5c0562ff (REV Abort)
++     * IMG_BUF_REG	5c056300 - 5c0563ff (REV Abort)
++     * SEQIRQ_REG	5c056400 - 5c0564ff (REV Abort)
++     * OCP_REG		5c060000 - 5c060fff (REV Abort)
++     * SYSC_REG		5c070000 - 5c070fff (REV Abort)
++     * MMU_REG		5d000000 - 5d000fff (REV Abort)
+      * sDMA R		68000400 - 680005ff
+      * sDMA W		68000600 - 680007ff
+      * Display Control	68000800 - 680009ff
+@@ -3849,9 +3849,9 @@
+      * GPMC (firewall)	68006000 - 680063ff
+      * GPMC (err login)	68006400 - 680067ff
+      * SMS (err login)	68006c00 - 68006fff
+-     * SMS registers	68008000 - 68008fff
+-     * SDRC registers	68009000 - 68009fff
+-     * GPMC registers	6800a000   6800afff
++     * SMS registers	68008000 - 68008fff (REV 0x00000020)
++     * SDRC registers	68009000 - 68009fff (REV 0x00000020)
++     * GPMC registers	6800a000   6800afff (REV 0x00000020)
+      */
+ 
+     qemu_register_reset(omap2_mpu_reset, s);
+diff -urN 4242/hw/pc.c qemu-omap/hw/pc.c
+--- 4242/hw/pc.c	2008-04-24 21:26:22.000000000 +0100
++++ qemu-omap/hw/pc.c	2008-04-23 09:57:56.000000000 +0100
+@@ -445,6 +445,37 @@
+     bdrv_set_boot_sector(drives_table[hda].bdrv, bootsect, sizeof(bootsect));
  }
-@@ -1020,9 +1117,19 @@ struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio)
-     s->precision = s->nextprecision = 0;
-     s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s);
-     s->pint = pint;
-+    s->model = 0x2102;
-     s->name = "tsc2102";
-     s->audio = audio;
  
-+    s->tr[0] = 0;
-+    s->tr[1] = 1;
-+    s->tr[2] = 0;
-+    s->tr[3] = 1;
-+    s->tr[4] = 1;
-+    s->tr[5] = 0;
-+    s->tr[6] = 0;
-+    s->tr[7] = 1;
-+
-     s->chip.opaque = s;
-     s->chip.send = (void *) tsc210x_write;
-     s->chip.receive = (void *) tsc210x_read;
-@@ -1048,9 +1155,147 @@ struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio)
-     return &s->chip;
++static int load_kernel(const char *filename, uint8_t *addr,
++                       uint8_t *real_addr)
++{
++    int fd, size;
++    int setup_sects;
++
++    fd = open(filename, O_RDONLY | O_BINARY);
++    if (fd < 0)
++        return -1;
++
++    /* load 16 bit code */
++    if (read(fd, real_addr, 512) != 512)
++        goto fail;
++    setup_sects = real_addr[0x1F1];
++    if (!setup_sects)
++        setup_sects = 4;
++    if (read(fd, real_addr + 512, setup_sects * 512) !=
++        setup_sects * 512)
++        goto fail;
++
++    /* load 32 bit code */
++    size = read(fd, addr, 16 * 1024 * 1024);
++    if (size < 0)
++        goto fail;
++    close(fd);
++    return size;
++ fail:
++    close(fd);
++    return -1;
++}
++
+ static long get_file_size(FILE *f)
+ {
+     long where, size;
+diff -urN 4242/hw/tusb6010.c qemu-omap/hw/tusb6010.c
+--- 4242/hw/tusb6010.c	2008-04-23 12:18:54.000000000 +0100
++++ qemu-omap/hw/tusb6010.c	2008-04-23 09:57:56.000000000 +0100
+@@ -287,9 +287,6 @@
+     /* TODO: How is this signalled?  */
  }
  
-+struct uwire_slave_s *tsc2301_init(qemu_irq penirq, qemu_irq kbirq,
-+                qemu_irq dav, AudioState *audio)
-+{
-+    struct tsc210x_state_s *s;
-+
-+    s = (struct tsc210x_state_s *)
-+            qemu_mallocz(sizeof(struct tsc210x_state_s));
-+    memset(s, 0, sizeof(struct tsc210x_state_s));
-+    s->x = 400;
-+    s->y = 240;
-+    s->pressure = 0;
-+    s->precision = s->nextprecision = 0;
-+    s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s);
-+    s->pint = penirq;
-+    s->kbint = kbirq;
-+    s->davint = dav;
-+    s->model = 0x2301;
-+    s->name = "tsc2301";
-+    s->audio = audio;
-+
-+    s->tr[0] = 0;
-+    s->tr[1] = 1;
-+    s->tr[2] = 0;
-+    s->tr[3] = 1;
-+    s->tr[4] = 1;
-+    s->tr[5] = 0;
-+    s->tr[6] = 0;
-+    s->tr[7] = 1;
-+
-+    s->chip.opaque = s;
-+    s->chip.send = (void *) tsc210x_write;
-+    s->chip.receive = (void *) tsc210x_read;
-+
-+    s->codec.opaque = s;
-+    s->codec.tx_swallow = (void *) tsc210x_i2s_swallow;
-+    s->codec.set_rate = (void *) tsc210x_i2s_set_rate;
-+    s->codec.in.fifo = s->in_fifo;
-+    s->codec.out.fifo = s->out_fifo;
-+
-+    tsc210x_reset(s);
-+
-+    qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1,
-+                    "QEMU TSC2301-driven Touchscreen");
-+
-+    if (s->audio)
-+        AUD_register_card(s->audio, s->name, &s->card);
-+
-+    qemu_register_reset((void *) tsc210x_reset, s);
-+    register_savevm(s->name, tsc2102_iid ++, 0,
-+                    tsc210x_save, tsc210x_load, s);
-+
-+    return &s->chip;
-+}
-+
- struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip)
+-extern CPUReadMemoryFunc *musb_read[];
+-extern CPUWriteMemoryFunc *musb_write[];
+-
+ static uint32_t tusb_async_readb(void *opaque, target_phys_addr_t addr)
  {
-     struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque;
- 
-     return &s->codec;
- }
-+
-+/*
-+ * Use tslib generated calibration data to generate ADC input values
-+ * from the touchscreen.  Assuming 12-bit precision was used during
-+ * tslib calibration.
-+ */
-+void tsc210x_set_transform(struct uwire_slave_s *chip,
-+                struct mouse_transform_info_s *info)
-+{
-+    struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque;
-+#if 0
-+    int64_t ltr[8];
-+
-+    ltr[0] = (int64_t) info->a[1] * info->y;
-+    ltr[1] = (int64_t) info->a[4] * info->x;
-+    ltr[2] = (int64_t) info->a[1] * info->a[3] -
-+            (int64_t) info->a[4] * info->a[0];
-+    ltr[3] = (int64_t) info->a[2] * info->a[4] -
-+            (int64_t) info->a[5] * info->a[1];
-+    ltr[4] = (int64_t) info->a[0] * info->y;
-+    ltr[5] = (int64_t) info->a[3] * info->x;
-+    ltr[6] = (int64_t) info->a[4] * info->a[0] -
-+            (int64_t) info->a[1] * info->a[3];
-+    ltr[7] = (int64_t) info->a[2] * info->a[3] -
-+            (int64_t) info->a[5] * info->a[0];
-+
-+    /* Avoid integer overflow */
-+    s->tr[0] = ltr[0] >> 11;
-+    s->tr[1] = ltr[1] >> 11;
-+    s->tr[2] = muldiv64(ltr[2], 1, info->a[6]);
-+    s->tr[3] = muldiv64(ltr[3], 1 << 4, ltr[2]);
-+    s->tr[4] = ltr[4] >> 11;
-+    s->tr[5] = ltr[5] >> 11;
-+    s->tr[6] = muldiv64(ltr[6], 1, info->a[6]);
-+    s->tr[7] = muldiv64(ltr[7], 1 << 4, ltr[6]);
-+#else
-+
-+    if (abs(info->a[0]) > abs(info->a[1])) {
-+        s->tr[0] = 0;
-+        s->tr[1] = -info->a[6] * info->x;
-+        s->tr[2] = info->a[0];
-+        s->tr[3] = -info->a[2] / info->a[0];
-+        s->tr[4] = info->a[6] * info->y;
-+        s->tr[5] = 0;
-+        s->tr[6] = info->a[4];
-+        s->tr[7] = -info->a[5] / info->a[4];
-+    } else {
-+        s->tr[0] = info->a[6] * info->y;
-+        s->tr[1] = 0;
-+        s->tr[2] = info->a[1];
-+        s->tr[3] = -info->a[2] / info->a[1];
-+        s->tr[4] = 0;
-+        s->tr[5] = -info->a[6] * info->x;
-+        s->tr[6] = info->a[3];
-+        s->tr[7] = -info->a[5] / info->a[3];
-+    }
-+
-+    s->tr[0] >>= 11;
-+    s->tr[1] >>= 11;
-+    s->tr[3] <<= 4;
-+    s->tr[4] >>= 11;
-+    s->tr[5] >>= 11;
-+    s->tr[7] <<= 4;
+     struct tusb_s *s = (struct tusb_s *) opaque;
+diff -urN 4242/hw/usb.h qemu-omap/hw/usb.h
+--- 4242/hw/usb.h	2008-04-23 12:18:54.000000000 +0100
++++ qemu-omap/hw/usb.h	2008-04-23 09:57:56.000000000 +0100
+@@ -219,6 +219,9 @@
+ /* usb-msd.c */
+ USBDevice *usb_msd_init(const char *filename);
+ 
++/* usb-net.c */
++USBDevice *usb_net_init(NICInfo *nd);
++
+ /* usb-wacom.c */
+ USBDevice *usb_wacom_init(void);
+ 
+@@ -254,3 +257,7 @@
+ uint32_t musb_core_intr_get(struct musb_s *s);
+ void musb_core_intr_clear(struct musb_s *s, uint32_t mask);
+ void musb_set_size(struct musb_s *s, int epnum, int size, int is_tx);
++#ifdef NEED_CPU_H
++extern CPUReadMemoryFunc *musb_read[];
++extern CPUWriteMemoryFunc *musb_write[];
 +#endif
-+}
-+
-+void tsc210x_key_event(struct uwire_slave_s *chip, int key, int down)
-+{
-+    struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque;
-+
-+    if (down)
-+        s->kb.down |= 1 << key;
-+    else
-+        s->kb.down &= ~(1 << key);
-+
-+    if (down && (s->kb.down & ~s->kb.mask) && !s->kb.intr) {
-+        s->kb.intr = 1;
-+        qemu_irq_lower(s->kbint);
-+    } else if (s->kb.intr && !(s->kb.down & ~s->kb.mask) &&
-+                    !(s->kb.mode & 1)) {
-+        s->kb.intr = 0;
-+        qemu_irq_raise(s->kbint);
-+    }
-+}
-diff --git a/hw/twl92230.c b/hw/twl92230.c
-new file mode 100644
-index 0000000..11a5d1a
---- /dev/null
-+++ b/hw/twl92230.c
-@@ -0,0 +1,923 @@
+diff -urN 4242/hw/usb-hub.c qemu-omap/hw/usb-hub.c
+--- 4242/hw/usb-hub.c	2008-04-23 11:43:37.000000000 +0100
++++ qemu-omap/hw/usb-hub.c	2008-04-23 09:57:56.000000000 +0100
+@@ -146,8 +146,8 @@
+ 	0x07,       /*  u8  ep_bLength; */
+ 	0x05,       /*  u8  ep_bDescriptorType; Endpoint */
+ 	0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
+- 	0x03,       /*  u8  ep_bmAttributes; Interrupt */
+- 	0x02, 0x00, /*  u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
++	0x03,       /*  u8  ep_bmAttributes; Interrupt */
++	0x02, 0x00, /*  u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
+ 	0xff        /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+ };
+ 
+diff -urN 4242/hw/usb-net.c qemu-omap/hw/usb-net.c
+--- 4242/hw/usb-net.c	1970-01-01 01:00:00.000000000 +0100
++++ qemu-omap/hw/usb-net.c	2008-04-23 09:57:56.000000000 +0100
+@@ -0,0 +1,1334 @@
 +/*
-+ * TI TWL92230C energy-management companion device for the OMAP24xx.
-+ * Aka. Menelaus (N4200 MENELAUS1_V2.2)
-+ *
-+ * Copyright (C) 2008 Nokia Corporation
-+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation; either version 2 of
-+ * the License, or (at your option) any later version.
++ * QEMU USB Net devices
++ * 
++ * Copyright (c) 2006 Thomas Sailer
++ * based on usb-hid.c Copyright (c) 2005 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:
 + *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
 + *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-+ * MA 02111-1307 USA
++ * 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 "hw.h"
-+#include "qemu-timer.h"
-+#include "i2c.h"
-+#include "sysemu.h"
-+#include "console.h"
-+
-+#define VERBOSE 1
-+
-+struct menelaus_s {
-+    i2c_slave i2c;
-+    qemu_irq irq;
-+
-+    int firstbyte;
-+    uint8_t reg;
-+
-+    uint8_t vcore[5];
-+    uint8_t dcdc[3];
-+    uint8_t ldo[8];
-+    uint8_t sleep[2];
-+    uint8_t osc;
-+    uint8_t detect;
-+    uint16_t mask;
-+    uint16_t status;
-+    uint8_t dir;
-+    uint8_t inputs;
-+    uint8_t outputs;
-+    uint8_t bbsms;
-+    uint8_t pull[4];
-+    uint8_t mmc_ctrl[3];
-+    uint8_t mmc_debounce;
-+    struct {
-+        uint8_t ctrl;
-+        uint16_t comp;
-+        QEMUTimer *hz;
-+        int64_t next;
-+        struct tm tm;
-+        struct tm new;
-+        struct tm alm;
-+        time_t sec;
-+        time_t alm_sec;
-+        time_t next_comp;
-+        struct tm *(*gettime)(const time_t *timep, struct tm *result);
-+    } rtc;
-+    qemu_irq handler[3];
-+    qemu_irq *in;
-+    int pwrbtn_state;
-+    qemu_irq pwrbtn;
-+};
-+
-+static inline void menelaus_update(struct menelaus_s *s)
-+{
-+    qemu_set_irq(s->irq, s->status & ~s->mask);
-+}
-+
-+static inline void menelaus_rtc_start(struct menelaus_s *s)
-+{
-+    s->rtc.next =+ qemu_get_clock(rt_clock);
-+    qemu_mod_timer(s->rtc.hz, s->rtc.next);
-+}
-+
-+static inline void menelaus_rtc_stop(struct menelaus_s *s)
-+{
-+    qemu_del_timer(s->rtc.hz);
-+    s->rtc.next =- qemu_get_clock(rt_clock);
-+    if (s->rtc.next < 1)
-+        s->rtc.next = 1;
-+}
-+
-+static void menelaus_rtc_update(struct menelaus_s *s)
-+{
-+    s->rtc.gettime(&s->rtc.sec, &s->rtc.tm);
-+}
-+
-+static void menelaus_alm_update(struct menelaus_s *s)
-+{
-+    if ((s->rtc.ctrl & 3) == 3)
-+        s->rtc.alm_sec = mktime(&s->rtc.alm);
-+}
-+
-+static void menelaus_rtc_hz(void *opaque)
-+{
-+    struct menelaus_s *s = (struct menelaus_s *) opaque;
-+
-+    s->rtc.sec ++;
-+    s->rtc.next += 1000;
-+    qemu_mod_timer(s->rtc.hz, s->rtc.next);
-+    if ((s->rtc.ctrl >> 3) & 3) {				/* EVERY */
-+        menelaus_rtc_update(s);
-+        if (((s->rtc.ctrl >> 3) & 3) == 1 && !s->rtc.tm.tm_sec)
-+            s->status |= 1 << 8;				/* RTCTMR */
-+        else if (((s->rtc.ctrl >> 3) & 3) == 2 && !s->rtc.tm.tm_min)
-+            s->status |= 1 << 8;				/* RTCTMR */
-+        else if (!s->rtc.tm.tm_hour)
-+            s->status |= 1 << 8;				/* RTCTMR */
-+    } else
-+        s->status |= 1 << 8;					/* RTCTMR */
-+    if ((s->rtc.ctrl >> 1) & 1) {				/* RTC_AL_EN */
-+        if (s->rtc.sec == s->rtc.alm_sec)
-+            s->status |= 1 << 9;				/* RTCALM */
-+        /* TODO: wake-up */
-+    }
-+    if (s->rtc.next_comp >= s->rtc.sec) {
-+        s->rtc.next -= muldiv64((int16_t) s->rtc.comp, 1000, 0x8000);
-+        s->rtc.next_comp = s->rtc.sec + 3600;
-+    }
-+    menelaus_update(s);
-+}
-+
-+void menelaus_reset(i2c_slave *i2c)
-+{
-+    struct menelaus_s *s = (struct menelaus_s *) i2c;
-+    time_t ti;
-+    s->reg = 0x00;
-+
-+    s->vcore[0] = 0x0c;	/* XXX: X-loader needs 0x8c? check!  */
-+    s->vcore[1] = 0x05;
-+    s->vcore[2] = 0x02;
-+    s->vcore[3] = 0x0c;
-+    s->vcore[4] = 0x03;
-+    s->dcdc[0] = 0x33;	/* Depends on wiring */
-+    s->dcdc[1] = 0x03;
-+    s->dcdc[2] = 0x00;
-+    s->ldo[0] = 0x95;
-+    s->ldo[1] = 0x7e;
-+    s->ldo[2] = 0x00;
-+    s->ldo[3] = 0x00;	/* Depends on wiring */
-+    s->ldo[4] = 0x03;	/* Depends on wiring */
-+    s->ldo[5] = 0x00;
-+    s->ldo[6] = 0x00;
-+    s->ldo[7] = 0x00;
-+    s->sleep[0] = 0x00;
-+    s->sleep[1] = 0x00;
-+    s->osc = 0x01;
-+    s->detect = 0x09;
-+    s->mask = 0x0fff;
-+    s->status = 0;
-+    s->dir = 0x07;
-+    s->outputs = 0x00;
-+    s->bbsms = 0x00;
-+    s->pull[0] = 0x00;
-+    s->pull[1] = 0x00;
-+    s->pull[2] = 0x00;
-+    s->pull[3] = 0x00;
-+    s->mmc_ctrl[0] = 0x03;
-+    s->mmc_ctrl[1] = 0xc0;
-+    s->mmc_ctrl[2] = 0x00;
-+    s->mmc_debounce = 0x05;
-+
-+    time(&ti);
-+    if (s->rtc.ctrl & 1)
-+        menelaus_rtc_stop(s);
-+    s->rtc.ctrl = 0x00;
-+    s->rtc.comp = 0x0000;
-+    s->rtc.next = 1000;
-+    s->rtc.sec = ti;
-+    s->rtc.next_comp = s->rtc.sec + 1800;
-+    s->rtc.alm.tm_sec = 0x00;
-+    s->rtc.alm.tm_min = 0x00;
-+    s->rtc.alm.tm_hour = 0x00;
-+    s->rtc.alm.tm_mday = 0x01;
-+    s->rtc.alm.tm_mon = 0x00;
-+    s->rtc.alm.tm_year = 2004;
-+    menelaus_update(s);
-+}
-+
-+static inline uint8_t to_bcd(int val)
-+{
-+    return ((val / 10) << 4) | (val % 10);
-+}
-+
-+static inline int from_bcd(uint8_t val)
-+{
-+    return ((val >> 4) * 10) + (val & 0x0f);
-+}
-+
-+static void menelaus_gpio_set(void *opaque, int line, int level)
-+{
-+    struct menelaus_s *s = (struct menelaus_s *) opaque;
-+
-+    /* No interrupt generated */
-+    s->inputs &= ~(1 << line);
-+    s->inputs |= level << line;
-+}
-+
-+static void menelaus_pwrbtn_set(void *opaque, int line, int level)
-+{
-+    struct menelaus_s *s = (struct menelaus_s *) opaque;
-+
-+    if (!s->pwrbtn_state && level) {
-+        s->status |= 1 << 11;					/* PSHBTN */
-+        menelaus_update(s);
-+    }
-+    s->pwrbtn_state = level;
-+}
-+
-+#define MENELAUS_REV		0x01
-+#define MENELAUS_VCORE_CTRL1	0x02
-+#define MENELAUS_VCORE_CTRL2	0x03
-+#define MENELAUS_VCORE_CTRL3	0x04
-+#define MENELAUS_VCORE_CTRL4	0x05
-+#define MENELAUS_VCORE_CTRL5	0x06
-+#define MENELAUS_DCDC_CTRL1	0x07
-+#define MENELAUS_DCDC_CTRL2	0x08
-+#define MENELAUS_DCDC_CTRL3	0x09
-+#define MENELAUS_LDO_CTRL1	0x0a
-+#define MENELAUS_LDO_CTRL2	0x0b
-+#define MENELAUS_LDO_CTRL3	0x0c
-+#define MENELAUS_LDO_CTRL4	0x0d
-+#define MENELAUS_LDO_CTRL5	0x0e
-+#define MENELAUS_LDO_CTRL6	0x0f
-+#define MENELAUS_LDO_CTRL7	0x10
-+#define MENELAUS_LDO_CTRL8	0x11
-+#define MENELAUS_SLEEP_CTRL1	0x12
-+#define MENELAUS_SLEEP_CTRL2	0x13
-+#define MENELAUS_DEVICE_OFF	0x14
-+#define MENELAUS_OSC_CTRL	0x15
-+#define MENELAUS_DETECT_CTRL	0x16
-+#define MENELAUS_INT_MASK1	0x17
-+#define MENELAUS_INT_MASK2	0x18
-+#define MENELAUS_INT_STATUS1	0x19
-+#define MENELAUS_INT_STATUS2	0x1a
-+#define MENELAUS_INT_ACK1	0x1b
-+#define MENELAUS_INT_ACK2	0x1c
-+#define MENELAUS_GPIO_CTRL	0x1d
-+#define MENELAUS_GPIO_IN	0x1e
-+#define MENELAUS_GPIO_OUT	0x1f
-+#define MENELAUS_BBSMS		0x20
-+#define MENELAUS_RTC_CTRL	0x21
-+#define MENELAUS_RTC_UPDATE	0x22
-+#define MENELAUS_RTC_SEC	0x23
-+#define MENELAUS_RTC_MIN	0x24
-+#define MENELAUS_RTC_HR		0x25
-+#define MENELAUS_RTC_DAY	0x26
-+#define MENELAUS_RTC_MON	0x27
-+#define MENELAUS_RTC_YR		0x28
-+#define MENELAUS_RTC_WKDAY	0x29
-+#define MENELAUS_RTC_AL_SEC	0x2a
-+#define MENELAUS_RTC_AL_MIN	0x2b
-+#define MENELAUS_RTC_AL_HR	0x2c
-+#define MENELAUS_RTC_AL_DAY	0x2d
-+#define MENELAUS_RTC_AL_MON	0x2e
-+#define MENELAUS_RTC_AL_YR	0x2f
-+#define MENELAUS_RTC_COMP_MSB	0x30
-+#define MENELAUS_RTC_COMP_LSB	0x31
-+#define MENELAUS_S1_PULL_EN	0x32
-+#define MENELAUS_S1_PULL_DIR	0x33
-+#define MENELAUS_S2_PULL_EN	0x34
-+#define MENELAUS_S2_PULL_DIR	0x35
-+#define MENELAUS_MCT_CTRL1	0x36
-+#define MENELAUS_MCT_CTRL2	0x37
-+#define MENELAUS_MCT_CTRL3	0x38
-+#define MENELAUS_MCT_PIN_ST	0x39
-+#define MENELAUS_DEBOUNCE1	0x3a
-+
-+static uint8_t menelaus_read(void *opaque, uint8_t addr)
-+{
-+    struct menelaus_s *s = (struct menelaus_s *) opaque;
-+    int reg = 0;
-+
-+    switch (addr) {
-+    case MENELAUS_REV:
-+        return 0x22;
-+
-+    case MENELAUS_VCORE_CTRL5: reg ++;
-+    case MENELAUS_VCORE_CTRL4: reg ++;
-+    case MENELAUS_VCORE_CTRL3: reg ++;
-+    case MENELAUS_VCORE_CTRL2: reg ++;
-+    case MENELAUS_VCORE_CTRL1:
-+        return s->vcore[reg];
-+
-+    case MENELAUS_DCDC_CTRL3: reg ++;
-+    case MENELAUS_DCDC_CTRL2: reg ++;
-+    case MENELAUS_DCDC_CTRL1:
-+        return s->dcdc[reg];
-+
-+    case MENELAUS_LDO_CTRL8: reg ++;
-+    case MENELAUS_LDO_CTRL7: reg ++;
-+    case MENELAUS_LDO_CTRL6: reg ++;
-+    case MENELAUS_LDO_CTRL5: reg ++;
-+    case MENELAUS_LDO_CTRL4: reg ++;
-+    case MENELAUS_LDO_CTRL3: reg ++;
-+    case MENELAUS_LDO_CTRL2: reg ++;
-+    case MENELAUS_LDO_CTRL1:
-+        return s->ldo[reg];
-+
-+    case MENELAUS_SLEEP_CTRL2: reg ++;
-+    case MENELAUS_SLEEP_CTRL1:
-+        return s->sleep[reg];
-+
-+    case MENELAUS_DEVICE_OFF:
-+        return 0;
++#include "qemu-common.h"
++#include "usb.h"
++#include "net.h"
++#include "../audio/sys-queue.h"
 +
-+    case MENELAUS_OSC_CTRL:
-+        return s->osc | (1 << 7);			/* CLK32K_GOOD */
++typedef uint32_t __le32;
++#include "ndis.h"
 +
-+    case MENELAUS_DETECT_CTRL:
-+        return s->detect;
++/*#define TRAFFIC_DEBUG*/
++/* Thanks to NetChip Technologies for donating this product ID.
++ * It's for devices with only CDC Ethernet configurations.
++ */
++#define CDC_VENDOR_NUM          0x0525  /* NetChip */
++#define CDC_PRODUCT_NUM         0xa4a1  /* Linux-USB Ethernet Gadget */
++/* For hardware that can talk RNDIS and either of the above protocols,
++ * use this ID ... the windows INF files will know it.
++ */
++#define RNDIS_VENDOR_NUM        0x0525  /* NetChip */
++#define RNDIS_PRODUCT_NUM       0xa4a2  /* Ethernet/RNDIS Gadget */
++
++#define STRING_MANUFACTURER             1
++#define STRING_PRODUCT                  2
++#define STRING_ETHADDR                  3
++#define STRING_DATA                     4
++#define STRING_CONTROL                  5
++#define STRING_RNDIS_CONTROL            6
++#define STRING_CDC                      7
++#define STRING_SUBSET                   8
++#define STRING_RNDIS                    9
++#define STRING_SERIALNUMBER             10
++
++#define DEV_CONFIG_VALUE        1       /* cdc or subset */
++#define DEV_RNDIS_CONFIG_VALUE  2       /* rndis; optional */
++
++#define USB_CDC_SUBCLASS_ACM                    0x02
++#define USB_CDC_SUBCLASS_ETHERNET               0x06
++
++#define USB_CDC_PROTO_NONE                      0
++#define USB_CDC_ACM_PROTO_VENDOR                0xff
++
++#define USB_CDC_HEADER_TYPE             0x00            /* header_desc */
++#define USB_CDC_CALL_MANAGEMENT_TYPE    0x01            /* call_mgmt_descriptor */
++#define USB_CDC_ACM_TYPE                0x02            /* acm_descriptor */
++#define USB_CDC_UNION_TYPE              0x06            /* union_desc */
++#define USB_CDC_ETHERNET_TYPE           0x0f            /* ether_desc */
++
++#define USB_DT_CS_INTERFACE             0x24
++#define USB_DT_CS_ENDPOINT              0x25
++
++#define ClassInterfaceRequest \
++        ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8)
++#define ClassInterfaceOutRequest \
++        ((USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8)
++
++#define USB_CDC_SEND_ENCAPSULATED_COMMAND       0x00
++#define USB_CDC_GET_ENCAPSULATED_RESPONSE       0x01
++#define USB_CDC_REQ_SET_LINE_CODING             0x20
++#define USB_CDC_REQ_GET_LINE_CODING             0x21
++#define USB_CDC_REQ_SET_CONTROL_LINE_STATE      0x22
++#define USB_CDC_REQ_SEND_BREAK                  0x23
++#define USB_CDC_SET_ETHERNET_MULTICAST_FILTERS  0x40
++#define USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER  0x41
++#define USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER  0x42
++#define USB_CDC_SET_ETHERNET_PACKET_FILTER      0x43
++#define USB_CDC_GET_ETHERNET_STATISTIC          0x44
++
++#define USB_ENDPOINT_XFER_BULK          2
++#define USB_ENDPOINT_XFER_INT           3
++
++#define LOG2_STATUS_INTERVAL_MSEC       5       /* 1 << 5 == 32 msec */
++#define STATUS_BYTECOUNT                16      /* 8 byte header + data */
++
++#define ETH_FRAME_LEN                   1514    /* Max. octets in frame sans FCS */
 +
-+    case MENELAUS_INT_MASK1:
-+        return (s->mask >> 0) & 0xff;
-+    case MENELAUS_INT_MASK2:
-+        return (s->mask >> 8) & 0xff;
++/*
++ * mostly the same descriptor as the linux gadget rndis driver
++ */
++static const uint8_t qemu_net_dev_descriptor[] = {
++	0x12,                /*  u8 bLength; */
++	USB_DT_DEVICE,       /*  u8 bDescriptorType; Device */
++	0x00, 0x02,          /*  u16 bcdUSB; v2.0 */
++	USB_CLASS_COMM,	     /*  u8  bDeviceClass; */
++	0x00,	             /*  u8  bDeviceSubClass; */
++	0x00,                /*  u8  bDeviceProtocol; [ low/full speeds only ] */
++	0x40,                /*  u8  bMaxPacketSize0 */
++	RNDIS_VENDOR_NUM & 0xff, RNDIS_VENDOR_NUM >> 8,   /*  u16 idVendor; */
++ 	RNDIS_PRODUCT_NUM & 0xff, RNDIS_PRODUCT_NUM >> 8, /*  u16 idProduct; */
++	0x00, 0x00,          /*  u16 bcdDevice */
++	STRING_MANUFACTURER, /*  u8  iManufacturer; */
++	STRING_PRODUCT,      /*  u8  iProduct; */
++	STRING_SERIALNUMBER, /*  u8  iSerialNumber; */
++	0x02                 /*  u8  bNumConfigurations; */
++};
++
++static const uint8_t qemu_net_rndis_config_descriptor[] = {
++	/* Configuration Descriptor */
++	0x09,                /*  u8  bLength */
++	USB_DT_CONFIG,       /*  u8  bDescriptorType */
++        0x43, 0x00,          /*  le16 wTotalLength */
++        0x02,                /*  u8  bNumInterfaces */
++        DEV_RNDIS_CONFIG_VALUE, /*  u8  bConfigurationValue */
++        STRING_RNDIS,        /*  u8  iConfiguration */
++        0xc0,                /*  u8  bmAttributes */
++        0x32,                /*  u8  bMaxPower */
++	/* RNDIS Control Interface */
++        0x09,                /*  u8  bLength */
++        USB_DT_INTERFACE,    /*  u8  bDescriptorType */
++        0x00,                /*  u8  bInterfaceNumber */
++        0x00,                /*  u8  bAlternateSetting */
++        0x01,                /*  u8  bNumEndpoints */
++        USB_CLASS_COMM,           /*  u8  bInterfaceClass */
++        USB_CDC_SUBCLASS_ACM,     /*  u8  bInterfaceSubClass */
++        USB_CDC_ACM_PROTO_VENDOR, /*  u8  bInterfaceProtocol */
++        STRING_RNDIS_CONTROL,     /*  u8  iInterface */
++	/* Header Descriptor */
++        0x05,                /*  u8    bLength */
++        USB_DT_CS_INTERFACE, /*  u8    bDescriptorType */
++        USB_CDC_HEADER_TYPE, /*  u8    bDescriptorSubType */
++        0x10, 0x01,          /*  le16  bcdCDC */
++	/* Call Management Descriptor */
++        0x05,                /*  u8    bLength */
++        USB_DT_CS_INTERFACE, /*  u8    bDescriptorType */
++        USB_CDC_CALL_MANAGEMENT_TYPE, /*  u8    bDescriptorSubType */
++        0x00,                /*  u8    bmCapabilities */
++        0x01,                /*  u8    bDataInterface */
++	/* ACM Descriptor */
++        0x04,                /*  u8    bLength */
++        USB_DT_CS_INTERFACE, /*  u8    bDescriptorType */
++        USB_CDC_ACM_TYPE,    /*  u8    bDescriptorSubType */
++        0x00,                /*  u8    bmCapabilities */
++	/* Union Descriptor */
++        0x05,                /*  u8    bLength */
++        USB_DT_CS_INTERFACE, /*  u8    bDescriptorType */
++        USB_CDC_UNION_TYPE,  /*  u8    bDescriptorSubType */
++        0x00,                /*  u8    bMasterInterface0 */
++        0x01,                /*  u8    bSlaveInterface0 */
++	/* Status Descriptor */
++        0x07,                /*  u8  bLength */
++        USB_DT_ENDPOINT,     /*  u8  bDescriptorType */
++        USB_DIR_IN | 1,      /*  u8  bEndpointAddress */
++        USB_ENDPOINT_XFER_INT, /*  u8  bmAttributes */
++        STATUS_BYTECOUNT & 0xff, STATUS_BYTECOUNT >> 8, /*  le16 wMaxPacketSize */
++        1 << LOG2_STATUS_INTERVAL_MSEC, /*  u8  bInterval */
++	/* RNDIS Data Interface */
++        0x09,                /*  u8  bLength */
++        USB_DT_INTERFACE,    /*  u8  bDescriptorType */
++        0x01,                /*  u8  bInterfaceNumber */
++        0x00,                /*  u8  bAlternateSetting */
++        0x02,                /*  u8  bNumEndpoints */
++        USB_CLASS_CDC_DATA,  /*  u8  bInterfaceClass */
++        0x00,                /*  u8  bInterfaceSubClass */
++        0x00,                /*  u8  bInterfaceProtocol */
++        STRING_DATA,         /*  u8  iInterface */
++	/* Source Endpoint */
++        0x07,                /*  u8  bLength */
++        USB_DT_ENDPOINT,     /*  u8  bDescriptorType */
++        USB_DIR_IN | 2,      /*  u8  bEndpointAddress */
++        USB_ENDPOINT_XFER_BULK, /*  u8  bmAttributes */
++        0x40, 0x00,          /*  le16 wMaxPacketSize */
++        0x00,                /*  u8  bInterval */
++	/* Sink Endpoint */
++        0x07,                /*  u8  bLength */
++        USB_DT_ENDPOINT,     /*  u8  bDescriptorType */
++        USB_DIR_OUT | 2,     /*  u8  bEndpointAddress */
++        USB_ENDPOINT_XFER_BULK, /*  u8  bmAttributes */
++        0x40, 0x00,          /*  le16 wMaxPacketSize */
++        0x00                 /*  u8  bInterval */
++};
++
++static const uint8_t qemu_net_cdc_config_descriptor[] = {
++	/* Configuration Descriptor */
++	0x09,                /*  u8  bLength */
++	USB_DT_CONFIG,       /*  u8  bDescriptorType */
++        0x50, 0x00,          /*  le16 wTotalLength */
++        0x02,                /*  u8  bNumInterfaces */
++        DEV_CONFIG_VALUE,    /*  u8  bConfigurationValue */
++        STRING_CDC,          /*  u8  iConfiguration */
++        0xc0,                /*  u8  bmAttributes */
++        0x32,                /*  u8  bMaxPower */
++	/* CDC Control Interface */
++        0x09,                /*  u8  bLength */
++        USB_DT_INTERFACE,    /*  u8  bDescriptorType */
++        0x00,                /*  u8  bInterfaceNumber */
++        0x00,                /*  u8  bAlternateSetting */
++        0x01,                /*  u8  bNumEndpoints */
++        USB_CLASS_COMM,            /*  u8  bInterfaceClass */
++        USB_CDC_SUBCLASS_ETHERNET, /*  u8  bInterfaceSubClass */
++        USB_CDC_PROTO_NONE,        /*  u8  bInterfaceProtocol */
++        STRING_CONTROL,            /*  u8  iInterface */
++	/* Header Descriptor */
++        0x05,                /*  u8    bLength */
++        USB_DT_CS_INTERFACE, /*  u8    bDescriptorType */
++        USB_CDC_HEADER_TYPE, /*  u8    bDescriptorSubType */
++        0x10, 0x01,          /*  le16  bcdCDC */
++	/* Union Descriptor */
++        0x05,                /*  u8    bLength */
++        USB_DT_CS_INTERFACE, /*  u8    bDescriptorType */
++        USB_CDC_UNION_TYPE,  /*  u8    bDescriptorSubType */
++        0x00,                /*  u8    bMasterInterface0 */
++        0x01,                /*  u8    bSlaveInterface0 */
++	/* Ethernet Descriptor */
++        0x0d,                /*  u8    bLength */
++        USB_DT_CS_INTERFACE, /*  u8    bDescriptorType */
++        USB_CDC_ETHERNET_TYPE,  /*  u8    bDescriptorSubType */
++        STRING_ETHADDR,         /*  u8    iMACAddress */
++        0x00, 0x00, 0x00, 0x00, /*  le32  bmEthernetStatistics */
++        ETH_FRAME_LEN & 0xff, ETH_FRAME_LEN >> 8, /*  le16  wMaxSegmentSize */
++        0x00, 0x00,          /*  le16  wNumberMCFilters */
++        0x00,                /*  u8    bNumberPowerFilters */
++	/* Status Descriptor */
++        0x07,                /*  u8  bLength */
++        USB_DT_ENDPOINT,     /*  u8  bDescriptorType */
++        USB_DIR_IN | 1,      /*  u8  bEndpointAddress */
++        USB_ENDPOINT_XFER_INT, /*  u8  bmAttributes */
++        STATUS_BYTECOUNT & 0xff, STATUS_BYTECOUNT >> 8, /*  le16 wMaxPacketSize */
++        1 << LOG2_STATUS_INTERVAL_MSEC, /*  u8  bInterval */
++	/* CDC Data (nop) Interface */
++        0x09,                /*  u8  bLength */
++        USB_DT_INTERFACE,    /*  u8  bDescriptorType */
++        0x01,                /*  u8  bInterfaceNumber */
++        0x00,                /*  u8  bAlternateSetting */
++        0x00,                /*  u8  bNumEndpoints */
++        USB_CLASS_CDC_DATA,  /*  u8  bInterfaceClass */
++        0x00,                /*  u8  bInterfaceSubClass */
++        0x00,                /*  u8  bInterfaceProtocol */
++        0x00,                /*  u8  iInterface */
++	/* CDC Data Interface */
++        0x09,                /*  u8  bLength */
++        USB_DT_INTERFACE,    /*  u8  bDescriptorType */
++        0x01,                /*  u8  bInterfaceNumber */
++        0x01,                /*  u8  bAlternateSetting */
++        0x02,                /*  u8  bNumEndpoints */
++        USB_CLASS_CDC_DATA,  /*  u8  bInterfaceClass */
++        0x00,                /*  u8  bInterfaceSubClass */
++        0x00,                /*  u8  bInterfaceProtocol */
++        STRING_DATA,         /*  u8  iInterface */
++	/* Source Endpoint */
++        0x07,                /*  u8  bLength */
++        USB_DT_ENDPOINT,     /*  u8  bDescriptorType */
++        USB_DIR_IN | 2,      /*  u8  bEndpointAddress */
++        USB_ENDPOINT_XFER_BULK, /*  u8  bmAttributes */
++        0x40, 0x00,          /*  le16 wMaxPacketSize */
++        0x00,                /*  u8  bInterval */
++	/* Sink Endpoint */
++        0x07,                /*  u8  bLength */
++        USB_DT_ENDPOINT,     /*  u8  bDescriptorType */
++        USB_DIR_OUT | 2,     /*  u8  bEndpointAddress */
++        USB_ENDPOINT_XFER_BULK, /*  u8  bmAttributes */
++        0x40, 0x00,          /*  le16 wMaxPacketSize */
++        0x00                 /*  u8  bInterval */
++};
 +
-+    case MENELAUS_INT_STATUS1:
-+        return (s->status >> 0) & 0xff;
-+    case MENELAUS_INT_STATUS2:
-+        return (s->status >> 8) & 0xff;
++/*
++ * RNDIS Status
++ */
 +
-+    case MENELAUS_INT_ACK1:
-+    case MENELAUS_INT_ACK2:
++#define RNDIS_MAXIMUM_FRAME_SIZE        1518
++#define RNDIS_MAX_TOTAL_SIZE            1558
++
++/* Remote NDIS Versions */
++#define RNDIS_MAJOR_VERSION             1
++#define RNDIS_MINOR_VERSION             0
++
++/* Status Values */
++#define RNDIS_STATUS_SUCCESS            0x00000000U     /* Success           */
++#define RNDIS_STATUS_FAILURE            0xC0000001U     /* Unspecified error */
++#define RNDIS_STATUS_INVALID_DATA       0xC0010015U     /* Invalid data      */
++#define RNDIS_STATUS_NOT_SUPPORTED      0xC00000BBU     /* Unsupported request */
++#define RNDIS_STATUS_MEDIA_CONNECT      0x4001000BU     /* Device connected  */
++#define RNDIS_STATUS_MEDIA_DISCONNECT   0x4001000CU     /* Device disconnected */
++
++/* Message Set for Connectionless (802.3) Devices */
++#define REMOTE_NDIS_PACKET_MSG          0x00000001U
++#define REMOTE_NDIS_INITIALIZE_MSG      0x00000002U     /* Initialize device */
++#define REMOTE_NDIS_HALT_MSG            0x00000003U
++#define REMOTE_NDIS_QUERY_MSG           0x00000004U
++#define REMOTE_NDIS_SET_MSG             0x00000005U
++#define REMOTE_NDIS_RESET_MSG           0x00000006U
++#define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007U
++#define REMOTE_NDIS_KEEPALIVE_MSG       0x00000008U
++
++/* Message completion */
++#define REMOTE_NDIS_INITIALIZE_CMPLT    0x80000002U
++#define REMOTE_NDIS_QUERY_CMPLT         0x80000004U
++#define REMOTE_NDIS_SET_CMPLT           0x80000005U
++#define REMOTE_NDIS_RESET_CMPLT         0x80000006U
++#define REMOTE_NDIS_KEEPALIVE_CMPLT     0x80000008U
++
++/* Device Flags */
++#define RNDIS_DF_CONNECTIONLESS         0x00000001U
++#define RNDIS_DF_CONNECTION_ORIENTED    0x00000002U
++
++#define RNDIS_MEDIUM_802_3              0x00000000U
++
++/* from drivers/net/sk98lin/h/skgepnmi.h */
++#define OID_PNP_CAPABILITIES                    0xFD010100
++#define OID_PNP_SET_POWER                       0xFD010101
++#define OID_PNP_QUERY_POWER                     0xFD010102
++#define OID_PNP_ADD_WAKE_UP_PATTERN             0xFD010103
++#define OID_PNP_REMOVE_WAKE_UP_PATTERN          0xFD010104
++#define OID_PNP_ENABLE_WAKE_UP                  0xFD010106
++
++typedef struct rndis_init_msg_type
++{
++        __le32  MessageType;
++        __le32  MessageLength;
++        __le32  RequestID;
++        __le32  MajorVersion;
++        __le32  MinorVersion;
++        __le32  MaxTransferSize;
++} rndis_init_msg_type;
++
++typedef struct rndis_init_cmplt_type
++{
++        __le32  MessageType;
++        __le32  MessageLength;
++        __le32  RequestID;
++        __le32  Status;
++        __le32  MajorVersion;
++        __le32  MinorVersion;
++        __le32  DeviceFlags;
++        __le32  Medium;
++        __le32  MaxPacketsPerTransfer;
++        __le32  MaxTransferSize;
++        __le32  PacketAlignmentFactor;
++        __le32  AFListOffset;
++        __le32  AFListSize;
++} rndis_init_cmplt_type;
++
++typedef struct rndis_halt_msg_type
++{
++        __le32  MessageType;
++        __le32  MessageLength;
++        __le32  RequestID;
++} rndis_halt_msg_type;
++
++typedef struct rndis_query_msg_type
++{
++        __le32  MessageType;
++        __le32  MessageLength;
++        __le32  RequestID;
++        __le32  OID;
++        __le32  InformationBufferLength;
++        __le32  InformationBufferOffset;
++        __le32  DeviceVcHandle;
++} rndis_query_msg_type;
++
++typedef struct rndis_query_cmplt_type
++{
++        __le32  MessageType;
++        __le32  MessageLength;
++        __le32  RequestID;
++        __le32  Status;
++        __le32  InformationBufferLength;
++        __le32  InformationBufferOffset;
++} rndis_query_cmplt_type;
++
++typedef struct rndis_set_msg_type
++{
++        __le32  MessageType;
++        __le32  MessageLength;
++        __le32  RequestID;
++        __le32  OID;
++        __le32  InformationBufferLength;
++        __le32  InformationBufferOffset;
++        __le32  DeviceVcHandle;
++} rndis_set_msg_type;
++
++typedef struct rndis_set_cmplt_type
++{
++        __le32  MessageType;
++        __le32  MessageLength;
++        __le32  RequestID;
++        __le32  Status;
++} rndis_set_cmplt_type;
++
++typedef struct rndis_reset_msg_type
++{
++        __le32  MessageType;
++        __le32  MessageLength;
++        __le32  Reserved;
++} rndis_reset_msg_type;
++
++typedef struct rndis_reset_cmplt_type
++{
++        __le32  MessageType;
++        __le32  MessageLength;
++        __le32  Status;
++        __le32  AddressingReset;
++} rndis_reset_cmplt_type;
++
++typedef struct rndis_indicate_status_msg_type
++{
++        __le32  MessageType;
++        __le32  MessageLength;
++        __le32  Status;
++        __le32  StatusBufferLength;
++        __le32  StatusBufferOffset;
++} rndis_indicate_status_msg_type;
++
++typedef struct rndis_keepalive_msg_type
++{
++        __le32  MessageType;
++        __le32  MessageLength;
++        __le32  RequestID;
++} rndis_keepalive_msg_type;
++
++typedef struct rndis_keepalive_cmplt_type
++{
++        __le32  MessageType;
++        __le32  MessageLength;
++        __le32  RequestID;
++        __le32  Status;
++} rndis_keepalive_cmplt_type;
++
++struct rndis_packet_msg_type
++{
++        __le32  MessageType;
++        __le32  MessageLength;
++        __le32  DataOffset;
++        __le32  DataLength;
++        __le32  OOBDataOffset;
++        __le32  OOBDataLength;
++        __le32  NumOOBDataElements;
++        __le32  PerPacketInfoOffset;
++        __le32  PerPacketInfoLength;
++        __le32  VcHandle;
++        __le32  Reserved;
++};
++
++struct rndis_config_parameter
++{
++        __le32  ParameterNameOffset;
++        __le32  ParameterNameLength;
++        __le32  ParameterType;
++        __le32  ParameterValueOffset;
++        __le32  ParameterValueLength;
++};
++
++/* implementation specific */
++enum rndis_state
++{
++        RNDIS_UNINITIALIZED,
++        RNDIS_INITIALIZED,
++        RNDIS_DATA_INITIALIZED,
++};
++
++static const uint32_t oid_supported_list[] =
++{
++        /* the general stuff */
++        OID_GEN_SUPPORTED_LIST,
++        OID_GEN_HARDWARE_STATUS,
++        OID_GEN_MEDIA_SUPPORTED,
++        OID_GEN_MEDIA_IN_USE,
++        OID_GEN_MAXIMUM_FRAME_SIZE,
++        OID_GEN_LINK_SPEED,
++        OID_GEN_TRANSMIT_BLOCK_SIZE,
++        OID_GEN_RECEIVE_BLOCK_SIZE,
++        OID_GEN_VENDOR_ID,
++        OID_GEN_VENDOR_DESCRIPTION,
++        OID_GEN_VENDOR_DRIVER_VERSION,
++        OID_GEN_CURRENT_PACKET_FILTER,
++        OID_GEN_MAXIMUM_TOTAL_SIZE,
++        OID_GEN_MEDIA_CONNECT_STATUS,
++        OID_GEN_PHYSICAL_MEDIUM,
++        /* the statistical stuff */
++        OID_GEN_XMIT_OK,
++        OID_GEN_RCV_OK,
++        OID_GEN_XMIT_ERROR,
++        OID_GEN_RCV_ERROR,
++        OID_GEN_RCV_NO_BUFFER,
++        /* mandatory 802.3 */
++        /* the general stuff */
++        OID_802_3_PERMANENT_ADDRESS,
++        OID_802_3_CURRENT_ADDRESS,
++        OID_802_3_MULTICAST_LIST,
++        OID_802_3_MAC_OPTIONS,
++        OID_802_3_MAXIMUM_LIST_SIZE,
++
++        /* the statistical stuff */
++        OID_802_3_RCV_ERROR_ALIGNMENT,
++        OID_802_3_XMIT_ONE_COLLISION,
++        OID_802_3_XMIT_MORE_COLLISIONS
++};
++
++struct rndis_response {
++	TAILQ_ENTRY(rndis_response) entries;
++	uint32_t length;
++	uint8_t buf[0];
++};
++
++
++typedef struct USBNetState {
++	USBDevice dev;
++
++	unsigned int rndis;
++	enum rndis_state rndis_state;
++        uint32_t medium;
++        uint32_t speed;
++        uint32_t media_state;
++	uint16_t filter;
++       	uint32_t vendorid;
++	uint8_t mac[6];
++
++	unsigned int out_ptr;
++	uint8_t out_buf[2048];
++
++	USBPacket *inpkt;
++	unsigned int in_ptr, in_len;
++	uint8_t in_buf[2048];	
++
++	VLANClientState *vc;
++	TAILQ_HEAD(rndis_resp_head, rndis_response) rndis_resp;
++} USBNetState;
++
++
++static int ndis_query(USBNetState *s, uint32_t oid, uint8_t *inbuf, unsigned int inlen, uint8_t *outbuf)
++{
++	switch (oid) {
++        /* general oids (table 4-1) */
++        /* mandatory */
++        case OID_GEN_SUPPORTED_LIST:
++	{
++                unsigned int i, count = sizeof(oid_supported_list) / sizeof(uint32_t);
++                for (i = 0; i < count; i++)
++                        ((__le32 *)outbuf)[i] = cpu_to_le32(oid_supported_list[i]);
++                return sizeof(oid_supported_list);
++	}
++
++        /* mandatory */
++	case OID_GEN_HARDWARE_STATUS:
++		*((__le32 *)outbuf) = cpu_to_le32(0);
++		return sizeof(__le32);
++		
++        /* mandatory */
++        case OID_GEN_MEDIA_SUPPORTED:
++		*((__le32 *)outbuf) = cpu_to_le32(s->medium);
++		return sizeof(__le32);
++
++        /* mandatory */
++        case OID_GEN_MEDIA_IN_USE:
++		*((__le32 *)outbuf) = cpu_to_le32(s->medium);
++		return sizeof(__le32);
++
++        /* mandatory */
++        case OID_GEN_MAXIMUM_FRAME_SIZE:
++		*((__le32 *)outbuf) = cpu_to_le32(ETH_FRAME_LEN);
++		return sizeof(__le32);
++		
++        /* mandatory */
++        case OID_GEN_LINK_SPEED:
++		*((__le32 *)outbuf) = cpu_to_le32(s->speed);
++		return sizeof(__le32);
++
++        /* mandatory */
++        case OID_GEN_TRANSMIT_BLOCK_SIZE:
++		*((__le32 *)outbuf) = cpu_to_le32(ETH_FRAME_LEN);
++		return sizeof(__le32);
++		
++        /* mandatory */
++        case OID_GEN_RECEIVE_BLOCK_SIZE:
++		*((__le32 *)outbuf) = cpu_to_le32(ETH_FRAME_LEN);
++		return sizeof(__le32);
++
++        /* mandatory */
++        case OID_GEN_VENDOR_ID:
++		*((__le32 *)outbuf) = cpu_to_le32(0x1234);
++		return sizeof(__le32);
++
++        /* mandatory */
++        case OID_GEN_VENDOR_DESCRIPTION:
++		strcpy(outbuf, "QEMU USB RNDIS Net");
++		return strlen(outbuf) + 1;
++
++       case OID_GEN_VENDOR_DRIVER_VERSION:
++		*((__le32 *)outbuf) = cpu_to_le32(1);
++		return sizeof(__le32);
++
++        /* mandatory */
++        case OID_GEN_CURRENT_PACKET_FILTER:
++		*((__le32 *)outbuf) = cpu_to_le32(s->filter);
++		return sizeof(__le32);
++
++        /* mandatory */
++        case OID_GEN_MAXIMUM_TOTAL_SIZE:
++		*((__le32 *)outbuf) = cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
++		return sizeof(__le32);
++
++        /* mandatory */
++        case OID_GEN_MEDIA_CONNECT_STATUS:
++		*((__le32 *)outbuf) = cpu_to_le32(s->media_state);
++		return sizeof(__le32);
++
++        case OID_GEN_PHYSICAL_MEDIUM:
++		*((__le32 *)outbuf) = cpu_to_le32(0);
++		return sizeof(__le32);
++
++        case OID_GEN_MAC_OPTIONS:
++		*((__le32 *)outbuf) = cpu_to_le32(NDIS_MAC_OPTION_RECEIVE_SERIALIZED | NDIS_MAC_OPTION_FULL_DUPLEX);
++		return sizeof(__le32);
++
++        /* statistics OIDs (table 4-2) */
++        /* mandatory */
++        case OID_GEN_XMIT_OK:
++		*((__le32 *)outbuf) = cpu_to_le32(0);
++		return sizeof(__le32);
++
++        /* mandatory */
++        case OID_GEN_RCV_OK:
++		*((__le32 *)outbuf) = cpu_to_le32(0);
++		return sizeof(__le32);
++
++        /* mandatory */
++        case OID_GEN_XMIT_ERROR:
++		*((__le32 *)outbuf) = cpu_to_le32(0);
++		return sizeof(__le32);
++
++        /* mandatory */
++        case OID_GEN_RCV_ERROR:
++		*((__le32 *)outbuf) = cpu_to_le32(0);
++		return sizeof(__le32);
++
++        /* mandatory */
++        case OID_GEN_RCV_NO_BUFFER:
++		*((__le32 *)outbuf) = cpu_to_le32(0);
++		return sizeof(__le32);
++
++        /* ieee802.3 OIDs (table 4-3) */
++        /* mandatory */
++        case OID_802_3_PERMANENT_ADDRESS:
++		memcpy(outbuf, s->mac, 6);
++		return 6;
++
++        /* mandatory */
++        case OID_802_3_CURRENT_ADDRESS:
++		memcpy(outbuf, s->mac, 6);
++		return 6;
++
++        /* mandatory */
++        case OID_802_3_MULTICAST_LIST:
++		*((__le32 *)outbuf) = cpu_to_le32(0xE0000000);
++		return sizeof(__le32);
++
++        /* mandatory */
++        case OID_802_3_MAXIMUM_LIST_SIZE:
++		*((__le32 *)outbuf) = cpu_to_le32(1);
++		return sizeof(__le32);
++
++        case OID_802_3_MAC_OPTIONS:
++		return 0;
++
++        /* ieee802.3 statistics OIDs (table 4-4) */
++        /* mandatory */
++        case OID_802_3_RCV_ERROR_ALIGNMENT:
++		*((__le32 *)outbuf) = cpu_to_le32(0);
++		return sizeof(__le32);
++
++        /* mandatory */
++        case OID_802_3_XMIT_ONE_COLLISION:
++		*((__le32 *)outbuf) = cpu_to_le32(0);
++		return sizeof(__le32);
++
++        /* mandatory */
++        case OID_802_3_XMIT_MORE_COLLISIONS:
++		*((__le32 *)outbuf) = cpu_to_le32(0);
++		return sizeof(__le32);
++
++	default:
++		fprintf(stderr, "usbnet: unknown OID 0x%08x\n", oid);
++		return 0;
++	}
++	return -1;
++}
++
++static int ndis_set(USBNetState *s, uint32_t oid, uint8_t *inbuf, unsigned int inlen)
++{
++	switch (oid) {
++        case OID_GEN_CURRENT_PACKET_FILTER:
++		s->filter = le32_to_cpup((__le32 *)inbuf);
++		if (s->filter) {
++			s->rndis_state = RNDIS_DATA_INITIALIZED;
++		} else {
++			s->rndis_state = RNDIS_INITIALIZED;
++		}
++		return 0;
++
++        case OID_802_3_MULTICAST_LIST:
++		return 0;
++
++	}
++	return -1;
++}
++
++static int rndis_get_response(USBNetState *s, uint8_t *buf)
++{
++	int ret = 0;
++	struct rndis_response *r = s->rndis_resp.tqh_first;
++	if (!r)
++		return ret;
++	TAILQ_REMOVE(&s->rndis_resp, r, entries);
++	ret = r->length;
++	memcpy(buf, r->buf, r->length);
++	qemu_free(r);
++	return ret;
++}
++
++static void *rndis_queue_response(USBNetState *s, unsigned int length)
++{
++	struct rndis_response *r = qemu_mallocz(sizeof(struct rndis_response) + length);
++	if (!r)
++		return NULL;
++	TAILQ_INSERT_TAIL(&s->rndis_resp, r, entries);
++	r->length = length;
++	return &r->buf[0];
++}
++
++static void rndis_clear_responsequeue(USBNetState *s)
++{
++	struct rndis_response *r;
++	
++	while ((r = s->rndis_resp.tqh_first)) {
++		TAILQ_REMOVE(&s->rndis_resp, r, entries);
++		qemu_free(r);
++	}
++}
++
++static int rndis_init_response(USBNetState *s, rndis_init_msg_type *buf)
++{
++	rndis_init_cmplt_type *resp = rndis_queue_response(s, sizeof(rndis_init_cmplt_type));
++	if (!resp)
++		return USB_RET_STALL;
++	resp->MessageType = cpu_to_le32(REMOTE_NDIS_INITIALIZE_CMPLT);
++        resp->MessageLength = cpu_to_le32(sizeof(rndis_init_cmplt_type));
++        resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
++        resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
++        resp->MajorVersion = cpu_to_le32(RNDIS_MAJOR_VERSION);
++        resp->MinorVersion = cpu_to_le32(RNDIS_MINOR_VERSION);
++        resp->DeviceFlags = cpu_to_le32(RNDIS_DF_CONNECTIONLESS);
++        resp->Medium = cpu_to_le32(RNDIS_MEDIUM_802_3);
++        resp->MaxPacketsPerTransfer = cpu_to_le32(1);
++        resp->MaxTransferSize = cpu_to_le32(ETH_FRAME_LEN + sizeof(struct rndis_packet_msg_type) + 22);
++        resp->PacketAlignmentFactor = cpu_to_le32(0);
++        resp->AFListOffset = cpu_to_le32(0);
++        resp->AFListSize = cpu_to_le32(0);
 +        return 0;
++}
 +
-+    case MENELAUS_GPIO_CTRL:
-+        return s->dir;
-+    case MENELAUS_GPIO_IN:
-+        return s->inputs | (~s->dir & s->outputs);
-+    case MENELAUS_GPIO_OUT:
-+        return s->outputs;
-+
-+    case MENELAUS_BBSMS:
-+        return s->bbsms;
-+
-+    case MENELAUS_RTC_CTRL:
-+        return s->rtc.ctrl;
-+    case MENELAUS_RTC_UPDATE:
-+        return 0x00;
-+    case MENELAUS_RTC_SEC:
-+        menelaus_rtc_update(s);
-+        return to_bcd(s->rtc.tm.tm_sec);
-+    case MENELAUS_RTC_MIN:
-+        menelaus_rtc_update(s);
-+        return to_bcd(s->rtc.tm.tm_min);
-+    case MENELAUS_RTC_HR:
-+        menelaus_rtc_update(s);
-+        if ((s->rtc.ctrl >> 2) & 1)			/* MODE12_n24 */
-+            return to_bcd((s->rtc.tm.tm_hour % 12) + 1) |
-+                    (!!(s->rtc.tm.tm_hour >= 12) << 7);	/* PM_nAM */
-+        else
-+            return to_bcd(s->rtc.tm.tm_hour);
-+    case MENELAUS_RTC_DAY:
-+        menelaus_rtc_update(s);
-+        return to_bcd(s->rtc.tm.tm_mday);
-+    case MENELAUS_RTC_MON:
-+        menelaus_rtc_update(s);
-+        return to_bcd(s->rtc.tm.tm_mon + 1);
-+    case MENELAUS_RTC_YR:
-+        menelaus_rtc_update(s);
-+        return to_bcd(s->rtc.tm.tm_year - 2000);
-+    case MENELAUS_RTC_WKDAY:
-+        menelaus_rtc_update(s);
-+        return to_bcd(s->rtc.tm.tm_wday);
-+    case MENELAUS_RTC_AL_SEC:
-+        return to_bcd(s->rtc.alm.tm_sec);
-+    case MENELAUS_RTC_AL_MIN:
-+        return to_bcd(s->rtc.alm.tm_min);
-+    case MENELAUS_RTC_AL_HR:
-+        if ((s->rtc.ctrl >> 2) & 1)			/* MODE12_n24 */
-+            return to_bcd((s->rtc.alm.tm_hour % 12) + 1) |
-+                    (!!(s->rtc.alm.tm_hour >= 12) << 7);/* AL_PM_nAM */
-+        else
-+            return to_bcd(s->rtc.alm.tm_hour);
-+    case MENELAUS_RTC_AL_DAY:
-+        return to_bcd(s->rtc.alm.tm_mday);
-+    case MENELAUS_RTC_AL_MON:
-+        return to_bcd(s->rtc.alm.tm_mon + 1);
-+    case MENELAUS_RTC_AL_YR:
-+        return to_bcd(s->rtc.alm.tm_year - 2000);
-+    case MENELAUS_RTC_COMP_MSB:
-+        return (s->rtc.comp >> 8) & 0xff;
-+    case MENELAUS_RTC_COMP_LSB:
-+        return (s->rtc.comp >> 0) & 0xff;
-+
-+    case MENELAUS_S1_PULL_EN:
-+        return s->pull[0];
-+    case MENELAUS_S1_PULL_DIR:
-+        return s->pull[1];
-+    case MENELAUS_S2_PULL_EN:
-+        return s->pull[2];
-+    case MENELAUS_S2_PULL_DIR:
-+        return s->pull[3];
-+
-+    case MENELAUS_MCT_CTRL3: reg ++;
-+    case MENELAUS_MCT_CTRL2: reg ++;
-+    case MENELAUS_MCT_CTRL1:
-+        return s->mmc_ctrl[reg];
-+    case MENELAUS_MCT_PIN_ST:
-+        /* TODO: return the real Card Detect */
-+        return 0;
-+    case MENELAUS_DEBOUNCE1:
-+        return s->mmc_debounce;
++static int rndis_query_response(USBNetState *s, rndis_query_msg_type *buf, unsigned int length)
++{
++        rndis_query_cmplt_type *resp;
++	uint8_t infobuf[sizeof(oid_supported_list)]; /* oid_supported_list is the largest data reply */
++	uint32_t bufoffs, buflen;
++	int infobuflen;
++	unsigned int resplen;
++	bufoffs = le32_to_cpu(buf->InformationBufferOffset) + 8;
++	buflen = le32_to_cpu(buf->InformationBufferLength);
++	if (bufoffs + buflen > length)
++		return USB_RET_STALL;
++	infobuflen = ndis_query(s, le32_to_cpu(buf->OID), bufoffs + (uint8_t *)buf, buflen, infobuf);
++	resplen = sizeof(rndis_query_cmplt_type) + ((infobuflen < 0) ? 0 : infobuflen);
++	resp = rndis_queue_response(s, resplen);
++	if (!resp)
++		return USB_RET_STALL;
++        resp->MessageType = cpu_to_le32(REMOTE_NDIS_QUERY_CMPLT);
++        resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
++	resp->MessageLength = cpu_to_le32(resplen);
++	if (infobuflen < 0) {
++		/* OID not supported */
++                resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
++		resp->InformationBufferLength = cpu_to_le32(0);
++                resp->InformationBufferOffset = cpu_to_le32(0);
++		return 0;
++	}
++	resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
++	resp->InformationBufferOffset = cpu_to_le32(infobuflen ? sizeof(rndis_query_cmplt_type) - 8 : 0);
++	resp->InformationBufferLength = cpu_to_le32(infobuflen);
++	memcpy(resp + 1, infobuf, infobuflen);
++	return 0;
++}
++
++static int rndis_set_response(USBNetState *s, rndis_set_msg_type *buf, unsigned int length)
++{
++        rndis_set_cmplt_type *resp = rndis_queue_response(s, sizeof(rndis_set_cmplt_type));
++	uint32_t bufoffs, buflen;
++	if (!resp)
++		return USB_RET_STALL;
++	bufoffs = le32_to_cpu(buf->InformationBufferOffset) + 8;
++	buflen = le32_to_cpu(buf->InformationBufferLength);
++	if (bufoffs + buflen > length)
++		return USB_RET_STALL;
++	int ret = ndis_set(s, le32_to_cpu(buf->OID), bufoffs + (uint8_t *)buf, buflen);
++        resp->MessageType = cpu_to_le32(REMOTE_NDIS_SET_CMPLT);
++        resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
++	resp->MessageLength = cpu_to_le32(sizeof(rndis_set_cmplt_type));
++	if (ret < 0) {
++		/* OID not supported */
++                resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
++		return 0;
++	}
++	resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
++	return 0;
++}
++
++static int rndis_reset_response(USBNetState *s, rndis_reset_msg_type *buf)
++{
++        rndis_reset_cmplt_type *resp = rndis_queue_response(s, sizeof(rndis_reset_cmplt_type));
++	if (!resp)
++		return USB_RET_STALL;
++        resp->MessageType = cpu_to_le32(REMOTE_NDIS_RESET_CMPLT);
++        resp->MessageLength = cpu_to_le32(sizeof(rndis_reset_cmplt_type));
++        resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
++        /* resent information */
++        resp->AddressingReset = cpu_to_le32(1);
++	return 0;
++}
++
++static int rndis_keepalive_response(USBNetState *s, rndis_keepalive_msg_type *buf)
++{
++        rndis_keepalive_cmplt_type *resp = rndis_queue_response(s, sizeof(rndis_keepalive_cmplt_type));
++	if (!resp)
++		return USB_RET_STALL;
++        resp->MessageType = cpu_to_le32(REMOTE_NDIS_KEEPALIVE_CMPLT);
++        resp->MessageLength = cpu_to_le32(sizeof(rndis_keepalive_cmplt_type));
++        resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
++        resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
++	return 0;
++}
++
++static int rndis_parse(USBNetState *s, uint8_t *data, int length)
++{
++        uint32_t MsgType, MsgLength;
++        __le32 *tmp = (__le32 *)data;
++        MsgType = le32_to_cpup(tmp++);
++        MsgLength = le32_to_cpup(tmp++);
++	
++	switch (MsgType) {
++	case REMOTE_NDIS_INITIALIZE_MSG:
++		s->rndis_state = RNDIS_INITIALIZED;
++		return rndis_init_response(s, (rndis_init_msg_type *)data);
++
++        case REMOTE_NDIS_HALT_MSG:
++		s->rndis_state = RNDIS_UNINITIALIZED;
++                return 0;
 +
-+    default:
-+#ifdef VERBOSE
-+        printf("%s: unknown register %02x\n", __FUNCTION__, addr);
++	case REMOTE_NDIS_QUERY_MSG:
++                return rndis_query_response(s, (rndis_query_msg_type *)data, length);
++
++        case REMOTE_NDIS_SET_MSG:
++                return rndis_set_response(s, (rndis_set_msg_type *)data, length);
++
++        case REMOTE_NDIS_RESET_MSG:
++		rndis_clear_responsequeue(s);
++		s->out_ptr = s->in_ptr = s->in_len = 0;
++                return rndis_reset_response(s, (rndis_reset_msg_type *)data);
++
++        case REMOTE_NDIS_KEEPALIVE_MSG:
++                /* For USB: host does this every 5 seconds */
++                return rndis_keepalive_response(s, (rndis_keepalive_msg_type *)data);	
++	}
++	return USB_RET_STALL;
++}
++
++static void usb_net_handle_reset(USBDevice *dev)
++{
++}
++
++static int usb_net_handle_control(USBDevice *dev, int request, int value,
++                                  int index, int length, uint8_t *data)
++{
++	USBNetState *s = (USBNetState *)dev;
++	int ret = 0;
++
++	switch(request) {
++	case DeviceRequest | USB_REQ_GET_STATUS:
++		data[0] = (1 << USB_DEVICE_SELF_POWERED) |
++			(dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
++		data[1] = 0x00;
++		ret = 2;
++		break;
++
++	case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
++		if (value == USB_DEVICE_REMOTE_WAKEUP) {
++			dev->remote_wakeup = 0;
++		} else {
++			goto fail;
++		}
++		ret = 0;
++		break;
++
++	case DeviceOutRequest | USB_REQ_SET_FEATURE:
++		if (value == USB_DEVICE_REMOTE_WAKEUP) {
++			dev->remote_wakeup = 1;
++		} else {
++			goto fail;
++		}
++		ret = 0;
++		break;
++
++	case DeviceOutRequest | USB_REQ_SET_ADDRESS:
++		dev->addr = value;
++		ret = 0;
++		break;
++
++	case ClassInterfaceOutRequest | USB_CDC_SEND_ENCAPSULATED_COMMAND:
++		if (!s->rndis || value || index != 0)
++			goto fail;
++#if TRAFFIC_DEBUG
++		{
++			unsigned int i;
++			fprintf(stderr, "SEND_ENCAPSULATED_COMMAND:");
++			for (i = 0; i < length; i++) {
++				if (!(i & 15))
++					fprintf(stderr, "\n%04X:", i);
++				fprintf(stderr, " %02X", data[i]);
++			}
++			fprintf(stderr, "\n\n");
++		}
 +#endif
-+        break;
-+    }
-+    return 0;
-+}
-+
-+static void menelaus_write(void *opaque, uint8_t addr, uint8_t value)
-+{
-+    struct menelaus_s *s = (struct menelaus_s *) opaque;
-+    int line;
-+    int reg = 0;
-+    struct tm tm;
-+
-+    switch (addr) {
-+    case MENELAUS_VCORE_CTRL1:
-+        s->vcore[0] = (value & 0xe) | MIN(value & 0x1f, 0x12);
-+        break;
-+    case MENELAUS_VCORE_CTRL2:
-+        s->vcore[1] = value;
-+        break;
-+    case MENELAUS_VCORE_CTRL3:
-+        s->vcore[2] = MIN(value & 0x1f, 0x12);
-+        break;
-+    case MENELAUS_VCORE_CTRL4:
-+        s->vcore[3] = MIN(value & 0x1f, 0x12);
-+        break;
-+    case MENELAUS_VCORE_CTRL5:
-+        s->vcore[4] = value & 3;
-+        /* XXX
-+         * auto set to 3 on M_Active, nRESWARM
-+         * auto set to 0 on M_WaitOn, M_Backup
-+         */
-+        break;
-+
-+    case MENELAUS_DCDC_CTRL1:
-+        s->dcdc[0] = value & 0x3f;
-+        break;
-+    case MENELAUS_DCDC_CTRL2:
-+        s->dcdc[1] = value & 0x07;
-+        /* XXX
-+         * auto set to 3 on M_Active, nRESWARM
-+         * auto set to 0 on M_WaitOn, M_Backup
-+         */
-+        break;
-+    case MENELAUS_DCDC_CTRL3:
-+        s->dcdc[2] = value & 0x07;
-+        break;
-+
-+    case MENELAUS_LDO_CTRL1:
-+        s->ldo[0] = value;
-+        break;
-+    case MENELAUS_LDO_CTRL2:
-+        s->ldo[1] = value & 0x7f;
-+        /* XXX
-+         * auto set to 0x7e on M_WaitOn, M_Backup
-+         */
-+        break;
-+    case MENELAUS_LDO_CTRL3:
-+        s->ldo[2] = value & 3;
-+        /* XXX
-+         * auto set to 3 on M_Active, nRESWARM
-+         * auto set to 0 on M_WaitOn, M_Backup
-+         */
-+        break;
-+    case MENELAUS_LDO_CTRL4:
-+        s->ldo[3] = value & 3;
-+        /* XXX
-+         * auto set to 3 on M_Active, nRESWARM
-+         * auto set to 0 on M_WaitOn, M_Backup
-+         */
-+        break;
-+    case MENELAUS_LDO_CTRL5:
-+        s->ldo[4] = value & 3;
-+        /* XXX
-+         * auto set to 3 on M_Active, nRESWARM
-+         * auto set to 0 on M_WaitOn, M_Backup
-+         */
-+        break;
-+    case MENELAUS_LDO_CTRL6:
-+        s->ldo[5] = value & 3;
-+        break;
-+    case MENELAUS_LDO_CTRL7:
-+        s->ldo[6] = value & 3;
-+        break;
-+    case MENELAUS_LDO_CTRL8:
-+        s->ldo[7] = value & 3;
-+        break;
-+
-+    case MENELAUS_SLEEP_CTRL2: reg ++;
-+    case MENELAUS_SLEEP_CTRL1:
-+        s->sleep[reg] = value;
-+        break;
-+
-+    case MENELAUS_DEVICE_OFF:
-+        if (value & 1)
-+            menelaus_reset(&s->i2c);
-+        break;
-+
-+    case MENELAUS_OSC_CTRL:
-+        s->osc = value & 7;
-+        break;
-+
-+    case MENELAUS_DETECT_CTRL:
-+        s->detect = value & 0x7f;
-+        break;
-+
-+    case MENELAUS_INT_MASK1:
-+        s->mask &= 0xf00;
-+        s->mask |= value << 0;
-+        menelaus_update(s);
-+        break;
-+    case MENELAUS_INT_MASK2:
-+        s->mask &= 0x0ff;
-+        s->mask |= value << 8;
-+        menelaus_update(s);
-+        break;
-+
-+    case MENELAUS_INT_ACK1:
-+        s->status &= ~(((uint16_t) value) << 0);
-+        menelaus_update(s);
-+        break;
-+    case MENELAUS_INT_ACK2:
-+        s->status &= ~(((uint16_t) value) << 8);
-+        menelaus_update(s);
-+        break;
-+
-+    case MENELAUS_GPIO_CTRL:
-+        for (line = 0; line < 3; line ++)
-+            if (((s->dir ^ value) >> line) & 1)
-+                if (s->handler[line])
-+                    qemu_set_irq(s->handler[line],
-+                                    ((s->outputs & ~s->dir) >> line) & 1);
-+        s->dir = value & 0x67;
-+        break;
-+    case MENELAUS_GPIO_OUT:
-+        for (line = 0; line < 3; line ++)
-+            if ((((s->outputs ^ value) & ~s->dir) >> line) & 1)
-+                if (s->handler[line])
-+                    qemu_set_irq(s->handler[line], (s->outputs >> line) & 1);
-+        s->outputs = value & 0x07;
-+        break;
-+
-+    case MENELAUS_BBSMS:
-+        s->bbsms = 0x0d;
-+        break;
-+
-+    case MENELAUS_RTC_CTRL:
-+        if ((s->rtc.ctrl ^ value) & 1) {			/* RTC_EN */
-+            if (value & 1)
-+                menelaus_rtc_start(s);
-+            else
-+                menelaus_rtc_stop(s);
-+        }
-+        s->rtc.ctrl = value & 0x1f;
-+        menelaus_alm_update(s);
-+        break;
-+    case MENELAUS_RTC_UPDATE:
-+        menelaus_rtc_update(s);
-+        memcpy(&tm, &s->rtc.tm, sizeof(tm));
-+        switch (value & 0xf) {
-+        case 0:
-+            break;
-+        case 1:
-+            tm.tm_sec = s->rtc.new.tm_sec;
-+            break;
-+        case 2:
-+            tm.tm_min = s->rtc.new.tm_min;
-+            break;
-+        case 3:
-+            if (s->rtc.new.tm_hour > 23)
-+                goto rtc_badness;
-+            tm.tm_hour = s->rtc.new.tm_hour;
-+            break;
-+        case 4:
-+            if (s->rtc.new.tm_mday < 1)
-+                goto rtc_badness;
-+            /* TODO check range */
-+            tm.tm_mday = s->rtc.new.tm_mday;
-+            break;
-+        case 5:
-+            if (s->rtc.new.tm_mon < 0 || s->rtc.new.tm_mon > 11)
-+                goto rtc_badness;
-+            tm.tm_mon = s->rtc.new.tm_mon;
-+            break;
-+        case 6:
-+            tm.tm_year = s->rtc.new.tm_year;
-+            break;
-+        case 7:
-+            /* TODO set .tm_mday instead */
-+            tm.tm_wday = s->rtc.new.tm_wday;
-+            break;
-+        case 8:
-+            if (s->rtc.new.tm_hour > 23)
-+                goto rtc_badness;
-+            if (s->rtc.new.tm_mday < 1)
-+                goto rtc_badness;
-+            if (s->rtc.new.tm_mon < 0 || s->rtc.new.tm_mon > 11)
-+                goto rtc_badness;
-+            tm.tm_sec = s->rtc.new.tm_sec;
-+            tm.tm_min = s->rtc.new.tm_min;
-+            tm.tm_hour = s->rtc.new.tm_hour;
-+            tm.tm_mday = s->rtc.new.tm_mday;
-+            tm.tm_mon = s->rtc.new.tm_mon;
-+            tm.tm_year = s->rtc.new.tm_year;
-+            break;
-+        rtc_badness:
-+        default:
-+            fprintf(stderr, "%s: bad RTC_UPDATE value %02x\n",
-+                            __FUNCTION__, value);
-+            s->status |= 1 << 10;				/* RTCERR */
-+            menelaus_update(s);
-+        }
-+        s->rtc.sec += difftime(mktime(&tm), mktime(&s->rtc.tm));
-+        break;
-+    case MENELAUS_RTC_SEC:
-+        s->rtc.tm.tm_sec = from_bcd(value & 0x7f);
-+        break;
-+    case MENELAUS_RTC_MIN:
-+        s->rtc.tm.tm_min = from_bcd(value & 0x7f);
-+        break;
-+    case MENELAUS_RTC_HR:
-+        s->rtc.tm.tm_hour = (s->rtc.ctrl & (1 << 2)) ?	/* MODE12_n24 */
-+                MIN(from_bcd(value & 0x3f), 12) + ((value >> 7) ? 11 : -1) :
-+                from_bcd(value & 0x3f);
-+        break;
-+    case MENELAUS_RTC_DAY:
-+        s->rtc.tm.tm_mday = from_bcd(value);
-+        break;
-+    case MENELAUS_RTC_MON:
-+        s->rtc.tm.tm_mon = MAX(1, from_bcd(value)) - 1;
-+        break;
-+    case MENELAUS_RTC_YR:
-+        s->rtc.tm.tm_year = 2000 + from_bcd(value);
-+        break;
-+    case MENELAUS_RTC_WKDAY:
-+        s->rtc.tm.tm_mday = from_bcd(value);
-+        break;
-+    case MENELAUS_RTC_AL_SEC:
-+        s->rtc.alm.tm_sec = from_bcd(value & 0x7f);
-+        menelaus_alm_update(s);
-+        break;
-+    case MENELAUS_RTC_AL_MIN:
-+        s->rtc.alm.tm_min = from_bcd(value & 0x7f);
-+        menelaus_alm_update(s);
-+        break;
-+    case MENELAUS_RTC_AL_HR:
-+        s->rtc.alm.tm_hour = (s->rtc.ctrl & (1 << 2)) ?	/* MODE12_n24 */
-+                MIN(from_bcd(value & 0x3f), 12) + ((value >> 7) ? 11 : -1) :
-+                from_bcd(value & 0x3f);
-+        menelaus_alm_update(s);
-+        break;
-+    case MENELAUS_RTC_AL_DAY:
-+        s->rtc.alm.tm_mday = from_bcd(value);
-+        menelaus_alm_update(s);
-+        break;
-+    case MENELAUS_RTC_AL_MON:
-+        s->rtc.alm.tm_mon = MAX(1, from_bcd(value)) - 1;
-+        menelaus_alm_update(s);
-+        break;
-+    case MENELAUS_RTC_AL_YR:
-+        s->rtc.alm.tm_year = 2000 + from_bcd(value);
-+        menelaus_alm_update(s);
-+        break;
-+    case MENELAUS_RTC_COMP_MSB:
-+        s->rtc.comp &= 0xff;
-+        s->rtc.comp |= value << 8;
-+        break;
-+    case MENELAUS_RTC_COMP_LSB:
-+        s->rtc.comp &= 0xff << 8;
-+        s->rtc.comp |= value;
-+        break;
-+
-+    case MENELAUS_S1_PULL_EN:
-+        s->pull[0] = value;
-+        break;
-+    case MENELAUS_S1_PULL_DIR:
-+        s->pull[1] = value & 0x1f;
-+        break;
-+    case MENELAUS_S2_PULL_EN:
-+        s->pull[2] = value;
-+        break;
-+    case MENELAUS_S2_PULL_DIR:
-+        s->pull[3] = value & 0x1f;
-+        break;
-+
-+    case MENELAUS_MCT_CTRL1:
-+        s->mmc_ctrl[0] = value & 0x7f;
-+        break;
-+    case MENELAUS_MCT_CTRL2:
-+        s->mmc_ctrl[1] = value;
-+        /* TODO update Card Detect interrupts */
-+        break;
-+    case MENELAUS_MCT_CTRL3:
-+        s->mmc_ctrl[2] = value & 0xf;
-+        break;
-+    case MENELAUS_DEBOUNCE1:
-+        s->mmc_debounce = value & 0x3f;
-+        break;
-+
-+    default:
-+#ifdef VERBOSE
-+        printf("%s: unknown register %02x\n", __FUNCTION__, addr);
++		ret = rndis_parse(s, data, length);
++		break;
++
++	case ClassInterfaceRequest | USB_CDC_GET_ENCAPSULATED_RESPONSE:
++		if (!s->rndis || value || index != 0)
++			goto fail;
++		ret = rndis_get_response(s, data);
++		if (!ret) {
++			data[0] = 0;
++			ret = 1;
++		}
++#if TRAFFIC_DEBUG
++		{
++			unsigned int i;
++			fprintf(stderr, "GET_ENCAPSULATED_RESPONSE:");
++			for (i = 0; i < ret; i++) {
++				if (!(i & 15))
++					fprintf(stderr, "\n%04X:", i);
++				fprintf(stderr, " %02X", data[i]);
++			}
++			fprintf(stderr, "\n\n");
++		}
 +#endif
-+    }
-+}
-+
-+static void menelaus_event(i2c_slave *i2c, enum i2c_event event)
-+{
-+    struct menelaus_s *s = (struct menelaus_s *) i2c;
-+
-+    if (event == I2C_START_SEND)
-+        s->firstbyte = 1;
-+}
-+
-+static int menelaus_tx(i2c_slave *i2c, uint8_t data)
-+{
-+    struct menelaus_s *s = (struct menelaus_s *) i2c;
-+    /* Interpret register address byte */
-+    if (s->firstbyte) {
-+        s->reg = data;
-+        s->firstbyte = 0;
-+    } else
-+        menelaus_write(s, s->reg ++, data);
-+
-+    return 0;
-+}
-+
-+static int menelaus_rx(i2c_slave *i2c)
-+{
-+    struct menelaus_s *s = (struct menelaus_s *) i2c;
-+
-+    return menelaus_read(s, s->reg ++);
-+}
-+
-+static void tm_put(QEMUFile *f, struct tm *tm) {
-+    qemu_put_be16(f, tm->tm_sec);
-+    qemu_put_be16(f, tm->tm_min);
-+    qemu_put_be16(f, tm->tm_hour);
-+    qemu_put_be16(f, tm->tm_mday);
-+    qemu_put_be16(f, tm->tm_min);
-+    qemu_put_be16(f, tm->tm_year);
-+}
-+
-+static void tm_get(QEMUFile *f, struct tm *tm) {
-+    tm->tm_sec = qemu_get_be16(f);
-+    tm->tm_min = qemu_get_be16(f);
-+    tm->tm_hour = qemu_get_be16(f);
-+    tm->tm_mday = qemu_get_be16(f);
-+    tm->tm_min = qemu_get_be16(f);
-+    tm->tm_year = qemu_get_be16(f);
-+}
-+
-+static void menelaus_save(QEMUFile *f, void *opaque)
-+{
-+    struct menelaus_s *s = (struct menelaus_s *) opaque;
-+
-+    qemu_put_be32(f, s->firstbyte);
-+    qemu_put_8s(f, &s->reg);
-+
-+    qemu_put_8s(f, &s->vcore[0]);
-+    qemu_put_8s(f, &s->vcore[1]);
-+    qemu_put_8s(f, &s->vcore[2]);
-+    qemu_put_8s(f, &s->vcore[3]);
-+    qemu_put_8s(f, &s->vcore[4]);
-+    qemu_put_8s(f, &s->dcdc[3]);
-+    qemu_put_8s(f, &s->dcdc[3]);
-+    qemu_put_8s(f, &s->dcdc[3]);
-+    qemu_put_8s(f, &s->ldo[0]);
-+    qemu_put_8s(f, &s->ldo[1]);
-+    qemu_put_8s(f, &s->ldo[2]);
-+    qemu_put_8s(f, &s->ldo[3]);
-+    qemu_put_8s(f, &s->ldo[4]);
-+    qemu_put_8s(f, &s->ldo[5]);
-+    qemu_put_8s(f, &s->ldo[6]);
-+    qemu_put_8s(f, &s->ldo[7]);
-+    qemu_put_8s(f, &s->sleep[0]);
-+    qemu_put_8s(f, &s->sleep[1]);
-+    qemu_put_8s(f, &s->osc);
-+    qemu_put_8s(f, &s->detect);
-+    qemu_put_be16s(f, &s->mask);
-+    qemu_put_be16s(f, &s->status);
-+    qemu_put_8s(f, &s->dir);
-+    qemu_put_8s(f, &s->inputs);
-+    qemu_put_8s(f, &s->outputs);
-+    qemu_put_8s(f, &s->bbsms);
-+    qemu_put_8s(f, &s->pull[0]);
-+    qemu_put_8s(f, &s->pull[1]);
-+    qemu_put_8s(f, &s->pull[2]);
-+    qemu_put_8s(f, &s->pull[3]);
-+    qemu_put_8s(f, &s->mmc_ctrl[0]);
-+    qemu_put_8s(f, &s->mmc_ctrl[1]);
-+    qemu_put_8s(f, &s->mmc_ctrl[2]);
-+    qemu_put_8s(f, &s->mmc_debounce);
-+    qemu_put_8s(f, &s->rtc.ctrl);
-+    qemu_put_be16s(f, &s->rtc.comp);
-+    /* Should be <= 1000 */
-+    qemu_put_be16(f, s->rtc.next - qemu_get_clock(rt_clock));
-+    tm_put(f, &s->rtc.new);
-+    tm_put(f, &s->rtc.alm);
-+    qemu_put_byte(f, s->pwrbtn_state);
-+
-+    i2c_slave_save(f, &s->i2c);
-+}
-+
-+static int menelaus_load(QEMUFile *f, void *opaque, int version_id)
-+{
-+    struct menelaus_s *s = (struct menelaus_s *) opaque;
-+
-+    s->firstbyte = qemu_get_be32(f);
-+    qemu_get_8s(f, &s->reg);
-+
-+    if (s->rtc.ctrl & 1)					/* RTC_EN */
-+        menelaus_rtc_stop(s);
-+    qemu_get_8s(f, &s->vcore[0]);
-+    qemu_get_8s(f, &s->vcore[1]);
-+    qemu_get_8s(f, &s->vcore[2]);
-+    qemu_get_8s(f, &s->vcore[3]);
-+    qemu_get_8s(f, &s->vcore[4]);
-+    qemu_get_8s(f, &s->dcdc[3]);
-+    qemu_get_8s(f, &s->dcdc[3]);
-+    qemu_get_8s(f, &s->dcdc[3]);
-+    qemu_get_8s(f, &s->ldo[0]);
-+    qemu_get_8s(f, &s->ldo[1]);
-+    qemu_get_8s(f, &s->ldo[2]);
-+    qemu_get_8s(f, &s->ldo[3]);
-+    qemu_get_8s(f, &s->ldo[4]);
-+    qemu_get_8s(f, &s->ldo[5]);
-+    qemu_get_8s(f, &s->ldo[6]);
-+    qemu_get_8s(f, &s->ldo[7]);
-+    qemu_get_8s(f, &s->sleep[0]);
-+    qemu_get_8s(f, &s->sleep[1]);
-+    qemu_get_8s(f, &s->osc);
-+    qemu_get_8s(f, &s->detect);
-+    qemu_get_be16s(f, &s->mask);
-+    qemu_get_be16s(f, &s->status);
-+    qemu_get_8s(f, &s->dir);
-+    qemu_get_8s(f, &s->inputs);
-+    qemu_get_8s(f, &s->outputs);
-+    qemu_get_8s(f, &s->bbsms);
-+    qemu_get_8s(f, &s->pull[0]);
-+    qemu_get_8s(f, &s->pull[1]);
-+    qemu_get_8s(f, &s->pull[2]);
-+    qemu_get_8s(f, &s->pull[3]);
-+    qemu_get_8s(f, &s->mmc_ctrl[0]);
-+    qemu_get_8s(f, &s->mmc_ctrl[1]);
-+    qemu_get_8s(f, &s->mmc_ctrl[2]);
-+    qemu_get_8s(f, &s->mmc_debounce);
-+    qemu_get_8s(f, &s->rtc.ctrl);
-+    qemu_get_be16s(f, &s->rtc.comp);
-+    s->rtc.next = qemu_get_be16(f);
-+    tm_get(f, &s->rtc.new);
-+    tm_get(f, &s->rtc.alm);
-+    s->pwrbtn_state = qemu_get_byte(f);
-+    menelaus_alm_update(s);
-+    menelaus_update(s);
-+    if (s->rtc.ctrl & 1)					/* RTC_EN */
-+        menelaus_rtc_start(s);
-+
-+    i2c_slave_load(f, &s->i2c);
-+    return 0;
-+}
-+
-+static int menelaus_iid = 0;
-+
-+i2c_slave *twl92230_init(i2c_bus *bus, qemu_irq irq)
-+{
-+    struct menelaus_s *s = (struct menelaus_s *)
-+            i2c_slave_init(bus, 0, sizeof(struct menelaus_s));
-+
-+    s->i2c.event = menelaus_event;
-+    s->i2c.recv = menelaus_rx;
-+    s->i2c.send = menelaus_tx;
-+
-+    /* TODO: use the qemu gettime functions */
-+    s->rtc.gettime = localtime_r;
-+
-+    s->irq = irq;
-+    s->rtc.hz = qemu_new_timer(rt_clock, menelaus_rtc_hz, s);
-+    s->in = qemu_allocate_irqs(menelaus_gpio_set, s, 3);
-+    s->pwrbtn = qemu_allocate_irqs(menelaus_pwrbtn_set, s, 1)[0];
-+
-+    menelaus_reset(&s->i2c);
-+
-+    register_savevm("menelaus", menelaus_iid ++,
-+                    0, menelaus_save, menelaus_load, s);
-+
-+    return &s->i2c;
-+}
-+
-+qemu_irq *twl92230_gpio_in_get(i2c_slave *i2c)
-+{
-+    struct menelaus_s *s = (struct menelaus_s *) i2c;
-+
-+    return s->in;
-+}
-+
-+void twl92230_gpio_out_set(i2c_slave *i2c, int line, qemu_irq handler)
-+{
-+    struct menelaus_s *s = (struct menelaus_s *) i2c;
-+
-+    if (line >= 3 || line < 0) {
-+        fprintf(stderr, "%s: No GPO line %i\n", __FUNCTION__, line);
-+        exit(-1);
-+    }
-+    s->handler[line] = handler;
-+}
-diff --git a/hw/versatilepb.c b/hw/versatilepb.c
-index da6e4ec..ecc0037 100644
---- a/hw/versatilepb.c
-+++ b/hw/versatilepb.c
-@@ -157,6 +157,8 @@ static qemu_irq *vpb_sic_init(uint32_t base, qemu_irq *parent, int irq)
-    peripherans and expansion busses.  For now we emulate a subset of the
-    PB peripherals and just change the board ID.  */
- 
-+static struct arm_boot_info versatile_binfo;
-+
- static void versatile_init(int ram_size, int vga_ram_size,
-                      const char *boot_device, DisplayState *ds,
-                      const char *kernel_filename, const char *kernel_cmdline,
-@@ -283,8 +285,12 @@ static void versatile_init(int ram_size, int vga_ram_size,
-     /*  0x101f3000 UART2.  */
-     /* 0x101f4000 SSPI.  */
- 
--    arm_load_kernel(env, ram_size, kernel_filename, kernel_cmdline,
--                    initrd_filename, board_id, 0x0);
-+    versatile_binfo.ram_size = ram_size;
-+    versatile_binfo.kernel_filename = kernel_filename;
-+    versatile_binfo.kernel_cmdline = kernel_cmdline;
-+    versatile_binfo.initrd_filename = initrd_filename;
-+    versatile_binfo.board_id = board_id;
-+    arm_load_kernel(env, &versatile_binfo);
- }
- 
- static void vpb_init(int ram_size, int vga_ram_size,
-diff --git a/softmmu_template.h b/softmmu_template.h
-index 0a4bc7e..d480f34 100644
---- a/softmmu_template.h
-+++ b/softmmu_template.h
-@@ -51,12 +51,15 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
++		break;
++
++	case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
++		switch(value >> 8) {
++		case USB_DT_DEVICE:
++			ret = sizeof(qemu_net_dev_descriptor);
++			memcpy(data, qemu_net_dev_descriptor, ret);
++			break;
++
++		case USB_DT_CONFIG:
++			switch (value & 0xff) {
++			case 0:
++				ret = sizeof(qemu_net_rndis_config_descriptor);
++				memcpy(data, qemu_net_rndis_config_descriptor,
++						ret);
++				break;
++
++			case 1:
++				ret = sizeof(qemu_net_cdc_config_descriptor);
++				memcpy(data, qemu_net_cdc_config_descriptor,
++						ret);
++				break;
++
++			default:
++				goto fail;
++			}
++			data[2] = ret & 0xff;
++			data[3] = ret >> 8;
++			break;
++
++		case USB_DT_STRING:
++			switch (value & 0xff) {
++			case 0:
++				/* language ids */
++				data[0] = 4;
++				data[1] = 3;
++				data[2] = 0x09;
++				data[3] = 0x04;
++				ret = 4;
++				break;
++				
++			case STRING_MANUFACTURER:
++				ret = set_usb_string(data, "QEMU");
++				break;
++
++			case STRING_PRODUCT:
++				ret = set_usb_string(data, "RNDIS/QEMU USB Network Device");
++				break;
++
++			case STRING_ETHADDR:
++				ret = set_usb_string(data, "400102030405");
++				break;
++
++			case STRING_DATA:
++				ret = set_usb_string(data, "QEMU USB Net Data Interface");
++				break;
++
++			case STRING_CONTROL:
++				ret = set_usb_string(data, "QEMU USB Net Control Interface");
++				break;
++
++			case STRING_RNDIS_CONTROL:
++				ret = set_usb_string(data, "QEMU USB Net RNDIS Control Interface");
++				break;
++
++			case STRING_CDC:
++				ret = set_usb_string(data, "QEMU USB Net CDC");
++				break;
++
++			case STRING_SUBSET:
++				ret = set_usb_string(data, "QEMU USB Net Subset");
++				break;
++
++			case STRING_RNDIS:
++				ret = set_usb_string(data, "QEMU USB Net RNDIS");
++				break;
++
++			case STRING_SERIALNUMBER:
++				ret = set_usb_string(data, "1");
++				break;
++
++			default:
++				goto fail;
++			}
++			break;
++
++		default:
++			goto fail;
++		}
++		break;
++
++	case DeviceRequest | USB_REQ_GET_CONFIGURATION:
++		data[0] = s->rndis ? DEV_RNDIS_CONFIG_VALUE : DEV_CONFIG_VALUE;
++		ret = 1;
++		break;
++
++	case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
++		switch (value & 0xff) {
++		case DEV_CONFIG_VALUE:
++			s->rndis = 0;
++			break;
++
++		case DEV_RNDIS_CONFIG_VALUE:
++			s->rndis = 1;
++			break;
++
++		default:
++			goto fail;
++		}
++		ret = 0;
++		break;
++
++	case DeviceRequest | USB_REQ_GET_INTERFACE:
++	case InterfaceRequest | USB_REQ_GET_INTERFACE:
++		data[0] = 0;
++		ret = 1;
++		break;
++
++	case DeviceOutRequest | USB_REQ_SET_INTERFACE:
++	case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
++		ret = 0;
++		break;
++
++	default:
++	fail:
++		fprintf(stderr, "usbnet: failed control transaction: request 0x%x value 0x%x index 0x%x length 0x%x\n",
++			request, value, index, length);
++		ret = USB_RET_STALL;
++		break;
++	}
++	return ret;
++}
++
++static int usb_net_handle_statusin(USBNetState *s, USBPacket *p)
++{
++	int ret = 8;
++	if (p->len < 8)
++		return USB_RET_STALL;
++	((__le32 *)p->data)[0] = cpu_to_le32(1);
++	((__le32 *)p->data)[1] = cpu_to_le32(0);
++	if (!s->rndis_resp.tqh_first)
++		ret = USB_RET_NAK;
++#if DEBUG
++	fprintf(stderr, "usbnet: interrupt poll len %u return %d", p->len, ret);
++	{
++		int i;
++		fprintf(stderr, ":");
++		for (i = 0; i < ret; i++) {
++			if (!(i & 15))
++				fprintf(stderr, "\n%04X:", i);
++			fprintf(stderr, " %02X", p->data[i]);
++		}
++		fprintf(stderr, "\n\n");
++	}
++#endif
++	return ret;
++}
++
++static int usb_net_handle_datain(USBNetState *s, USBPacket *p)
++{
++	int ret = USB_RET_NAK;
++
++	if (s->in_ptr > s->in_len) {
++		s->in_ptr = s->in_len = 0;
++		ret = USB_RET_NAK;
++		return ret;
++	}
++	if (!s->in_len) {
++		ret = USB_RET_NAK;
++		return ret;
++	}
++	ret = s->in_len - s->in_ptr;
++	if (ret > p->len)
++		ret = p->len;
++	memcpy(p->data, &s->in_buf[s->in_ptr], ret);
++	s->in_ptr += ret;
++	if (s->in_ptr >= s->in_len && (s->rndis || (s->in_len & (64-1)) || !ret)) {
++		/* no short packet necessary */
++		s->in_ptr = s->in_len = 0;
++	}
++#if TRAFFIC_DEBUG
++	fprintf(stderr, "usbnet: data in len %u return %d", p->len, ret);
++	{
++		int i;
++		fprintf(stderr, ":");
++		for (i = 0; i < ret; i++) {
++			if (!(i & 15))
++				fprintf(stderr, "\n%04X:", i);
++			fprintf(stderr, " %02X", p->data[i]);
++		}
++		fprintf(stderr, "\n\n");
++	}
++#endif
++	return ret;
++}
++
++static int usb_net_handle_dataout(USBNetState *s, USBPacket *p)
++{
++	int ret = p->len;
++	int sz = sizeof(s->out_buf) - s->out_ptr;
++	struct rndis_packet_msg_type *msg = (struct rndis_packet_msg_type *)s->out_buf;
++	uint32_t len;
++
++#if TRAFFIC_DEBUG
++	fprintf(stderr, "usbnet: data out len %u\n", p->len);
++	{
++		int i;
++		fprintf(stderr, ":");
++		for (i = 0; i < p->len; i++) {
++			if (!(i & 15))
++				fprintf(stderr, "\n%04X:", i);
++			fprintf(stderr, " %02X", p->data[i]);
++		}
++		fprintf(stderr, "\n\n");
++	}
++#endif
++	if (sz > ret)
++		sz = ret;
++	memcpy(&s->out_buf[s->out_ptr], p->data, sz);
++	s->out_ptr += sz;
++	if (!s->rndis) {
++		if (ret < 64) {
++			qemu_send_packet(s->vc, s->out_buf, s->out_ptr);
++			s->out_ptr = 0;
++		}
++		return ret;
++	}
++	len = le32_to_cpu(msg->MessageLength);
++	if (s->out_ptr < 8 || s->out_ptr < len)
++		return ret;
++	if (le32_to_cpu(msg->MessageType) == REMOTE_NDIS_PACKET_MSG) {
++		uint32_t offs = 8 + le32_to_cpu(msg->DataOffset);
++		uint32_t size = le32_to_cpu(msg->DataLength);
++		if (offs + size <= len)
++			qemu_send_packet(s->vc, s->out_buf + offs, size);
++	}
++	s->out_ptr -= len;
++	memmove(s->out_buf, &s->out_buf[len], s->out_ptr);
++	return ret;
++}
++
++static int usb_net_handle_data(USBDevice *dev, USBPacket *p)
++{
++	USBNetState *s = (USBNetState *)dev;
++	int ret = 0;
++
++	switch(p->pid) {
++	case USB_TOKEN_IN:
++		switch (p->devep) {
++		case 1:
++			ret = usb_net_handle_statusin(s, p);
++			break;
++
++		case 2:
++			ret = usb_net_handle_datain(s, p);
++			break;
++
++		default:
++			goto fail;
++		}
++		break;
++
++	case USB_TOKEN_OUT:
++		switch (p->devep) {
++		case 2:
++			ret = usb_net_handle_dataout(s, p);
++			break;
++
++		default:
++			goto fail;
++		}
++		break;
++
++	default:
++	fail:
++		ret = USB_RET_STALL;
++		break;
++	}
++	if (ret == USB_RET_STALL)
++		fprintf(stderr, "usbnet: failed data transaction: pid 0x%x ep 0x%x len 0x%x\n", p->pid, p->devep, p->len);
++	return ret;
++}
++
++static void usbnet_receive(void *opaque, const uint8_t *buf, int size)
++{
++	USBNetState *s = opaque;
++
++	if (s->rndis) {
++		struct rndis_packet_msg_type *msg = (struct rndis_packet_msg_type *)s->in_buf;
++		if (!s->rndis_state == RNDIS_DATA_INITIALIZED)
++			return;
++		if (size + sizeof(struct rndis_packet_msg_type) > sizeof(s->in_buf))
++			return;
++		memset(msg, 0, sizeof(struct rndis_packet_msg_type));
++		msg->MessageType = cpu_to_le32(REMOTE_NDIS_PACKET_MSG);
++		msg->MessageLength = cpu_to_le32(size + sizeof(struct rndis_packet_msg_type));
++		msg->DataOffset = cpu_to_le32(sizeof(struct rndis_packet_msg_type) - 8);
++		msg->DataLength = cpu_to_le32(size);
++		//msg->OOBDataOffset;
++		//msg->OOBDataLength;
++		//msg->NumOOBDataElements;
++		//msg->PerPacketInfoOffset;
++		//msg->PerPacketInfoLength;
++		//msg->VcHandle;
++		//msg->Reserved;
++		memcpy(msg + 1, buf, size);
++		s->in_len = size + sizeof(struct rndis_packet_msg_type);
++	} else {
++		if (size > sizeof(s->in_buf))
++			return;
++		memcpy(s->in_buf, buf, size);
++		s->in_len = size;
++	}
++	s->in_ptr = 0;
++}
++
++static int usbnet_can_receive(void *opaque)
++{
++	USBNetState *s = opaque;
++
++	if (s->rndis && !s->rndis_state == RNDIS_DATA_INITIALIZED)
++		return 1;
++	return !s->in_len;
++}
++
++static void usb_net_handle_destroy(USBDevice *dev)
++{
++	USBNetState *s = (USBNetState *)dev;
++	rndis_clear_responsequeue(s);
++	qemu_free(s);
++}
++
++USBDevice *usb_net_init(NICInfo *nd)
++{
++	USBNetState *s;
++
++	s = qemu_mallocz(sizeof(USBNetState));
++	if (!s)
++		return NULL;
++	s->dev.speed = USB_SPEED_FULL;
++	s->dev.handle_packet = usb_generic_handle_packet;
++
++	s->dev.handle_reset = usb_net_handle_reset;
++	s->dev.handle_control = usb_net_handle_control;
++	s->dev.handle_data = usb_net_handle_data;
++	s->dev.handle_destroy = usb_net_handle_destroy;
++
++	s->rndis = 1;
++	s->rndis_state = RNDIS_UNINITIALIZED;
++        s->medium = NDIS_MEDIUM_802_3;
++        s->speed = 1000000; /* 100MBps, in 100Bps units */
++        s->media_state = NDIS_MEDIA_STATE_CONNECTED;
++	s->filter = 0;
++        s->vendorid = 0x1234;
++	memcpy(s->mac, nd->macaddr, 6);
++	TAILQ_INIT(&s->rndis_resp);
++
++	pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Network Interface");
++	s->vc = qemu_new_vlan_client(nd->vlan, usbnet_receive, usbnet_can_receive, s);
++	snprintf(s->vc->info_str, sizeof(s->vc->info_str),
++		 "usbnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
++		 s->mac[0], s->mac[1], s->mac[2],
++		 s->mac[3], s->mac[4], s->mac[5]);
++	fprintf(stderr, "usbnet: initialized mac %02x:%02x:%02x:%02x:%02x:%02x\n",
++		s->mac[0], s->mac[1], s->mac[2],
++		s->mac[3], s->mac[4], s->mac[5]);
++	return (USBDevice *)s;
++}
+diff -urN 4242/Makefile qemu-omap/Makefile
+--- 4242/Makefile	2008-04-24 20:17:05.000000000 +0100
++++ qemu-omap/Makefile	2008-04-23 09:57:55.000000000 +0100
+@@ -55,7 +55,8 @@
+ OBJS+=tmp105.o
+ OBJS+=scsi-disk.o cdrom.o
+ OBJS+=scsi-generic.o
+-OBJS+=usb.o usb-hub.o usb-linux.o usb-hid.o usb-msd.o usb-wacom.o usb-serial.o
++OBJS+=usb.o usb-hub.o usb-linux.o usb-hid.o usb-msd.o usb-net.o
++OBJS+=usb-wacom.o usb-serial.o
+ OBJS+=sd.o ssi-sd.o
+ 
+ ifdef CONFIG_BRLAPI
+diff -urN 4242/softmmu_template.h qemu-omap/softmmu_template.h
+--- 4242/softmmu_template.h	2008-04-24 18:11:49.000000000 +0100
++++ qemu-omap/softmmu_template.h	2008-04-23 09:57:56.000000000 +0100
+@@ -51,12 +51,15 @@
                                                          int mmu_idx,
                                                          void *retaddr);
  static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr,
@@ -13821,7 +2162,7 @@ index 0a4bc7e..d480f34 100644
  #if SHIFT <= 2
      res = io_mem_read[index][SHIFT](io_mem_opaque[index], physaddr);
  #else
-@@ -95,7 +98,9 @@ DATA_TYPE REGPARM glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
+@@ -95,7 +98,9 @@
              /* IO access */
              if ((addr & (DATA_SIZE - 1)) != 0)
                  goto do_unaligned_access;
@@ -13832,7 +2173,7 @@ index 0a4bc7e..d480f34 100644
          } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
              /* slow unaligned access (it spans two pages or IO) */
          do_unaligned_access:
-@@ -147,7 +152,9 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
+@@ -147,7 +152,9 @@
              /* IO access */
              if ((addr & (DATA_SIZE - 1)) != 0)
                  goto do_unaligned_access;
@@ -13843,7 +2184,7 @@ index 0a4bc7e..d480f34 100644
          } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
          do_unaligned_access:
              /* slow unaligned access (it spans two pages) */
-@@ -186,11 +193,14 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
+@@ -186,11 +193,14 @@
  static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr,
                                            DATA_TYPE val,
                                            target_ulong tlb_addr,
@@ -13860,7 +2201,7 @@ index 0a4bc7e..d480f34 100644
      env->mem_write_vaddr = tlb_addr;
      env->mem_write_pc = (unsigned long)retaddr;
  #if SHIFT <= 2
-@@ -228,7 +238,8 @@ void REGPARM glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr,
+@@ -228,7 +238,8 @@
              if ((addr & (DATA_SIZE - 1)) != 0)
                  goto do_unaligned_access;
              retaddr = GETPC();
@@ -13870,7 +2211,7 @@ index 0a4bc7e..d480f34 100644
          } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
          do_unaligned_access:
              retaddr = GETPC();
-@@ -278,7 +289,8 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
+@@ -278,7 +289,8 @@
              /* IO access */
              if ((addr & (DATA_SIZE - 1)) != 0)
                  goto do_unaligned_access;
@@ -13880,91 +2221,161 @@ index 0a4bc7e..d480f34 100644
          } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
          do_unaligned_access:
              /* XXX: not efficient, but simple */
-diff --git a/target-arm/cpu.h b/target-arm/cpu.h
-index b284a21..633b335 100644
---- a/target-arm/cpu.h
-+++ b/target-arm/cpu.h
-@@ -198,12 +198,16 @@ typedef struct CPUARMState {
-     CPU_COMMON
+diff -urN 4242/target-i386/cpu.h qemu-omap/target-i386/cpu.h
+--- 4242/target-i386/cpu.h	2008-04-23 12:18:51.000000000 +0100
++++ qemu-omap/target-i386/cpu.h	2008-04-23 09:57:56.000000000 +0100
+@@ -499,7 +499,7 @@
+     SegmentCache idt; /* only base and limit are used */
+ 
+     target_ulong cr[9]; /* NOTE: cr1, cr5-7 are unused */
+-    uint64_t a20_mask;
++    uint32_t a20_mask;
+ 
+     /* FPU state */
+     unsigned int fpstt; /* top of stack index */
+diff -urN 4242/target-i386/helper2.c qemu-omap/target-i386/helper2.c
+--- 4242/target-i386/helper2.c	2008-04-23 12:18:51.000000000 +0100
++++ qemu-omap/target-i386/helper2.c	2008-04-23 09:57:56.000000000 +0100
+@@ -377,7 +377,7 @@
+     env->hflags |= HF_GIF_MASK;
+ 
+     cpu_x86_update_cr0(env, 0x60000010);
+-    env->a20_mask = ~0x0;
++    env->a20_mask = 0xffffffff;
+     env->smbase = 0x30000;
+ 
+     env->idt.limit = 0xffff;
+@@ -695,7 +695,7 @@
+         /* when a20 is changed, all the MMU mappings are invalid, so
+            we must flush everything */
+         tlb_flush(env, 1);
+-        env->a20_mask = (~0x100000) | (a20_state << 20);
++        env->a20_mask = 0xffefffff | (a20_state << 20);
+     }
+ }
  
-     /* These fields after the common ones so they are preserved on reset.  */
--    int ram_size;
--    const char *kernel_filename;
--    const char *kernel_cmdline;
--    const char *initrd_filename;
--    int board_id;
--    target_phys_addr_t loader_start;
-+    struct arm_boot_info {
-+        int ram_size;
-+        const char *kernel_filename;
-+        const char *kernel_cmdline;
-+        const char *initrd_filename;
-+        target_phys_addr_t loader_start;
-+        int nb_cpus;
-+        int board_id;
-+        int (*atag_board)(struct arm_boot_info *info, void *p);
-+    } *boot_info;
- } CPUARMState;
+@@ -800,8 +800,7 @@
  
- CPUARMState *cpu_arm_init(const char *cpu_model);
-@@ -377,6 +381,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
- #define ARM_CPUID_PXA270_C0   0x69054114
- #define ARM_CPUID_PXA270_C5   0x69054117
- #define ARM_CPUID_ARM1136     0x4117b363
-+#define ARM_CPUID_ARM1136_R2  0x4107b362
- #define ARM_CPUID_ARM11MPCORE 0x410fb022
- #define ARM_CPUID_CORTEXA8    0x410fc080
- #define ARM_CPUID_CORTEXM3    0x410fc231
-diff --git a/target-arm/helper.c b/target-arm/helper.c
-index 86470db..0709129 100644
---- a/target-arm/helper.c
-+++ b/target-arm/helper.c
-@@ -53,6 +53,9 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
-         env->cp15.c0_cachetype = 0x1dd20d2;
-         env->cp15.c1_sys = 0x00090078;
-         break;
-+    case ARM_CPUID_ARM1136_R2:
-+        /* TODO! */
-+        env->GE = 0x5;
-     case ARM_CPUID_ARM1136:
-         set_feature(env, ARM_FEATURE_V6);
-         set_feature(env, ARM_FEATURE_VFP);
-@@ -198,6 +201,7 @@ static const struct arm_cpu_t arm_cpu_names[] = {
-     { ARM_CPUID_ARM946, "arm946"},
-     { ARM_CPUID_ARM1026, "arm1026"},
-     { ARM_CPUID_ARM1136, "arm1136"},
-+    { ARM_CPUID_ARM1136_R2, "arm1136-r2"},
-     { ARM_CPUID_ARM11MPCORE, "arm11mpcore"},
-     { ARM_CPUID_CORTEXM3, "cortex-m3"},
-     { ARM_CPUID_CORTEXA8, "cortex-a8"},
-@@ -1539,6 +1543,7 @@ uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
-             case ARM_CPUID_ARM1026:
-                 return 1;
-             case ARM_CPUID_ARM1136:
-+            case ARM_CPUID_ARM1136_R2:
-                 return 7;
-             case ARM_CPUID_ARM11MPCORE:
-                 return 1;
-@@ -1721,6 +1726,10 @@ uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
-             case 8: /* TI925T_status */
-                 return 0;
-             }
-+            /* TODO: Peripheral port remap register:
-+             * On OMAP2 mcr p15, 0, rn, c15, c2, 4 sets up the interrupt
-+             * controller base address at $rn & ~0xfff and map size of
-+             * 0x200 << ($rn & 0xfff), when MMU is off.  */
-             goto bad_reg;
+ #else
+ 
+-/* Bits 52-62 of a PTE are reserved. Bit 63 is the NX bit. */
+-#define PHYS_ADDR_MASK 0xffffffffff000L
++#define PHYS_ADDR_MASK 0xfffff000
+ 
+ /* return value:
+    -1 = cannot handle fault
+@@ -813,10 +812,9 @@
+                              int is_write1, int mmu_idx, int is_softmmu)
+ {
+     uint64_t ptep, pte;
+-    target_ulong pde_addr, pte_addr;
++    uint32_t pdpe_addr, pde_addr, pte_addr;
+     int error_code, is_dirty, prot, page_size, ret, is_write, is_user;
+-    target_phys_addr_t paddr;
+-    uint32_t page_offset;
++    unsigned long paddr, page_offset;
+     target_ulong vaddr, virt_addr;
+ 
+     is_user = mmu_idx == MMU_USER_IDX;
+@@ -836,11 +834,12 @@
+ 
+     if (env->cr[4] & CR4_PAE_MASK) {
+         uint64_t pde, pdpe;
+-        target_ulong pdpe_addr;
+ 
++        /* XXX: we only use 32 bit physical addresses */
+ #ifdef TARGET_X86_64
+         if (env->hflags & HF_LMA_MASK) {
+-            uint64_t pml4e_addr, pml4e;
++            uint32_t pml4e_addr;
++            uint64_t pml4e;
+             int32_t sext;
+ 
+             /* test virtual address sign extension */
+@@ -1102,19 +1101,17 @@
+ 
+ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+ {
+-    target_ulong pde_addr, pte_addr;
+-    uint64_t pte;
+-    target_phys_addr_t paddr;
+-    uint32_t page_offset;
+-    int page_size;
++    uint32_t pde_addr, pte_addr;
++    uint32_t pde, pte, paddr, page_offset, page_size;
+ 
+     if (env->cr[4] & CR4_PAE_MASK) {
+-        target_ulong pdpe_addr;
+-        uint64_t pde, pdpe;
++        uint32_t pdpe_addr, pde_addr, pte_addr;
++        uint32_t pdpe;
+ 
++        /* XXX: we only use 32 bit physical addresses */
+ #ifdef TARGET_X86_64
+         if (env->hflags & HF_LMA_MASK) {
+-            uint64_t pml4e_addr, pml4e;
++            uint32_t pml4e_addr, pml4e;
+             int32_t sext;
+ 
+             /* test virtual address sign extension */
+@@ -1124,13 +1121,13 @@
+ 
+             pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
+                 env->a20_mask;
+-            pml4e = ldq_phys(pml4e_addr);
++            pml4e = ldl_phys(pml4e_addr);
+             if (!(pml4e & PG_PRESENT_MASK))
+                 return -1;
+ 
+             pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
+                 env->a20_mask;
+-            pdpe = ldq_phys(pdpe_addr);
++            pdpe = ldl_phys(pdpe_addr);
+             if (!(pdpe & PG_PRESENT_MASK))
+                 return -1;
+         } else
+@@ -1138,14 +1135,14 @@
+         {
+             pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
+                 env->a20_mask;
+-            pdpe = ldq_phys(pdpe_addr);
++            pdpe = ldl_phys(pdpe_addr);
+             if (!(pdpe & PG_PRESENT_MASK))
+                 return -1;
+         }
+ 
+         pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
+             env->a20_mask;
+-        pde = ldq_phys(pde_addr);
++        pde = ldl_phys(pde_addr);
+         if (!(pde & PG_PRESENT_MASK)) {
+             return -1;
+         }
+@@ -1158,11 +1155,9 @@
+             pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
+                 env->a20_mask;
+             page_size = 4096;
+-            pte = ldq_phys(pte_addr);
++            pte = ldl_phys(pte_addr);
          }
-         return 0;
-diff --git a/vl.c b/vl.c
-index d371af7..76d8def 100644
---- a/vl.c
-+++ b/vl.c
-@@ -8006,6 +8006,7 @@ static void register_machines(void)
-     qemu_register_machine(&borzoipda_machine);
-     qemu_register_machine(&terrierpda_machine);
-     qemu_register_machine(&palmte_machine);
-+    qemu_register_machine(&n800_machine);
-     qemu_register_machine(&lm3s811evb_machine);
-     qemu_register_machine(&lm3s6965evb_machine);
-     qemu_register_machine(&connex_machine);
+     } else {
+-        uint32_t pde;
+-
+         if (!(env->cr[0] & CR0_PG_MASK)) {
+             pte = addr;
+             page_size = 4096;
+diff -urN 4242/vl.c qemu-omap/vl.c
+--- 4242/vl.c	2008-04-24 21:26:21.000000000 +0100
++++ qemu-omap/vl.c	2008-04-23 09:57:57.000000000 +0100
+@@ -5284,6 +5284,11 @@
+         dev = usb_keyboard_init();
+     } else if (strstart(devname, "disk:", &p)) {
+         dev = usb_msd_init(p);
++    } else if (strstart(devname, "net:", &p)) {
++        unsigned int nr = strtoul(p, NULL, 0);
++        if (nr >= (unsigned int) nb_nics || strcmp(nd_table[nr].model, "usb"))
++            return -1;
++        dev = usb_net_init(&nd_table[nr]);
+     } else if (!strcmp(devname, "wacom-tablet")) {
+         dev = usb_wacom_init();
+     } else if (strstart(devname, "serial:", &p)) {
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/series b/meta/packages/qemu/qemu-0.9.1+svn/series
index 126da8828..fb110340c 100644
--- a/meta/packages/qemu/qemu-0.9.1+svn/series
+++ b/meta/packages/qemu/qemu-0.9.1+svn/series
@@ -1,5 +1,4 @@
-02_snapshot_use_tmpdir.patch -p0
-05_non-fatal_if_linux_hd_missing.patch -p1
+05_non-fatal_if_linux_hd_missing.patch 
 06_exit_segfault.patch -p0
 10_signal_jobs.patch -p0
 11_signal_sigaction.patch -p0
@@ -8,18 +7,19 @@
 32_syscall_sysctl.patch -p0
 33_syscall_ppc_clone.patch -p0
 39_syscall_fadvise64.patch -p0
-41_arm_fpa_sigfpe.patch -p0
-52_ne2000_return.patch -p1
+52_ne2000_return.patch 
 61_safe_64bit_int.patch -p0
 63_sparc_build.patch -p0
-64_ppc_asm_constraints.patch -p1
+64_ppc_asm_constraints.patch 
 65_kfreebsd.patch -p0
 66_tls_ld.patch -p0
 91-oh-sdl-cursor.patch -p0
-qemu-0.9.0-nptl.patch -p1
-qemu-0.9.0-nptl-update.patch -p1
-qemu-amd64-32b-mapping-0.9.0.patch -p1
+qemu-0.9.0-nptl.patch 
+qemu-0.9.0-nptl-update.patch 
+qemu-amd64-32b-mapping-0.9.0.patch 
 workaround_bad_futex_headers.patch -p1
-fix_segfault.patch -p1
-no-strip.patch -p1
+fix_segfault.patch 
+no-strip.patch 
+fix_brk.patch 
+fix_protection_bits.patch -p1
 qemu-n800-support.patch -p1
diff --git a/meta/packages/qemu/qemu-0.9.1+svn/writev_fix.patch b/meta/packages/qemu/qemu-0.9.1+svn/writev_fix.patch
deleted file mode 100644
index e0ed4af97..000000000
--- a/meta/packages/qemu/qemu-0.9.1+svn/writev_fix.patch
+++ /dev/null
@@ -1,17 +0,0 @@
----
- linux-user/syscall.c |    2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-Index: qemu-0.9.1/linux-user/syscall.c
-===================================================================
---- qemu-0.9.1.orig/linux-user/syscall.c	2008-02-03 00:00:00.000000000 +0000
-+++ qemu-0.9.1/linux-user/syscall.c	2008-02-03 00:00:38.000000000 +0000
-@@ -1048,7 +1048,7 @@ static abi_long lock_iovec(int type, str
-         base = tswapl(target_vec[i].iov_base);
-         vec[i].iov_len = tswapl(target_vec[i].iov_len);
-         vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
--	if (!vec[i].iov_base) 
-+	if (!vec[i].iov_base && vec[i].iov_len) 
-             goto fail;
-     }
-     unlock_user (target_vec, target_addr, 0);
diff --git a/meta/packages/qemu/qemu_0.9.1.bb b/meta/packages/qemu/qemu_0.9.1.bb
index a51e437f7..5400afb05 100644
--- a/meta/packages/qemu/qemu_0.9.1.bb
+++ b/meta/packages/qemu/qemu_0.9.1.bb
@@ -7,7 +7,6 @@ FILESDIR = "${WORKDIR}"
 
 SRC_URI = "\
     http://fabrice.bellard.free.fr/qemu/qemu-0.9.1.tar.gz \
-    file://02_snapshot_use_tmpdir.patch;patch=1;pnum=0 \
     file://04_do_not_print_rtc_freq_if_ok.patch;patch=1;pnum=1 \
     file://05_non-fatal_if_linux_hd_missing.patch;patch=1;pnum=1 \
     file://06_exit_segfault.patch;patch=1;pnum=0 \
diff --git a/meta/packages/qemu/qemu_svn.bb b/meta/packages/qemu/qemu_svn.bb
index 802d47b71..0d15a0c3a 100644
--- a/meta/packages/qemu/qemu_svn.bb
+++ b/meta/packages/qemu/qemu_svn.bb
@@ -1,13 +1,12 @@
 LICENSE = "GPL"
 DEPENDS = "zlib"
 PV = "0.9.1+svnr${SRCREV}"
-PR = "r3"
+PR = "r5"
 
 FILESPATH = "${FILE_DIRNAME}/qemu-0.9.1+svn/"
 
 SRC_URI = "\
     svn://svn.savannah.nongnu.org/qemu;module=trunk \
-    file://02_snapshot_use_tmpdir.patch;patch=1;pnum=0 \
     file://05_non-fatal_if_linux_hd_missing.patch;patch=1;pnum=1 \
     file://06_exit_segfault.patch;patch=1;pnum=0 \
     file://10_signal_jobs.patch;patch=1;pnum=0 \
@@ -17,7 +16,6 @@ SRC_URI = "\
     file://32_syscall_sysctl.patch;patch=1;pnum=0 \
     file://33_syscall_ppc_clone.patch;patch=1;pnum=0 \
     file://39_syscall_fadvise64.patch;patch=1;pnum=0 \
-    file://41_arm_fpa_sigfpe.patch;patch=1;pnum=0 \
     file://52_ne2000_return.patch;patch=1;pnum=1 \
     file://61_safe_64bit_int.patch;patch=1;pnum=0 \
     file://63_sparc_build.patch;patch=1;pnum=0 \
@@ -26,7 +24,6 @@ SRC_URI = "\
     file://66_tls_ld.patch;patch=1;pnum=0 \
     file://91-oh-sdl-cursor.patch;patch=1;pnum=0 \
     file://qemu-0.9.0-nptl.patch;patch=1 \
-    file://qemu-0.9.0-nptl-update.patch;patch=1 \
     file://qemu-amd64-32b-mapping-0.9.0.patch;patch=1 \
     file://workaround_bad_futex_headers.patch;patch=1 \
     file://fix_segfault.patch;patch=1 \
-- 
cgit v1.2.3