Merge branch 'upstream-1.7' into tizen_qemu_1.7
authorSeokYeon Hwang <syeon.hwang@samsung.com>
Wed, 11 Dec 2013 01:38:35 +0000 (10:38 +0900)
committerSeokYeon Hwang <syeon.hwang@samsung.com>
Wed, 11 Dec 2013 05:12:09 +0000 (14:12 +0900)
Signed-off-by: SeokYeon Hwang <syeon.hwang@samsung.com>
Conflicts:
VERSION
block/cow.c
block/raw-win32.c
block/stream.c
block/vmdk.c
blockdev.c
exec.c
hw/i386/pc_piix.c
hw/scsi/scsi-bus.c
include/qom/cpu.h
include/sysemu/kvm.h
qemu-img.c
tcg/tcg.c
tcg/tcg.h
vl.c

Change-Id: Ib8de93ad2c05150934e17e63d7f8e90ffdfccc62

57 files changed:
1  2 
.gitignore
Makefile
Makefile.target
arch_init.c
audio/audio.c
block.c
block/raw-win32.c
blockdev.c
configure
cpu-exec.c
cpus.c
default-configs/arm-softmmu.mak
exec.c
hw/Makefile.objs
hw/acpi/piix4.c
hw/arm/Makefile.objs
hw/display/vga.c
hw/i386/pc.c
hw/i386/pc_piix.c
hw/i386/pc_sysfw.c
hw/intc/apic_common.c
hw/pci/pci-hotplug-old.c
hw/pci/pci.c
hw/usb/dev-storage.c
hw/vigs/vigs_device.c
hw/virtio/virtio-pci.c
include/exec/cpu-defs.h
include/hw/i386/pc.h
include/qemu-common.h
include/sysemu/arch_init.h
include/sysemu/kvm.h
include/sysemu/sysemu.h
main-loop.c
qapi-schema.json
qemu-char.c
qemu-options.hx
qom/object.c
target-i386/translate.c
tcg/i386/tcg-target.c
tcg/tcg.c
tcg/tcg.h
tizen/src/ecs/ecs.c
tizen/src/hw/maru_board.c
tizen/src/hw/maru_brill_codec.c
tizen/src/hw/maru_brill_codec.h
tizen/src/hw/maru_camera_common_pci.c
tizen/src/hw/maru_vga.c
tizen/src/hw/maru_vga_template.h
tizen/src/maru_sdl.c
tizen/src/mloop_event.c
ui/input.c
ui/sdl.c
util/oslib-posix.c
util/oslib-win32.c
util/qemu-sockets.c
vl.c
xen-all.c

diff --cc .gitignore
@@@ -1,3 -1,3 +1,4 @@@
++config.status
  config-devices.*
  config-all-devices.*
  config-all-disas.*
diff --cc Makefile
Simple merge
diff --cc Makefile.target
@@@ -125,18 -121,8 +121,18 @@@ LIBS+=$(libs_softmmu
  
  # xen support
  obj-$(CONFIG_XEN) += xen-all.o xen-mapcache.o
- obj-$(CONFIG_NO_XEN) += xen-stub.o
+ obj-$(call lnot,$(CONFIG_XEN)) += xen-stub.o
  
 +# HAX support
 +ifdef CONFIG_WIN32
 +obj-$(CONFIG_HAX) += target-i386/hax-all.o target-i386/hax-windows.o
 +obj-$(CONFIG_NO_HAX) += hax-stub.o
 +endif
 +ifdef CONFIG_DARWIN
 +obj-$(CONFIG_HAX) += target-i386/hax-all.o target-i386/hax-darwin.o
 +obj-$(CONFIG_NO_HAX) += hax-stub.o
 +endif
 +
  # Hardware support
  ifeq ($(TARGET_NAME), sparc64)
  obj-y += hw/sparc64/
diff --cc arch_init.c
Simple merge
diff --cc audio/audio.c
Simple merge
diff --cc block.c
+++ b/block.c
@@@ -1605,9 -1715,10 +1715,12 @@@ static void bdrv_delete(BlockDriverStat
      assert(!bs->dev);
      assert(!bs->job);
      assert(!bs->in_use);
+     assert(!bs->refcnt);
+     bdrv_close(bs);
  
 +    bdrv_close(bs);
 +
      /* remove from list, if necessary */
      bdrv_make_anon(bs);
  
@@@ -239,9 -235,12 +240,10 @@@ static QemuOptsList raw_runtime_opts = 
      },
  };
  
- static int raw_open(BlockDriverState *bs, QDict *options, int flags)
+ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
+                     Error **errp)
  {
      BDRVRawState *s = bs->opaque;
 -    int access_flags;
 -    DWORD overlapped;
      QemuOpts *opts;
      Error *local_err = NULL;
      const char *filename;
@@@ -575,16 -538,13 +582,18 @@@ static int hdev_probe_device(const cha
      return 0;
  }
  
- static int hdev_open(BlockDriverState *bs, QDict *options, int flags)
+ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
+                      Error **errp)
  {
      BDRVRawState *s = bs->opaque;
 +#ifndef CONFIG_MARU
      int access_flags, create_flags;
+     int ret = 0;
      DWORD overlapped;
 +#else
 +    int open_flags;
 +#endif
 +    int ret = 0;
      char device_name[64];
  
      Error *local_err = NULL;
          if (err == ERROR_ACCESS_DENIED) {
              ret = -EACCES;
          } else {
-             ret = -1;
+             ret = -EINVAL;
          }
+         error_setg_errno(errp, -ret, "Could not open device");
          goto done;
      }
 +#else
 +      /*
 +    s->hfile = CreateFile(g_win32_locale_filename_from_utf8(filename),
 +                          access_flags,
 +                          FILE_SHARE_READ, NULL,
 +                          create_flags, overlapped, NULL);
 +      */
 +    open_flags = (O_BINARY & ~O_ACCMODE);
 +    if (flags & BDRV_O_RDWR) {
 +        open_flags |= O_RDWR;
 +    } else {
 +        open_flags |= O_RDONLY;
 +    }
 +
 +    /* Use O_DSYNC for write-through caching, no flags for write-back caching,
 +     * and O_DIRECT for no caching. */
 +    /*
 +       if ((flags & BDRV_O_NOCACHE)) {
 +       open_flags |= O_DIRECT;
 +       }
 +       if (!(flags & BDRV_O_CACHE_WB)) {
 +       open_flags |= O_DSYNC;
 +       }
 +     */
 +
 +    ret = qemu_open(filename, open_flags, 0644);
 +    if (ret < 0) {
 +        error_report("raw_open failed(%d) \n", ret);
 +        return -errno;
 +    }
 +    s->hfile = (HANDLE)_get_osfhandle(ret);
 +#endif
 +    return 0;
  
  done:
      qemu_opts_del(opts);
diff --cc blockdev.c
@@@ -281,27 -288,11 +288,16 @@@ static int parse_block_error_action(con
      }
  }
  
- static bool do_check_io_limits(BlockIOLimit *io_limits, Error **errp)
 +#ifdef CONFIG_MARU
 +extern int start_simple_client(char* msg);
 +extern char* maru_convert_path(char* msg, const char *path);
 +#endif
 +
+ static bool check_throttle_config(ThrottleConfig *cfg, Error **errp)
  {
-     bool bps_flag;
-     bool iops_flag;
-     assert(io_limits);
-     bps_flag  = (io_limits->bps[BLOCK_IO_LIMIT_TOTAL] != 0)
-                  && ((io_limits->bps[BLOCK_IO_LIMIT_READ] != 0)
-                  || (io_limits->bps[BLOCK_IO_LIMIT_WRITE] != 0));
-     iops_flag = (io_limits->iops[BLOCK_IO_LIMIT_TOTAL] != 0)
-                  && ((io_limits->iops[BLOCK_IO_LIMIT_READ] != 0)
-                  || (io_limits->iops[BLOCK_IO_LIMIT_WRITE] != 0));
-     if (bps_flag || iops_flag) {
-         error_setg(errp, "bps(iops) and bps_rd/bps_wr(iops_rd/iops_wr) "
-                          "cannot be used at the same time");
+     if (throttle_conflicting(cfg)) {
+         error_setg(errp, "bps/iops/max total values and read/write values"
+                          " cannot be used at the same time");
          return false;
      }
  
@@@ -691,45 -509,15 +514,25 @@@ static DriveInfo *blockdev_init(QDict *
          bdrv_flags |= BDRV_O_INCOMING;
      }
  
-     if (media == MEDIA_CDROM) {
-         /* CDROM is fine for any interface, don't check.  */
-         ro = 1;
-     } else if (ro == 1) {
-         if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY &&
-             type != IF_NONE && type != IF_PFLASH) {
-             error_report("read-only not supported by this bus type");
-             goto err;
-         }
-     }
      bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
  
-     if (ro && copy_on_read) {
-         error_report("warning: disabling copy_on_read on read-only drive");
-     }
      QINCREF(bs_opts);
-     ret = bdrv_open(dinfo->bdrv, file, bs_opts, bdrv_flags, drv);
+     ret = bdrv_open(dinfo->bdrv, file, bs_opts, bdrv_flags, drv, &error);
  
      if (ret < 0) {
-         if (ret == -EMEDIUMTYPE) {
-             error_report("could not open disk image %s: not in %s format",
-                          file ?: dinfo->id, drv ? drv->format_name :
-                          qdict_get_str(bs_opts, "driver"));
-         } else {
-             error_report("could not open disk image %s: %s",
-                          file ?: dinfo->id, strerror(-ret));
-         }
 +#ifdef CONFIG_MARU
 +        const char _msg[] = "Failed to load disk file from the following path. Check if the file is corrupted or missing.\n\n";
 +          char* err_msg = NULL;
 +        err_msg = maru_convert_path((char*)_msg, file);
 +        start_simple_client(err_msg);
 +        if (err_msg) {
 +            g_free(err_msg);
 +        }
 +#endif
 +
+         error_setg(errp, "could not open disk image %s: %s",
+                    file ?: dinfo->id, error_get_pretty(error));
+         error_free(error);
          goto err;
      }
  
diff --cc configure
+++ b/configure
@@@ -230,14 -242,12 +243,17 @@@ rbd="
  smartcard_nss=""
  libusb=""
  usb_redir=""
 +opengl=""
 +efence="no"
 +yagl="no"
 +yagl_stats="no"
  glx=""
 +vigs="no"
  zlib="yes"
  guest_agent=""
+ guest_agent_with_vss="no"
+ vss_win32_sdk=""
+ win_sdk="no"
  want_tools="yes"
  libiscsi=""
  coroutine=""
@@@ -562,14 -579,9 +591,13 @@@ Haiku
    kvm="yes"
    vhost_net="yes"
    vhost_scsi="yes"
-   if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
+   if [ "$cpu" = "i386" -o "$cpu" = "x86_64" -o "$cpu" = "x32" ] ; then
      audio_possible_drivers="$audio_possible_drivers fmod"
    fi
 +
 +# fix linking error on Ubuntu 13.04
 +#  libs_qga="-lrt $libs_qga"
 +#  QEMU_INCLUDES="-I\$(SRC_PATH)/linux-headers $QEMU_INCLUDES"
    QEMU_INCLUDES="-I\$(SRC_PATH)/linux-headers -I$(pwd)/linux-headers $QEMU_INCLUDES"
  ;;
  esac
@@@ -1232,11 -1225,9 +1291,13 @@@ echo "  --gcov=GCOV              use sp
  echo "  --enable-tpm             enable TPM support"
  echo "  --disable-libssh2        disable ssh block device support"
  echo "  --enable-libssh2         enable ssh block device support"
+ echo "  --disable-vhdx           disables support for the Microsoft VHDX image format"
+ echo "  --enable-vhdx            enable support for the Microsoft VHDX image format"
  echo ""
 +# for TIZEN-maru
 +echo "TIZEN-maru options:"
 +echo "  --enable-maru            enable maru board"
 +echo "  --enable-shm             enable shared memory for framebuffer"
  echo "NOTE: The object files are built at the place where configure is launched"
  exit 1
  fi
@@@ -3690,14 -3775,10 +3847,15 @@@ echo "xfsctl support    $xfs
  echo "nss used          $smartcard_nss"
  echo "libusb            $libusb"
  echo "usb net redir     $usb_redir"
 +echo "OpenGL support    $opengl"
 +echo "EFence support    $efence"
 +echo "YaGL support      $yagl"
 +echo "YaGL stats        $yagl_stats"
  echo "GLX support       $glx"
 +echo "VIGS support      $vigs"
  echo "libiscsi support  $libiscsi"
  echo "build guest agent $guest_agent"
+ echo "QGA VSS support   $guest_agent_with_vss"
  echo "seccomp support   $seccomp"
  echo "coroutine backend $coroutine"
  echo "coroutine pool    $coroutine_pool"
@@@ -3709,12 -3790,8 +3867,13 @@@ echo "TPM support       $tpm
  echo "libssh2 support   $libssh2"
  echo "TPM passthrough   $tpm_passthrough"
  echo "QOM debugging     $qom_cast_debug"
+ echo "vhdx              $vhdx"
  
 +# for TIZEN-maru
 +echo "TIZEN-maru support $maru"
 +echo "TIZEN-maru shared framebuffer support $shm"
 +#
 +
  if test "$sdl_too_old" = "yes"; then
  echo "-> Your SDL version is too old - please upgrade to have SDL support"
  fi
@@@ -4138,36 -4183,17 +4294,27 @@@ if test "$virtio_blk_data_plane" = "yes
    echo 'CONFIG_VIRTIO_BLK_DATA_PLANE=$(CONFIG_VIRTIO)' >> $config_host_mak
  fi
  
+ if test "$vhdx" = "yes" ; then
+   echo "CONFIG_VHDX=y" >> $config_host_mak
+ fi
  # USB host support
- case "$usb" in
- linux)
-   echo "HOST_USB=linux legacy" >> $config_host_mak
- ;;
- bsd)
-   echo "HOST_USB=bsd" >> $config_host_mak
- ;;
- libusb)
-   if test "$linux" = "yes"; then
-     echo "HOST_USB=libusb linux legacy" >> $config_host_mak
-   else
-     echo "HOST_USB=libusb legacy" >> $config_host_mak
-   fi
- ;;
- *)
+ if test "$libusb" = "yes"; then
+   echo "HOST_USB=libusb legacy" >> $config_host_mak
+ else
    echo "HOST_USB=stub" >> $config_host_mak
- ;;
- esac
+ fi
  
 +# for TIZEN-maru
 +if test "$maru" = "yes" ; then
 +  echo "CONFIG_MARU=y" >> $config_host_mak
 +fi
 +if test "$shm" = "yes" ; then
 +  echo "CONFIG_USE_SHM=y" >> $config_host_mak
 +fi
 +if test "$gl" = "yes" ; then
 +  echo "CONFIG_GL_BACKEND=y" >> $config_host_mak
 +fi
  # TPM passthrough support?
  if test "$tpm" = "yes"; then
    echo 'CONFIG_TPM=$(CONFIG_SOFTMMU)' >> $config_host_mak
diff --cc cpu-exec.c
Simple merge
diff --cc cpus.c
Simple merge
@@@ -80,5 -79,5 +80,6 @@@ CONFIG_ZYNQ=
  CONFIG_VERSATILE_PCI=y
  CONFIG_VERSATILE_I2C=y
  
 +CONFIG_SOUND=y
  CONFIG_SDHCI=y
+ CONFIG_INTEGRATOR_DEBUG=y
diff --cc exec.c
--- 1/exec.c
--- 2/exec.c
+++ b/exec.c
@@@ -1123,41 -1114,32 +1115,47 @@@ ram_addr_t qemu_ram_alloc_from_ptr(ram_
      if (host) {
          new_block->host = host;
          new_block->flags |= RAM_PREALLOC_MASK;
-     } else {
+     } else if (xen_enabled()) {
          if (mem_path) {
- #if defined (__linux__) && !defined(TARGET_S390X)
-             new_block->host = file_ram_alloc(new_block, size, mem_path);
-             if (!new_block->host) {
-                 new_block->host = qemu_anon_ram_alloc(size);
-                 memory_try_enable_merging(new_block->host, size);
-             }
- #else
-             fprintf(stderr, "-mem-path option unsupported\n");
+             fprintf(stderr, "-mem-path not supported with Xen\n");
              exit(1);
- #endif
-         } else {
-             if (xen_enabled()) {
-                 xen_ram_alloc(new_block->offset, size, mr);
-             } else if (kvm_enabled()) {
-                 /* some s390/kvm configurations have special constraints */
-                 new_block->host = kvm_ram_alloc(size);
-             } else {
-                 new_block->host = qemu_anon_ram_alloc(size);
- #ifdef CONFIG_HAX
+         }
+         xen_ram_alloc(new_block->offset, size, mr);
+     } else {
+         if (mem_path) {
+             if (phys_mem_alloc != qemu_anon_ram_alloc) {
                  /*
-                  * In Hax, the qemu allocate the virtual address, and HAX kernel
-                  * populate the memory with physical memory. Currently we have no
-                  * paging, so user should make sure enough free memory in advance
+                  * file_ram_alloc() needs to allocate just like
+                  * phys_mem_alloc, but we haven't bothered to provide
+                  * a hook there.
                   */
-                 if (hax_enabled()) {
-                     int ret;
-                     ret = hax_populate_ram((uint64_t)new_block->host, size);
-                     if (ret < 0) {
-                         fprintf(stderr, "Hax failed to populate ram\n");
-                         exit(-1);
-                     }
+                 fprintf(stderr,
+                         "-mem-path not supported with this accelerator\n");
+                 exit(1);
+             }
+             new_block->host = file_ram_alloc(new_block, size, mem_path);
+         }
+         if (!new_block->host) {
+             new_block->host = phys_mem_alloc(size);
++#ifdef CONFIG_HAX
++            /*
++             * In Hax, the qemu allocate the virtual address, and HAX kernel
++             * populate the memory with physical memory. Currently we have no
++             * paging, so user should make sure enough free memory in advance
++             */
++            if (hax_enabled()) {
++                int ret;
++                ret = hax_populate_ram((uint64_t)new_block->host, size);
++                if (ret < 0) {
++                    fprintf(stderr, "Hax failed to populate ram\n");
++                    exit(-1);
 +                }
++            }
 +#endif
+             if (!new_block->host) {
+                 fprintf(stderr, "Cannot set up guest memory '%s': %s\n",
+                         new_block->mr->name, strerror(errno));
+                 exit(1);
              }
              memory_try_enable_merging(new_block->host, size);
          }
Simple merge
diff --cc hw/acpi/piix4.c
  #include "exec/ioport.h"
  #include "hw/nvram/fw_cfg.h"
  #include "exec/address-spaces.h"
+ #include "hw/acpi/piix4.h"
  
 +#ifdef CONFIG_MARU
 +#include "tizen/src/hw/maru_pm.h"
 +#endif
 +
  //#define DEBUG
  
  #ifdef DEBUG
@@@ -1,34 -1,6 +1,34 @@@
 +obj-y = arm_pic.o
 +obj-y += arm_boot.o
 +obj-y += zynq_slcr.o
 +obj-y += arm_gic.o arm_gic_common.o
 +obj-y += realview_gic.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 +obj-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o
 +obj-y += exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o
 +obj-y += exynos4210_pmu.o exynos4210_mct.o exynos4210_fimd.o
 +obj-y += exynos4210_rtc.o exynos4210_i2c.o
 +obj-y += exynos4210_cmu.o exynos4210_g3d.o
 +obj-y += exynos4210_i2s.o exynos4210_audio.o
 +obj-y += arm_mptimer.o a15mpcore.o
 +obj-y += armv7m.o armv7m_nvic.o stellaris_enet.o
 +obj-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
 +obj-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
 +obj-y += zaurus.o ide/microdrive.o tc6393xb.o
 +obj-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o \
 +                omap_gpio.o omap_intc.o omap_uart.o
 +obj-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
 +                omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o omap_l4.o
 +obj-y += tsc210x.o
 +obj-y += blizzard.o onenand.o cbus.o tusb6010.o usb/hcd-musb.o
 +obj-y += mst_fpga.o
 +obj-y += bitbang_i2c.o marvell_88w8618_audio.o
 +obj-y += framebuffer.o
 +obj-y += strongarm.o
 +obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 +obj-$(CONFIG_FDT) += ../device_tree.o
  obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
  obj-y += integratorcp.o kzm.o mainstone.o musicpal.o nseries.o
- obj-y += omap_sx1.o palm.o pic_cpu.o realview.o spitz.o stellaris.o
+ obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o
  obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o
  
  obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
Simple merge
diff --cc hw/i386/pc.c
  #include "hw/cpu/icc_bus.h"
  #include "hw/boards.h"
  #include "hw/pci/pci_host.h"
+ #include "acpi-build.h"
  
 +#ifdef CONFIG_MARU
 +#include "../../tizen/src/maru_err_table.h"
 +#endif
  /* debug PC/ISA interrupts */
  //#define DEBUG_IRQ
  
  
  #define MAX_IDE_BUS 2
  
++#ifdef CONFIG_MARU
++void pc_init_pci(QEMUMachineInitArgs *args);
++
++extern MemoryRegion *global_ram_memory; 
++extern void *preallocated_ptr;
++#endif
++
  static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
  static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
  static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
@@@ -129,19 -128,20 +135,32 @@@ static void pc_init1(QEMUMachineInitArg
      guest_info->has_pci_info = has_pci_info;
      guest_info->isapc_ram_fw = !pci_enabled;
  
++#ifdef CONFIG_MARU
++    // for ramdump...
++    global_ram_memory = ram_memory;
++#endif
++
      /* allocate ram and load rom/bios */
      if (!xen_enabled()) {
++#ifdef CONFIG_MARU
++        // W/A for allocate larger continuous heap.
++        // see vl.c
++        if(preallocated_ptr != NULL) {
++            g_free(preallocated_ptr);
++        }
++#endif
          fw_cfg = pc_memory_init(system_memory,
-                        kernel_filename, kernel_cmdline, initrd_filename,
 -                       args->kernel_filename, args->kernel_cmdline,
 -                       args->initrd_filename,
--                       below_4g_mem_size, above_4g_mem_size,
--                       rom_memory, &ram_memory, guest_info);
++                args->kernel_filename, args->kernel_cmdline,
++                args->initrd_filename,
++                below_4g_mem_size, above_4g_mem_size,
++                rom_memory, &ram_memory, guest_info);
      }
  
      gsi_state = g_malloc0(sizeof(*gsi_state));
      if (kvm_irqchip_in_kernel()) {
          kvm_pc_setup_irq_routing(pci_enabled);
          gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
--                                 GSI_NUM_PINS);
++                GSI_NUM_PINS);
      } else {
          gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
      }
      if (pci_enabled) {
          pc_pci_device_init(pci_bus);
      }
-     if (has_pvpanic) {
-         pvpanic_init(isa_bus);
-     }
  }
  
++#ifdef CONFIG_MARU
++void pc_init_pci(QEMUMachineInitArgs *args)
++#else
  static void pc_init_pci(QEMUMachineInitArgs *args)
++#endif
  {
-     ram_addr_t ram_size = args->ram_size;
-     const char *cpu_model = args->cpu_model;
-     const char *kernel_filename = args->kernel_filename;
-     const char *kernel_cmdline = args->kernel_cmdline;
-     const char *initrd_filename = args->initrd_filename;
-     const char *boot_device = args->boot_device;
-     pc_init1(get_system_memory(),
-              get_system_io(),
-              ram_size, boot_device,
-              kernel_filename, kernel_cmdline,
-              initrd_filename, cpu_model, 1, 1);
+     pc_init1(args, 1, 1);
  }
  
- static void pc_init_pci_1_6(QEMUMachineInitArgs *args)
+ static void pc_compat_1_6(QEMUMachineInitArgs *args)
  {
      has_pci_info = false;
-     pc_init_pci(args);
+     rom_file_in_ram = false;
+     has_acpi_build = false;
  }
  
- static void pc_init_pci_1_5(QEMUMachineInitArgs *args)
+ static void pc_compat_1_5(QEMUMachineInitArgs *args)
  {
-     has_pvpanic = true;
-     pc_init_pci_1_6(args);
+     pc_compat_1_6(args);
  }
  
- static void pc_init_pci_1_4(QEMUMachineInitArgs *args)
+ static void pc_compat_1_4(QEMUMachineInitArgs *args)
  {
+     pc_compat_1_5(args);
      x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE);
      x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ);
-     has_pci_info = false;
-     pc_init_pci(args);
  }
  
- static void pc_init_pci_1_3(QEMUMachineInitArgs *args)
+ static void pc_compat_1_3(QEMUMachineInitArgs *args)
  {
+     pc_compat_1_4(args);
      enable_compat_apic_id_mode();
-     pc_init_pci_1_4(args);
  }
  
- /* PC machine init function for pc-1.1 to pc-1.2 */
- static void pc_init_pci_1_2(QEMUMachineInitArgs *args)
+ /* PC compat function for pc-0.14 to pc-1.2 */
+ static void pc_compat_1_2(QEMUMachineInitArgs *args)
  {
+     pc_compat_1_3(args);
      disable_kvm_pv_eoi();
-     pc_init_pci_1_3(args);
  }
  
- /* PC machine init function for pc-0.14 to pc-1.0 */
- static void pc_init_pci_1_0(QEMUMachineInitArgs *args)
+ static void pc_init_pci_1_6(QEMUMachineInitArgs *args)
+ {
+     pc_compat_1_6(args);
+     pc_init_pci(args);
+ }
+ static void pc_init_pci_1_5(QEMUMachineInitArgs *args)
+ {
+     pc_compat_1_5(args);
+     pc_init_pci(args);
+ }
+ static void pc_init_pci_1_4(QEMUMachineInitArgs *args)
+ {
+     pc_compat_1_4(args);
+     pc_init_pci(args);
+ }
+ static void pc_init_pci_1_3(QEMUMachineInitArgs *args)
  {
-     pc_init_pci_1_2(args);
+     pc_compat_1_3(args);
+     pc_init_pci(args);
+ }
+ /* PC machine init function for pc-0.14 to pc-1.2 */
+ static void pc_init_pci_1_2(QEMUMachineInitArgs *args)
+ {
+     pc_compat_1_2(args);
+     pc_init_pci(args);
  }
  
  /* PC init function for pc-0.10 to pc-0.13, and reused by xenfv */
Simple merge
Simple merge
Simple merge
diff --cc hw/pci/pci.c
Simple merge
Simple merge
index ef8e2d4,0000000..6cc986d
mode 100644,000000..100644
--- /dev/null
@@@ -1,372 -1,0 +1,372 @@@
-         qemu_irq_lower(s->dev.pci_dev.irq[0]);
 +/*
 + * vigs
 + *
 + * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
 + *
 + * Contact:
 + * Stanislav Vorobiov <s.vorobiov@samsung.com>
 + * Jinhyung Jo <jinhyung.jo@samsung.com>
 + * YeongKyoon Lee <yeongkyoon.lee@samsung.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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + */
 +
 +#include "vigs_device.h"
 +#include "vigs_log.h"
 +#include "vigs_server.h"
 +#include "vigs_backend.h"
 +#include "vigs_regs.h"
 +#include "hw/hw.h"
 +#include "ui/console.h"
 +
 +#define PCI_VENDOR_ID_VIGS 0x19B2
 +#define PCI_DEVICE_ID_VIGS 0x1011
 +
 +#define VIGS_IO_SIZE 0x1000
 +
 +typedef struct VIGSState
 +{
 +    VIGSDevice dev;
 +
 +    void *display;
 +
 +    MemoryRegion vram_bar;
 +    uint32_t vram_size;
 +
 +    MemoryRegion ram_bar;
 +    uint32_t ram_size;
 +
 +    MemoryRegion io_bar;
 +
 +    struct vigs_server *server;
 +
 +    /*
 +     * Our console.
 +     */
 +    QemuConsole *con;
 +
 +    uint32_t reg_int;
 +} VIGSState;
 +
 +#define TYPE_VIGS_DEVICE "vigs"
 +
 +extern const char *vigs_backend;
 +
 +static void vigs_update_irq(VIGSState *s)
 +{
 +    if ((s->reg_int & VIGS_REG_INT_VBLANK_ENABLE) == 0) {
-         qemu_irq_raise(s->dev.pci_dev.irq[0]);
++        pci_set_irq(&s->dev.pci_dev, 0);
 +        return;
 +    }
 +
 +    if (s->reg_int & VIGS_REG_INT_VBLANK_PENDING) {
-         qemu_irq_lower(s->dev.pci_dev.irq[0]);
++        pci_set_irq(&s->dev.pci_dev, 1);
 +    } else {
++        pci_set_irq(&s->dev.pci_dev, 0);
 +    }
 +}
 +
 +static void vigs_hw_update(void *opaque)
 +{
 +    VIGSState *s = opaque;
 +    DisplaySurface *ds = qemu_console_surface(s->con);
 +
 +    if (!surface_data(ds)) {
 +        return;
 +    }
 +
 +    vigs_server_update_display(s->server);
 +
 +    dpy_gfx_update(s->con, 0, 0, surface_width(ds), surface_height(ds));
 +
 +    if (s->reg_int & VIGS_REG_INT_VBLANK_ENABLE) {
 +        s->reg_int |= VIGS_REG_INT_VBLANK_PENDING;
 +        vigs_update_irq(s);
 +    }
 +}
 +
 +static void vigs_hw_invalidate(void *opaque)
 +{
 +}
 +
 +static void vigs_dpy_resize(void *user_data,
 +                            uint32_t width,
 +                            uint32_t height)
 +{
 +    VIGSState *s = user_data;
 +    DisplaySurface *ds = qemu_console_surface(s->con);
 +
 +    if ((width != surface_width(ds)) ||
 +        (height != surface_height(ds)))
 +    {
 +        qemu_console_resize(s->con, width, height);
 +    }
 +}
 +
 +static uint32_t vigs_dpy_get_stride(void *user_data)
 +{
 +    VIGSState *s = user_data;
 +    DisplaySurface *ds = qemu_console_surface(s->con);
 +
 +    return surface_stride(ds);
 +}
 +
 +static uint32_t vigs_dpy_get_bpp(void *user_data)
 +{
 +    VIGSState *s = user_data;
 +    DisplaySurface *ds = qemu_console_surface(s->con);
 +
 +    return surface_bytes_per_pixel(ds);
 +}
 +
 +static uint8_t *vigs_dpy_get_data(void *user_data)
 +{
 +    VIGSState *s = user_data;
 +    DisplaySurface *ds = qemu_console_surface(s->con);
 +
 +    return surface_data(ds);
 +}
 +
 +static uint64_t vigs_io_read(void *opaque, hwaddr offset,
 +                             unsigned size)
 +{
 +    VIGSState *s = opaque;
 +
 +    switch (offset) {
 +    case VIGS_REG_INT:
 +        return s->reg_int;
 +    default:
 +        VIGS_LOG_CRITICAL("Bad register 0x%X read", (uint32_t)offset);
 +        break;
 +    }
 +
 +    return 0;
 +}
 +
 +static void vigs_io_write(void *opaque, hwaddr offset,
 +                          uint64_t value, unsigned size)
 +{
 +    VIGSState *s = opaque;
 +
 +    switch (offset) {
 +    case VIGS_REG_EXEC:
 +        vigs_server_dispatch(s->server, value);
 +        break;
 +    case VIGS_REG_INT:
 +        if (((s->reg_int & VIGS_REG_INT_VBLANK_PENDING) == 0) &&
 +            (value & VIGS_REG_INT_VBLANK_PENDING)) {
 +            VIGS_LOG_CRITICAL("Attempt to set VBLANK_PENDING");
 +            value &= ~VIGS_REG_INT_VBLANK_PENDING;
 +        }
 +
 +        if (((s->reg_int & VIGS_REG_INT_VBLANK_ENABLE) == 0) &&
 +            (value & VIGS_REG_INT_VBLANK_ENABLE)) {
 +            VIGS_LOG_DEBUG("VBLANK On");
 +        } else if (((value & VIGS_REG_INT_VBLANK_ENABLE) == 0) &&
 +                   (s->reg_int & VIGS_REG_INT_VBLANK_ENABLE)) {
 +            VIGS_LOG_DEBUG("VBLANK Off");
 +        }
 +
 +        s->reg_int = value & VIGS_REG_INT_MASK;
 +        if ((value & VIGS_REG_INT_VBLANK_ENABLE) == 0) {
 +            s->reg_int &= ~VIGS_REG_INT_VBLANK_PENDING;
 +        }
 +        vigs_update_irq(s);
 +        break;
 +    default:
 +        VIGS_LOG_CRITICAL("Bad register 0x%X write", (uint32_t)offset);
 +        break;
 +    }
 +}
 +
 +static struct GraphicHwOps vigs_hw_ops =
 +{
 +    .invalidate = vigs_hw_invalidate,
 +    .gfx_update = vigs_hw_update
 +};
 +
 +static const MemoryRegionOps vigs_io_ops =
 +{
 +    .read = vigs_io_read,
 +    .write = vigs_io_write,
 +    .endianness = DEVICE_NATIVE_ENDIAN,
 +};
 +
 +static struct vigs_display_ops vigs_dpy_ops =
 +{
 +    .resize = vigs_dpy_resize,
 +    .get_stride = vigs_dpy_get_stride,
 +    .get_bpp = vigs_dpy_get_bpp,
 +    .get_data = vigs_dpy_get_data,
 +};
 +
 +static int vigs_device_init(PCIDevice *dev)
 +{
 +    VIGSState *s = DO_UPCAST(VIGSState, dev.pci_dev, dev);
 +    struct vigs_backend *backend = NULL;
 +
 +    vigs_log_init();
 +
 +    if (s->vram_size < 16 * 1024 * 1024) {
 +        VIGS_LOG_WARN("\"vram_size\" is too small, defaulting to 16mb");
 +        s->vram_size = 16 * 1024 * 1024;
 +    }
 +
 +    if (s->ram_size < 1 * 1024 * 1024) {
 +        VIGS_LOG_WARN("\"ram_size\" is too small, defaulting to 1mb");
 +        s->ram_size = 1 * 1024 * 1024;
 +    }
 +
 +    pci_config_set_interrupt_pin(dev->config, 1);
 +
 +    memory_region_init_ram(&s->vram_bar, OBJECT(s),
 +                           TYPE_VIGS_DEVICE ".vram",
 +                           s->vram_size);
 +
 +    memory_region_init_ram(&s->ram_bar, OBJECT(s),
 +                           TYPE_VIGS_DEVICE ".ram",
 +                           s->ram_size);
 +
 +    memory_region_init_io(&s->io_bar, OBJECT(s),
 +                          &vigs_io_ops,
 +                          s,
 +                          TYPE_VIGS_DEVICE ".io",
 +                          VIGS_IO_SIZE);
 +
 +    pci_register_bar(&s->dev.pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->vram_bar);
 +    pci_register_bar(&s->dev.pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ram_bar);
 +    pci_register_bar(&s->dev.pci_dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io_bar);
 +
 +    if (!strcmp(vigs_backend, "gl")) {
 +        backend = vigs_gl_backend_create(s->display);
 +    } else if (!strcmp(vigs_backend, "sw")) {
 +        backend = vigs_sw_backend_create();
 +    }
 +
 +    if (!backend) {
 +        goto fail;
 +    }
 +
 +    s->con = graphic_console_init(DEVICE(dev), &vigs_hw_ops, s);
 +
 +    if (!s->con) {
 +        goto fail;
 +    }
 +
 +    s->server = vigs_server_create(memory_region_get_ram_ptr(&s->vram_bar),
 +                                   memory_region_get_ram_ptr(&s->ram_bar),
 +                                   &vigs_dpy_ops,
 +                                   s,
 +                                   backend);
 +
 +    if (!s->server) {
 +        goto fail;
 +    }
 +
 +    s->dev.wsi = &s->server->wsi;
 +
 +    VIGS_LOG_INFO("VIGS initialized");
 +
 +    VIGS_LOG_DEBUG("vram_size = %u", s->vram_size);
 +    VIGS_LOG_DEBUG("ram_size = %u", s->ram_size);
 +
 +    return 0;
 +
 +fail:
 +    if (backend) {
 +        backend->destroy(backend);
 +    }
 +
 +    memory_region_destroy(&s->io_bar);
 +    memory_region_destroy(&s->ram_bar);
 +    memory_region_destroy(&s->vram_bar);
 +
 +    vigs_log_cleanup();
 +
 +    return -1;
 +}
 +
 +static void vigs_device_reset(DeviceState *d)
 +{
 +    VIGSState *s = container_of(d, VIGSState, dev.pci_dev.qdev);
 +
 +    vigs_server_reset(s->server);
 +
 +    s->reg_int = 0;
 +
 +    VIGS_LOG_INFO("VIGS reset");
 +}
 +
 +static void vigs_device_exit(PCIDevice *dev)
 +{
 +    VIGSState *s = DO_UPCAST(VIGSState, dev.pci_dev, dev);
 +
 +    vigs_server_destroy(s->server);
 +
 +    memory_region_destroy(&s->io_bar);
 +    memory_region_destroy(&s->ram_bar);
 +    memory_region_destroy(&s->vram_bar);
 +
 +    VIGS_LOG_INFO("VIGS deinitialized");
 +
 +    vigs_log_cleanup();
 +}
 +
 +static Property vigs_properties[] = {
 +    {
 +        .name   = "display",
 +        .info   = &qdev_prop_ptr,
 +        .offset = offsetof(VIGSState, display),
 +    },
 +    DEFINE_PROP_UINT32("vram_size", VIGSState, vram_size,
 +                       32 * 1024 * 1024),
 +    DEFINE_PROP_UINT32("ram_size", VIGSState, ram_size,
 +                       1 * 1024 * 1024),
 +    DEFINE_PROP_END_OF_LIST(),
 +};
 +
 +static void vigs_class_init(ObjectClass *klass, void *data)
 +{
 +    DeviceClass *dc = DEVICE_CLASS(klass);
 +    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = vigs_device_init;
 +    k->exit = vigs_device_exit;
 +    k->vendor_id = PCI_VENDOR_ID_VIGS;
 +    k->device_id = PCI_DEVICE_ID_VIGS;
 +    k->class_id = PCI_CLASS_DISPLAY_VGA;
 +    dc->reset = vigs_device_reset;
 +    dc->props = vigs_properties;
 +    dc->desc = "VIGS device";
 +}
 +
 +static TypeInfo vigs_device_info =
 +{
 +    .name          = TYPE_VIGS_DEVICE,
 +    .parent        = TYPE_PCI_DEVICE,
 +    .instance_size = sizeof(VIGSState),
 +    .class_init    = vigs_class_init,
 +};
 +
 +static void vigs_register_types(void)
 +{
 +    type_register_static(&vigs_device_info);
 +}
 +
 +type_init(vigs_register_types)
@@@ -1501,347 -1502,10 +1502,348 @@@ static const TypeInfo virtio_rng_pci_in
      .class_init    = virtio_rng_pci_class_init,
  };
  
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_GL);
 +#ifdef CONFIG_MARU
 +/* virtio-gl-pci */
 +
 +static int virtio_gl_pci_init(VirtIOPCIProxy *vpci_dev)
 +{
 +    VirtIOGLPCI *dev = VIRTIO_GL_PCI(vpci_dev);
 +    DeviceState *vdev = DEVICE(&dev->vdev);
 +
 +    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
 +    if (qdev_init(vdev) < 0) {
 +        return -1;
 +    }
 +
 +    return 0;
 +}
 +
 +static void virtio_gl_pci_class_init(ObjectClass *klass, void *data)
 +{
 +    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
 +    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = virtio_gl_pci_init;
 +    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
 +    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_GL;
 +    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
 +    pcidev_k->class_id = PCI_CLASS_OTHERS;
 +}
 +
 +static void virtio_gl_pci_instance_init(Object *obj)
 +{
 +    VirtIOGLPCI *dev = VIRTIO_GL_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_TOUCHSCREEN);
++    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_GL);
 +    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 +}
 +
 +static TypeInfo virtio_gl_pci_info = {
 +    .name          = TYPE_VIRTIO_GL_PCI,
 +    .parent        = TYPE_VIRTIO_PCI,
 +    .instance_size = sizeof(VirtIOGLPCI),
 +    .instance_init = virtio_gl_pci_instance_init,
 +    .class_init    = virtio_gl_pci_class_init,
 +};
 +
 +/* virtio-touchscreen-pci */
 +
 +static int virtio_touchscreen_pci_init(VirtIOPCIProxy *vpci_dev)
 +{
 +    VirtIOTouchscreenPCI *dev = VIRTIO_TOUCHSCREEN_PCI(vpci_dev);
 +    DeviceState *vdev = DEVICE(&dev->vdev);
 +
 +    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
 +    if (qdev_init(vdev) < 0) {
 +        return -1;
 +    }
 +    return 0;
 +}
 +
 +static void virtio_touchscreen_pci_class_init(ObjectClass *klass, void *data)
 +{
 +//    DeviceClass *dc = DEVICE_CLASS(klass);
 +    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
 +    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = virtio_touchscreen_pci_init;
 +    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
 +    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_TOUCHSCREEN;
 +    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
 +    pcidev_k->class_id = PCI_CLASS_OTHERS;
 +}
 +
 +static void virtio_touchscreen_pci_instance_init(Object *obj)
 +{
 +    VirtIOTouchscreenPCI *dev = VIRTIO_TOUCHSCREEN_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_KEYBOARD);
++    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_TOUCHSCREEN);
 +    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 +}
 +
 +static TypeInfo virtio_touchscreen_pci_info = {
 +    .name          = TYPE_VIRTIO_TOUCHSCREEN_PCI,
 +    .parent        = TYPE_VIRTIO_PCI,
 +    .instance_size = sizeof(VirtIOTouchscreenPCI),
 +      .instance_init = virtio_touchscreen_pci_instance_init,
 +    .class_init    = virtio_touchscreen_pci_class_init,
 +};
 +
 +/* virtio-keyboard-pci */
 +
 +static int virtio_keyboard_pci_init(VirtIOPCIProxy *vpci_dev)
 +{
 +    VirtIOKeyboardPCI *dev = VIRTIO_KEYBOARD_PCI(vpci_dev);
 +    DeviceState *vdev = DEVICE(&dev->vdev);
 +
 +    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
 +    if (qdev_init(vdev) < 0) {
 +        return -1;
 +    }
 +    return 0;
 +}
 +
 +static void virtio_keyboard_pci_class_init(ObjectClass *klass, void *data)
 +{
 +//    DeviceClass *dc = DEVICE_CLASS(klass);
 +    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
 +    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = virtio_keyboard_pci_init;
 +    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
 +    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_KEYBOARD;
 +    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
 +    pcidev_k->class_id = PCI_CLASS_OTHERS;
 +}
 +
 +static void virtio_keyboard_pci_instance_init(Object *obj)
 +{
 +    VirtIOKeyboardPCI *dev = VIRTIO_KEYBOARD_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_ESM);
++    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_KEYBOARD);
 +    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 +}
 +
 +static TypeInfo virtio_keyboard_pci_info = {
 +    .name          = TYPE_VIRTIO_KEYBOARD_PCI,
 +    .parent        = TYPE_VIRTIO_PCI,
 +    .instance_size = sizeof(VirtIOKeyboardPCI),
 +      .instance_init = virtio_keyboard_pci_instance_init,
 +    .class_init    = virtio_keyboard_pci_class_init,
 +};
 +
 +/* virtio-esm-pci */
 +
 +static int virtio_esm_pci_init(VirtIOPCIProxy *vpci_dev)
 +{
 +    VirtIOESMPCI *dev = VIRTIO_ESM_PCI(vpci_dev);
 +    DeviceState *vdev = DEVICE(&dev->vdev);
 +
 +    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
 +    if (qdev_init(vdev) < 0) {
 +        return -1;
 +    }
 +    return 0;
 +}
 +
 +static void virtio_esm_pci_class_init(ObjectClass *klass, void *data)
 +{
 +//    DeviceClass *dc = DEVICE_CLASS(klass);
 +    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
 +    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = virtio_esm_pci_init;
 +    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
 +    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_ESM;
 +    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
 +    pcidev_k->class_id = PCI_CLASS_OTHERS;
 +}
 +
 +static void virtio_esm_pci_instance_init(Object *obj)
 +{
 +    VirtIOESMPCI *dev = VIRTIO_ESM_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_HWKEY);
++    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_ESM);
 +    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 +}
 +
 +static TypeInfo virtio_esm_pci_info = {
 +    .name          = TYPE_VIRTIO_ESM_PCI,
 +    .parent        = TYPE_VIRTIO_PCI,
 +    .instance_size = sizeof(VirtIOESMPCI),
 +      .instance_init = virtio_esm_pci_instance_init,
 +    .class_init    = virtio_esm_pci_class_init,
 +};
 +
 +/* virtio-hwkey-pci */
 +
 +static int virtio_hwkey_pci_init(VirtIOPCIProxy *vpci_dev)
 +{
 +    VirtIOHWKeyPCI *dev = VIRTIO_HWKEY_PCI(vpci_dev);
 +    DeviceState *vdev = DEVICE(&dev->vdev);
 +
 +    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
 +    if (qdev_init(vdev) < 0) {
 +        return -1;
 +    }
 +    return 0;
 +}
 +
 +static void virtio_hwkey_pci_class_init(ObjectClass *klass, void *data)
 +{
 +//    DeviceClass *dc = DEVICE_CLASS(klass);
 +    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
 +    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = virtio_hwkey_pci_init;
 +    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
 +    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_HWKEY;
 +    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
 +    pcidev_k->class_id = PCI_CLASS_OTHERS;
 +}
 +
 +static void virtio_hwkey_pci_instance_init(Object *obj)
 +{
 +    VirtIOHWKeyPCI *dev = VIRTIO_HWKEY_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_EVDI);
++    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_HWKEY);
 +    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 +}
 +
 +static TypeInfo virtio_hwkey_pci_info = {
 +    .name          = TYPE_VIRTIO_HWKEY_PCI,
 +    .parent        = TYPE_VIRTIO_PCI,
 +    .instance_size = sizeof(VirtIOHWKeyPCI),
 +      .instance_init = virtio_hwkey_pci_instance_init,
 +    .class_init    = virtio_hwkey_pci_class_init,
 +};
 +
 +/* virtio-evdi-pci */
 +
 +static int virtio_evdi_pci_init(VirtIOPCIProxy *vpci_dev)
 +{
 +    VirtIOEVDIPCI *dev = VIRTIO_EVDI_PCI(vpci_dev);
 +    DeviceState *vdev = DEVICE(&dev->vdev);
 +
 +    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
 +    if (qdev_init(vdev) < 0) {
 +        return -1;
 +    }
 +    return 0;
 +}
 +
 +static void virtio_evdi_pci_class_init(ObjectClass *klass, void *data)
 +{
 +//    DeviceClass *dc = DEVICE_CLASS(klass);
 +    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
 +    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = virtio_evdi_pci_init;
 +    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
 +    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_EVDI;
 +    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
 +    pcidev_k->class_id = PCI_CLASS_OTHERS;
 +}
 +
 +static void virtio_evdi_pci_instance_init(Object *obj)
 +{
 +    VirtIOEVDIPCI *dev = VIRTIO_EVDI_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SENSOR);
++    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_EVDI);
 +    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 +}
 +
 +static TypeInfo virtio_evdi_pci_info = {
 +    .name          = TYPE_VIRTIO_EVDI_PCI,
 +    .parent        = TYPE_VIRTIO_PCI,
 +    .instance_size = sizeof(VirtIOEVDIPCI),
 +      .instance_init = virtio_evdi_pci_instance_init,
 +    .class_init    = virtio_evdi_pci_class_init,
 +};
 +
 +/* virtio-sensor-pci */
 +
 +static int virtio_sensor_pci_init(VirtIOPCIProxy *vpci_dev)
 +{
 +    VirtIOSENSORPCI *dev = VIRTIO_SENSOR_PCI(vpci_dev);
 +    DeviceState *vdev = DEVICE(&dev->vdev);
 +
 +    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
 +    if (qdev_init(vdev) < 0) {
 +        return -1;
 +    }
 +    return 0;
 +}
 +
 +static void virtio_sensor_pci_class_init(ObjectClass *klass, void *data)
 +{
 +    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
 +    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = virtio_sensor_pci_init;
 +    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
 +    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SENSOR;
 +    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
 +    pcidev_k->class_id = PCI_CLASS_OTHERS;
 +}
 +
 +static void virtio_sensor_pci_instance_init(Object *obj)
 +{
 +    VirtIOSENSORPCI *dev = VIRTIO_SENSOR_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_NFC);
++    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SENSOR);
 +    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 +}
 +
 +static TypeInfo virtio_sensor_pci_info = {
 +    .name          = TYPE_VIRTIO_SENSOR_PCI,
 +    .parent        = TYPE_VIRTIO_PCI,
 +    .instance_size = sizeof(VirtIOSENSORPCI),
 +      .instance_init = virtio_sensor_pci_instance_init,
 +    .class_init    = virtio_sensor_pci_class_init,
 +};
 +
 +/* virtio NFC */
 +
 +static int virtio_nfc_pci_init(VirtIOPCIProxy *vpci_dev)
 +{
 +    VirtIONFCPCI *dev = VIRTIO_NFC_PCI(vpci_dev);
 +    DeviceState *vdev = DEVICE(&dev->vdev);
 +
 +    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
 +    if (qdev_init(vdev) < 0) {
 +        return -1;
 +    }
 +    return 0;
 +}
 +
 +static void virtio_nfc_pci_class_init(ObjectClass *klass, void *data)
 +{
 +    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
 +    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = virtio_nfc_pci_init;
 +    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
 +    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_NFC;
 +    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
 +    pcidev_k->class_id = PCI_CLASS_OTHERS;
 +}
 +
 +static void virtio_nfc_pci_instance_init(Object *obj)
 +{
 +    VirtIONFCPCI *dev = VIRTIO_NFC_PCI(obj);
++    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_NFC);
 +    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 +}
 +
 +static TypeInfo virtio_nfc_pci_info = {
 +    .name          = TYPE_VIRTIO_NFC_PCI,
 +    .parent        = TYPE_VIRTIO_PCI,
 +    .instance_size = sizeof(VirtIONFCPCI),
 +      .instance_init = virtio_nfc_pci_instance_init,
 +    .class_init    = virtio_nfc_pci_class_init,
 +};
 +
 +
 +#endif
 +
  /* virtio-pci-bus */
  
- static void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev)
+ static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size,
+                                VirtIOPCIProxy *dev)
  {
      DeviceState *qdev = DEVICE(dev);
      BusState *qbus;
@@@ -176,13 -176,7 +176,11 @@@ typedef struct CPUWatchpoint 
      sigjmp_buf jmp_env;                                                 \
      int exception_index;                                                \
                                                                          \
 +    /* for hax */                                                       \
 +    int hax_vcpu_dirty;                                                 \
 +    struct hax_vcpu_state *hax_vcpu;                                    \
 +                                                                        \
      /* user data */                                                     \
      void *opaque;                                                       \
-                                                                         \
-     const char *cpu_model_str;
  
  #endif
Simple merge
Simple merge
Simple merge
@@@ -296,13 -282,19 +282,23 @@@ int kvm_physical_memory_addr_from_host(
  
  #endif /* NEED_CPU_H */
  
+ void kvm_cpu_synchronize_state(CPUState *cpu);
  void kvm_cpu_synchronize_post_reset(CPUState *cpu);
  void kvm_cpu_synchronize_post_init(CPUState *cpu);
 +#ifdef CONFIG_HAX
 +void hax_cpu_synchronize_post_reset(CPUArchState *env);
 +void hax_cpu_synchronize_post_init(CPUArchState *env);
 +#endif
  
+ /* generic hooks - to be moved/refactored once there are more users */
+ static inline void cpu_synchronize_state(CPUState *cpu)
+ {
+     if (kvm_enabled()) {
+         kvm_cpu_synchronize_state(cpu);
+     }
+ }
  static inline void cpu_synchronize_post_reset(CPUState *cpu)
  {
      if (kvm_enabled()) {
Simple merge
diff --cc main-loop.c
Simple merge
Simple merge
diff --cc qemu-char.c
Simple merge
diff --cc qemu-options.hx
Simple merge
diff --cc qom/object.c
Simple merge
Simple merge
Simple merge
diff --cc tcg/tcg.c
Simple merge
diff --cc tcg/tcg.h
Simple merge
index 7bbd271,0000000..67e921d
mode 100644,000000..100644
--- /dev/null
@@@ -1,995 -1,0 +1,995 @@@
-         qemu_del_timer(cs->alive_timer);
 +/*
 + * Emulator Control Server
 + *
 + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
 + *
 + * Contact:
 + *  Jinhyung choi   <jinhyung2.choi@samsung.com>
 + *  MunKyu Im       <munkyu.im@samsung.com>
 + *  Daiyoung Kim    <daiyoung777.kim@samsung.com>
 + *  YeongKyoon Lee  <yeongkyoon.lee@samsung.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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + */
 +
 +#include <stdbool.h>
 +#include <pthread.h>
 +#include <stdlib.h>
 +
 +#include "hw/qdev.h"
 +#include "net/net.h"
 +#include "ui/console.h"
 +
 +#include "qemu-common.h"
 +#include "qemu/queue.h"
 +#include "qemu/sockets.h"
 +#include "qemu/option.h"
 +#include "qemu/timer.h"
 +#include "qemu/main-loop.h"
 +#include "sysemu/char.h"
 +#include "config.h"
 +#include "qapi/qmp/qint.h"
 +
 +#include "sdb.h"
 +#include "ecs.h"
 +#include "guest_server.h"
 +#include "emul_state.h"
 +
 +#include "genmsg/ecs.pb-c.h"
 +
 +#define DEBUG
 +
 +#ifndef min
 +#define min(a,b) ((a)<(b)?(a):(b))
 +#endif
 +
 +static QTAILQ_HEAD(ECS_ClientHead, ECS_Client)
 +clients = QTAILQ_HEAD_INITIALIZER(clients);
 +
 +static ECS_State *current_ecs;
 +
 +static void* keepalive_buf;
 +static int payloadsize;
 +
 +static int port;
 +static int port_setting = -1;
 +
 +static int log_fd = -1;
 +static int g_client_id = 1;
 +
 +static pthread_mutex_t mutex_clilist = PTHREAD_MUTEX_INITIALIZER;
 +
 +static int suspend_state = 1;
 +
 +void ecs_set_suspend_state(int state)
 +{
 +    suspend_state = state;
 +}
 +
 +int ecs_get_suspend_state(void)
 +{
 +    return suspend_state;
 +}
 +
 +static char* get_emulator_ecs_log_path(void)
 +{
 +    gchar *emulator_ecs_log_path = NULL;
 +    gchar *tizen_sdk_data = NULL;
 +#ifndef CONFIG_WIN32
 +    char emulator_ecs[] = "/emulator/vms/ecs.log";
 +#else
 +    char emulator_ecs[] = "\\emulator\\vms\\ecs.log";
 +#endif
 +
 +    tizen_sdk_data = get_tizen_sdk_data_path();
 +    if (!tizen_sdk_data) {
 +        LOG("failed to get tizen-sdk-data path.\n");
 +        return NULL;
 +    }
 +
 +    emulator_ecs_log_path =
 +        g_malloc(strlen(tizen_sdk_data) + sizeof(emulator_ecs) + 1);
 +    if (!emulator_ecs_log_path) {
 +        LOG("failed to allocate memory.\n");
 +        return NULL;
 +    }
 +
 +    g_snprintf(emulator_ecs_log_path, strlen(tizen_sdk_data) + sizeof(emulator_ecs),
 +             "%s%s", tizen_sdk_data, emulator_ecs);
 +
 +    g_free(tizen_sdk_data);
 +
 +    LOG("ecs log path: %s\n", emulator_ecs_log_path);
 +    return emulator_ecs_log_path;
 +}
 +
 +static char* get_emulator_ecs_prop_path(void)
 +{
 +    int path_len = 0;
 +    gchar *ecs_property_path = NULL;
 +    gchar *tizen_sdk_data = NULL;
 +#ifndef CONFIG_WIN32
 +    char emulator_vms[] = "/emulator/vms/";
 +    char ecs_prop[] = "/.ecs.properties";
 +#else
 +    char emulator_vms[] = "\\emulator\\vms\\";
 +    char ecs_prop[] = "\\.ecs.properties";
 +#endif
 +    char* emul_name = get_emul_vm_name();
 +
 +    tizen_sdk_data = get_tizen_sdk_data_path();
 +    if (!tizen_sdk_data) {
 +        LOG("failed to get tizen-sdk-data path.\n");
 +        return NULL;
 +    }
 +
 +    path_len = strlen(tizen_sdk_data) + sizeof(emulator_vms) + sizeof(ecs_prop) + strlen(emul_name);
 +    ecs_property_path = g_malloc(path_len + 1);
 +    g_snprintf(ecs_property_path, path_len, "%s%s%s%s", tizen_sdk_data, emulator_vms, emul_name, ecs_prop);
 +
 +    g_free(tizen_sdk_data);
 +    LOG("ecs property path: %s", ecs_property_path);
 +
 +    return ecs_property_path;
 +}
 +
 +static inline void start_logging(void) {
 +    char* path = get_emulator_ecs_log_path();
 +    if (!path)
 +        return;
 +
 +#ifdef _WIN32
 +    FILE* fnul;
 +    FILE* flog;
 +
 +    fnul = fopen("NUL", "rt");
 +    if (fnul != NULL)
 +    stdin[0] = fnul[0];
 +
 +    flog = fopen(path, "wt+");
 +    if (flog == NULL)
 +    flog = fnul;
 +
 +    setvbuf(flog, NULL, _IONBF, 0);
 +
 +    stdout[0] = flog[0];
 +    stderr[0] = flog[0];
 +#else
 +    log_fd = open("/dev/null", O_RDONLY);
 +    dup2(log_fd, 0);
 +
 +    log_fd = creat(path, 0640);
 +    if (log_fd < 0) {
 +        log_fd = open("/dev/null", O_WRONLY);
 +    }
 +    dup2(log_fd, 1);
 +    dup2(log_fd, 2);
 +#endif
 +}
 +
 +static inline void stop_logging(void) {
 +    int ret = -1;
 +    if (log_fd >= 0) {
 +        ret = close(log_fd);
 +        if (ret != 0) {
 +            LOG("failed to close log fd.");
 +        }
 +    }
 +}
 +
 +int ecs_write(int fd, const uint8_t *buf, int len) {
 +    LOG("write buflen : %d, buf : %s", len, (char*)buf);
 +    if (fd < 0) {
 +        return -1;
 +    }
 +
 +    return send_all(fd, buf, len);
 +}
 +
 +void ecs_client_close(ECS_Client* clii) {
 +    if (clii == NULL)
 +        return;
 +
 +    pthread_mutex_lock(&mutex_clilist);
 +
 +    if (clii->client_fd > 0) {
 +        LOG("ecs client closed with fd: %d", clii->client_fd);
 +        closesocket(clii->client_fd);
 +#ifndef CONFIG_LINUX
 +        FD_CLR(clii->client_fd, &clii->cs->reads);
 +#endif
 +        clii->client_fd = -1;
 +    }
 +
 +    QTAILQ_REMOVE(&clients, clii, next);
 +
 +    g_free(clii);
 +    clii = NULL;
 +
 +    pthread_mutex_unlock(&mutex_clilist);
 +}
 +
 +bool send_to_all_client(const char* data, const int len) {
 +    LOG("data len: %d, data: %s", len, data);
 +    pthread_mutex_lock(&mutex_clilist);
 +
 +    ECS_Client *clii;
 +
 +    QTAILQ_FOREACH(clii, &clients, next)
 +    {
 +        send_to_client(clii->client_fd, data, len);
 +    }
 +    pthread_mutex_unlock(&mutex_clilist);
 +
 +    return true;
 +}
 +
 +void send_to_single_client(ECS_Client *clii, const char* data, const int len)
 +{
 +    pthread_mutex_lock(&mutex_clilist);
 +    send_to_client(clii->client_fd, data, len);
 +    pthread_mutex_unlock(&mutex_clilist);
 +}
 +
 +void send_to_client(int fd, const char* data, const int len)
 +{
 +    ecs_write(fd, (const uint8_t*) data, len);
 +}
 +
 +void read_val_short(const char* data, unsigned short* ret_val) {
 +    memcpy(ret_val, data, sizeof(unsigned short));
 +}
 +
 +void read_val_char(const char* data, unsigned char* ret_val) {
 +    memcpy(ret_val, data, sizeof(unsigned char));
 +}
 +
 +void read_val_str(const char* data, char* ret_val, int len) {
 +    memcpy(ret_val, data, len);
 +}
 +
 +bool ntf_to_control(const char* data, const int len) {
 +    return true;
 +}
 +
 +bool ntf_to_monitor(const char* data, const int len) {
 +    return true;
 +}
 +
 +void print_binary(const char* data, const int len) {
 +    int i;
 +    printf("[DATA: ");
 +    for(i = 0; i < len; i++) {
 +        if(i == len - 1) {
 +            printf("%02x]\n", data[i]);
 +        } else {
 +            printf("%02x,", data[i]);
 +        }
 +    }
 +}
 +
 +void ecs_make_header(QDict* obj, type_length length, type_group group,
 +        type_action action) {
 +    qdict_put(obj, "length", qint_from_int((int64_t )length));
 +    qdict_put(obj, "group", qint_from_int((int64_t )group));
 +    qdict_put(obj, "action", qint_from_int((int64_t )action));
 +}
 +
 +static Monitor *monitor_create(void) {
 +    Monitor *mon;
 +
 +    mon = g_malloc0(sizeof(*mon));
 +    if (NULL == mon) {
 +        LOG("monitor allocation failed.");
 +        return NULL;
 +    }
 +
 +    return mon;
 +}
 +
 +static void ecs_close(ECS_State *cs) {
 +    ECS_Client *clii;
 +    LOG("### Good bye! ECS ###");
 +
 +    if (cs == NULL)
 +        return;
 +
 +    if (0 <= cs->listen_fd) {
 +        LOG("close listen_fd: %d", cs->listen_fd);
 +        closesocket(cs->listen_fd);
 +        cs->listen_fd = -1;
 +    }
 +
 +    if (cs->mon != NULL) {
 +        g_free(cs->mon);
 +        cs->mon = NULL;
 +    }
 +
 +    if (keepalive_buf) {
 +        g_free(keepalive_buf);
 +    }
 +
 +    if (cs->alive_timer != NULL) {
-     qemu_mod_timer(current_ecs->alive_timer,
-             qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() * TIMER_ALIVE_S);
++        timer_del(cs->alive_timer);
 +        cs->alive_timer = NULL;
 +    }
 +
 +    QTAILQ_FOREACH(clii, &clients, next)
 +    {
 +        ecs_client_close(clii);
 +    }
 +
 +    g_free(cs);
 +    cs = NULL;
 +    current_ecs = NULL;
 +
 +    stop_logging();
 +}
 +
 +#ifndef _WIN32
 +static ssize_t ecs_recv(int fd, char *buf, size_t len) {
 +    struct msghdr msg = { NULL, };
 +    struct iovec iov[1];
 +    union {
 +        struct cmsghdr cmsg;
 +        char control[CMSG_SPACE(sizeof(int))];
 +    } msg_control;
 +    int flags = 0;
 +
 +    iov[0].iov_base = buf;
 +    iov[0].iov_len = len;
 +
 +    msg.msg_iov = iov;
 +    msg.msg_iovlen = 1;
 +    msg.msg_control = &msg_control;
 +    msg.msg_controllen = sizeof(msg_control);
 +
 +#ifdef MSG_CMSG_CLOEXEC
 +    flags |= MSG_CMSG_CLOEXEC;
 +#endif
 +    return recvmsg(fd, &msg, flags);
 +}
 +
 +#else
 +static ssize_t ecs_recv(int fd, char *buf, size_t len)
 +{
 +    return qemu_recv(fd, buf, len, 0);
 +}
 +#endif
 +
 +
 +static void reset_sbuf(sbuf* sbuf)
 +{
 +    memset(sbuf->_buf, 0, 4096);
 +    sbuf->_use = 0;
 +    sbuf->_netlen = 0;
 +}
 +
 +static void ecs_read(ECS_Client *cli) {
 +
 +    int read = 0;
 +    int to_read_bytes = 0;
 +
 +#ifndef __WIN32
 +    if (ioctl(cli->client_fd, FIONREAD, &to_read_bytes) < 0)
 +    {
 +        LOG("ioctl failed");
 +        return;
 +    }
 +#else
 +    unsigned long to_read_bytes_long = 0;
 +    if (ioctlsocket(cli->client_fd, FIONREAD, &to_read_bytes_long) < 0)
 +    {
 +        LOG("ioctl failed");
 +         return;
 +    }
 +     to_read_bytes = (int)to_read_bytes_long;
 +#endif
 +
 +    if (to_read_bytes == 0) {
 +        LOG("ioctl FIONREAD: 0");
 +        goto fail;
 +    }
 +
 +    if (cli->sbuf._netlen == 0)
 +    {
 +        if (to_read_bytes < 4)
 +        {
 +            //LOG("insufficient data size to read");
 +            return;
 +        }
 +
 +        long payloadsize = 0;
 +        read = ecs_recv(cli->client_fd, (char*) &payloadsize, 4);
 +
 +        if (read < 4)
 +        {
 +            LOG("insufficient header size");
 +            goto fail;
 +        }
 +
 +        payloadsize = ntohl(payloadsize);
 +
 +        cli->sbuf._netlen = payloadsize;
 +
 +        LOG("payload size: %ld\n", payloadsize);
 +
 +        to_read_bytes -= 4;
 +    }
 +
 +    if (to_read_bytes == 0)
 +        return;
 +
 +
 +    to_read_bytes = min(to_read_bytes, cli->sbuf._netlen - cli->sbuf._use);
 +
 +    read = ecs_recv(cli->client_fd, (char*)(cli->sbuf._buf + cli->sbuf._use), to_read_bytes);
 +    if (read == 0)
 +        goto fail;
 +
 +
 +    cli->sbuf._use += read;
 +
 +
 +    if (cli->sbuf._netlen == cli->sbuf._use)
 +    {
 +        handle_protobuf_msg(cli, (char*)cli->sbuf._buf, cli->sbuf._use);
 +        reset_sbuf(&cli->sbuf);
 +    }
 +
 +    return;
 +fail:
 +    ecs_client_close(cli);
 +}
 +
 +#ifdef CONFIG_LINUX
 +static void epoll_cli_add(ECS_State *cs, int fd) {
 +    struct epoll_event events;
 +
 +    /* event control set for read event */
 +    events.events = EPOLLIN;
 +    events.data.fd = fd;
 +
 +    if (epoll_ctl(cs->epoll_fd, EPOLL_CTL_ADD, fd, &events) < 0) {
 +        LOG("Epoll control fails.in epoll_cli_add.");
 +    }
 +}
 +#endif
 +
 +static ECS_Client *ecs_find_client(int fd) {
 +    ECS_Client *clii;
 +
 +    QTAILQ_FOREACH(clii, &clients, next)
 +    {
 +        if (clii->client_fd == fd)
 +            return clii;
 +    }
 +    return NULL;
 +}
 +
 +ECS_Client *find_client(unsigned char id, unsigned char type) {
 +    ECS_Client *clii;
 +
 +    QTAILQ_FOREACH(clii, &clients, next)
 +    {
 +        if (clii->client_id == id && clii->client_type == type)
 +            return clii;
 +    }
 +    return NULL;
 +}
 +
 +static int ecs_add_client(ECS_State *cs, int fd) {
 +
 +    ECS_Client *clii = g_malloc0(sizeof(ECS_Client));
 +    if (NULL == clii) {
 +        LOG("ECS_Client allocation failed.");
 +        return -1;
 +    }
 +
 +    reset_sbuf(&clii->sbuf);
 +
 +    qemu_set_nonblock(fd);
 +
 +    clii->client_fd = fd;
 +    clii->cs = cs;
 +    clii->client_type = TYPE_NONE;
 +
 +    ecs_json_message_parser_init(&clii->parser, handle_qmp_command, clii);
 +
 +#ifdef CONFIG_LINUX
 +    epoll_cli_add(cs, fd);
 +#else
 +    FD_SET(fd, &cs->reads);
 +#endif
 +
 +    pthread_mutex_lock(&mutex_clilist);
 +
 +    QTAILQ_INSERT_TAIL(&clients, clii, next);
 +
 +    LOG("Add an ecs client. fd: %d", fd);
 +
 +    pthread_mutex_unlock(&mutex_clilist);
 +
 +//    send_ecs_version_check(clii);
 +
 +    return 0;
 +}
 +
 +static void ecs_accept(ECS_State *cs) {
 +    struct sockaddr_in saddr;
 +#ifndef _WIN32
 +    struct sockaddr_un uaddr;
 +#endif
 +    struct sockaddr *addr;
 +    socklen_t len;
 +    int fd;
 +
 +    for (;;) {
 +#ifndef _WIN32
 +        if (cs->is_unix) {
 +            len = sizeof(uaddr);
 +            addr = (struct sockaddr *) &uaddr;
 +        } else
 +#endif
 +        {
 +            len = sizeof(saddr);
 +            addr = (struct sockaddr *) &saddr;
 +        }
 +        fd = qemu_accept(cs->listen_fd, addr, &len);
 +        if (0 > fd && EINTR != errno) {
 +            return;
 +        } else if (0 <= fd) {
 +            break;
 +        }
 +    }
 +    if (0 > ecs_add_client(cs, fd)) {
 +        LOG("failed to add client.");
 +    }
 +}
 +
 +#ifdef CONFIG_LINUX
 +static void epoll_init(ECS_State *cs) {
 +    struct epoll_event events;
 +
 +    cs->epoll_fd = epoll_create(MAX_EVENTS);
 +    if (cs->epoll_fd < 0) {
 +        closesocket(cs->listen_fd);
 +    }
 +
 +    events.events = EPOLLIN;
 +    events.data.fd = cs->listen_fd;
 +
 +    if (epoll_ctl(cs->epoll_fd, EPOLL_CTL_ADD, cs->listen_fd, &events) < 0) {
 +        close(cs->listen_fd);
 +        close(cs->epoll_fd);
 +    }
 +}
 +#endif
 +
 +static void send_keep_alive_msg(ECS_Client *clii) {
 +    send_to_single_client(clii, keepalive_buf, payloadsize);
 +}
 +
 +static void make_keep_alive_msg(void) {
 +    int len_pack = 0;
 +    char msg [5] = {'s','e','l','f'};
 +
 +    ECS__Master master = ECS__MASTER__INIT;
 +    ECS__KeepAliveReq req = ECS__KEEP_ALIVE_REQ__INIT;
 +
 +    req.time_str = (char*) g_malloc(5);
 +
 +    strncpy(req.time_str, msg, 4);
 +
 +    master.type = ECS__MASTER__TYPE__KEEPALIVE_REQ;
 +    master.keepalive_req = &req;
 +
 +    len_pack = ecs__master__get_packed_size(&master);
 +    payloadsize = len_pack + 4;
 +
 +    keepalive_buf = g_malloc(len_pack + 4);
 +    if (!keepalive_buf) {
 +        LOG("keep alive message creation is failed.");
 +        return;
 +    }
 +
 +    ecs__master__pack(&master, keepalive_buf + 4);
 +
 +    len_pack = htonl(len_pack);
 +    memcpy(keepalive_buf, &len_pack, 4);
 +}
 +
 +static void alive_checker(void *opaque) {
 +
 +    ECS_Client *clii;
 +
 +    if (NULL != current_ecs && !current_ecs->ecs_running) {
 +        return;
 +    }
 +
 +    QTAILQ_FOREACH(clii, &clients, next)
 +    {
 +        if (1 == clii->keep_alive) {
 +            LOG("get client fd %d - keep alive fail", clii->client_fd);
 +            ecs_client_close(clii);
 +            continue;
 +        }
 +        LOG("set client fd %d - keep alive 1", clii->client_fd);
 +        clii->keep_alive = 1;
 +        send_keep_alive_msg(clii);
 +    }
 +
 +    if (current_ecs == NULL) {
 +        LOG("alive checking is failed because current ecs is null.");
 +        return;
 +    }
 +
-     cs->alive_timer = qemu_new_timer_ns(vm_clock, alive_checker, cs);
++    timer_mod(current_ecs->alive_timer,
++            qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + get_ticks_per_sec() * TIMER_ALIVE_S);
 +
 +}
 +
 +static int socket_initialize(ECS_State *cs, QemuOpts *opts) {
 +    int fd = -1;
 +    Error *local_err = NULL;
 +
 +    fd = inet_listen_opts(opts, 0, &local_err);
 +    if (0 > fd || error_is_set(&local_err)) {
 +        qerror_report_err(local_err);
 +        error_free(local_err);
 +        return -1;
 +    }
 +
 +    LOG("Listen fd is %d", fd);
 +
 +    qemu_set_nonblock(fd);
 +
 +    cs->listen_fd = fd;
 +
 +#ifdef CONFIG_LINUX
 +    epoll_init(cs);
 +#else
 +    FD_ZERO(&cs->reads);
 +    FD_SET(fd, &cs->reads);
 +#endif
 +
 +    make_keep_alive_msg();
 +
-     qemu_mod_timer(cs->alive_timer,
-             qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() * TIMER_ALIVE_S);
++    cs->alive_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, alive_checker, cs);
 +
++    timer_mod(cs->alive_timer,
++            qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + get_ticks_per_sec() * TIMER_ALIVE_S);
 +
 +    return 0;
 +}
 +
 +#ifdef CONFIG_LINUX
 +static int ecs_loop(ECS_State *cs) {
 +    int i, nfds;
 +
 +    nfds = epoll_wait(cs->epoll_fd, cs->events, MAX_EVENTS, 100);
 +    if (0 == nfds) {
 +        return 0;
 +    }
 +
 +    if (0 > nfds) {
 +        if (errno == EINTR)
 +            return 0;
 +        perror("epoll wait error");
 +        return -1;
 +    }
 +
 +    for (i = 0; i < nfds; i++) {
 +        if (cs->events[i].data.fd == cs->listen_fd) {
 +            ecs_accept(cs);
 +            continue;
 +        }
 +        ecs_read(ecs_find_client(cs->events[i].data.fd));
 +    }
 +
 +    return 0;
 +}
 +#elif defined(CONFIG_WIN32)
 +static int ecs_loop(ECS_State *cs)
 +{
 +    int index = 0;
 +    TIMEVAL timeout;
 +    fd_set temps = cs->reads;
 +
 +    timeout.tv_sec = 5;
 +    timeout.tv_usec = 0;
 +
 +    if (select(0, &temps, 0, 0, &timeout) < 0) {
 +        LOG("select error.");
 +        return -1;
 +    }
 +
 +    for (index = 0; index < cs->reads.fd_count; index++) {
 +        if (FD_ISSET(cs->reads.fd_array[index], &temps)) {
 +            if (cs->reads.fd_array[index] == cs->listen_fd) {
 +                ecs_accept(cs);
 +                continue;
 +            }
 +
 +            ecs_read(ecs_find_client(cs->reads.fd_array[index]));
 +        }
 +    }
 +
 +    return 0;
 +}
 +#elif defined(CONFIG_DARWIN)
 +static int ecs_loop(ECS_State *cs)
 +{
 +    int index = 0;
 +    int res = 0;
 +    struct timeval timeout;
 +    fd_set temps = cs->reads;
 +
 +    timeout.tv_sec = 5;
 +    timeout.tv_usec = 0;
 +
 +    if ((res = select(MAX_FD_NUM + 1, &temps, NULL, NULL, &timeout)) < 0) {
 +        LOG("select failed..");
 +        return -1;
 +    }
 +
 +    for (index = 0; index < MAX_FD_NUM; index ++) {
 +        if (FD_ISSET(index, &temps)) {
 +            if (index == cs->listen_fd) {
 +                ecs_accept(cs);
 +                continue;
 +            }
 +
 +            ecs_read(ecs_find_client(index));
 +        }
 +    }
 +
 +    return 0;
 +}
 +
 +#endif
 +
 +int get_ecs_port(void) {
 +    if (port_setting < 0) {
 +        LOG("ecs port is not determined yet.");
 +        return 0;
 +    }
 +    LOG("requests ecs port, and port is %d", port);
 +    return port;
 +}
 +
 +static int set_ecs_port(int port) {
 +    FILE* fprop;
 +    char* path = get_emulator_ecs_prop_path();
 +    if (!path)
 +        return -1;
 +
 +    fprop = fopen(path, "wt+");
 +    if (fprop == NULL) {
 +        return -1;
 +    }
 +
 +    fprintf(fprop, "%d", port);
 +    fclose(fprop);
 +
 +    g_free(path);
 +
 +    return 0;
 +}
 +
 +static int setting_ecs_port(ECS_State *cs) {
 +    struct sockaddr server_addr;
 +    socklen_t server_len;
 +
 +    server_len = sizeof(server_addr);
 +    memset(&server_addr, 0, sizeof(server_addr));
 +    if (getsockname(cs->listen_fd, (struct sockaddr *) &server_addr, &server_len) < 0) {
 +        return -1;
 +    }
 +
 +    port = ntohs( ((struct sockaddr_in *) &server_addr)->sin_port );
 +    LOG("listen port is %d", port);
 +
 +    return set_ecs_port(port);
 +}
 +
 +static void* ecs_initialize(void* args) {
 +    int ret = 1;
 +    ECS_State *cs = NULL;
 +    QemuOpts *opts = NULL;
 +    Error *local_err = NULL;
 +    Monitor* mon = NULL;
 +    char host_port[16];
 +
 +    start_logging();
 +    LOG("ecs starts initializing.");
 +
 +    opts = qemu_opts_create(qemu_find_opts(ECS_OPTS_NAME), ECS_OPTS_NAME, 1, &local_err);
 +    if (error_is_set(&local_err)) {
 +        qerror_report_err(local_err);
 +        error_free(local_err);
 +        return NULL;
 +    }
 +
 +    qemu_opt_set(opts, "host", HOST_LISTEN_ADDR);
 +
 +    cs = g_malloc0(sizeof(ECS_State));
 +    if (NULL == cs) {
 +        LOG("ECS_State allocation failed.");
 +        return NULL;
 +    }
 +
 +    sprintf(host_port, "%d", port);
 +    qemu_opt_set(opts, "port", host_port);
 +    ret = socket_initialize(cs, opts);
 +    if (ret < 0) {
 +        LOG("Socket initialization is failed.");
 +        ecs_close(cs);
 +        return NULL;
 +    }
 +
 +    if (setting_ecs_port(cs) < 0) {
 +        LOG("Failed to get random port.");
 +        ecs_close(cs);
 +        return NULL;
 +    }
 +
 +    port_setting = 1;
 +
 +    mon = monitor_create();
 +    if (NULL == mon) {
 +        LOG("monitor initialization failed.");
 +        ecs_close(cs);
 +        return NULL;
 +    }
 +
 +    cs->mon = mon;
 +    current_ecs = cs;
 +    cs->ecs_running = 1;
 +
 +    LOG("ecs_loop entered.");
 +    while (cs->ecs_running) {
 +        ret = ecs_loop(cs);
 +        if (0 > ret) {
 +            ecs_close(cs);
 +            break;
 +        }
 +    }
 +    LOG("ecs_loop exited.");
 +
 +    return NULL;
 +}
 +
 +int stop_ecs(void) {
 +    LOG("ecs is closing.");
 +    if (NULL != current_ecs) {
 +        current_ecs->ecs_running = 0;
 +        ecs_close(current_ecs);
 +    }
 +
 +    pthread_mutex_destroy(&mutex_clilist);
 +
 +    return 0;
 +}
 +
 +int start_ecs(void) {
 +    pthread_t thread_id;
 +
 +    if (0 != pthread_create(&thread_id, NULL, ecs_initialize, NULL)) {
 +        LOG("pthread creation failed.");
 +        return -1;
 +    }
 +    return 0;
 +}
 +
 +bool handle_protobuf_msg(ECS_Client* cli, char* data, int len)
 +{
 +    ECS__Master* master = ecs__master__unpack(NULL, (size_t)len, (const uint8_t*)data);
 +    if (!master)
 +        return false;
 +
 +    if (master->type == ECS__MASTER__TYPE__INJECTOR_REQ)
 +    {
 +        ECS__InjectorReq* msg = master->injector_req;
 +        if (!msg)
 +            goto fail;
 +        msgproc_injector_req(cli, msg);
 +    }
 +    else if (master->type == ECS__MASTER__TYPE__MONITOR_REQ)
 +    {
 +        ECS__MonitorReq* msg = master->monitor_req;
 +        if (!msg)
 +            goto fail;
 +        msgproc_monitor_req(cli, msg);
 +    }
 +    else if (master->type == ECS__MASTER__TYPE__DEVICE_REQ)
 +    {
 +        cli->client_type = TYPE_ECP;
 +        ECS__DeviceReq* msg = master->device_req;
 +        if (!msg)
 +            goto fail;
 +        msgproc_device_req(cli, msg);
 +    }
 +    else if (master->type == ECS__MASTER__TYPE__NFC_REQ)
 +    {
 +        ECS__NfcReq* msg = master->nfc_req;
 +        if (!msg)
 +            goto fail;
 +
 +        pthread_mutex_lock(&mutex_clilist);
 +        if(cli->client_type == TYPE_NONE) {
 +            if (!strncmp(msg->category, MSG_TYPE_NFC, 3)) {
 +                QTAILQ_REMOVE(&clients, cli, next);
 +                cli->client_type = TYPE_ECP;
 +                if(g_client_id > 255) {
 +                    g_client_id = 1;
 +                }
 +                cli->client_id = g_client_id++;
 +
 +                QTAILQ_INSERT_TAIL(&clients, cli, next);
 +            }
 +            else if (!strncmp(msg->category, MSG_TYPE_SIMUL_NFC, 9)) {
 +                QTAILQ_REMOVE(&clients, cli, next);
 +                cli->client_type = TYPE_SIMUL_NFC;
 +                if(g_client_id > 255) {
 +                    g_client_id = 1;
 +                }
 +                cli->client_id = g_client_id++;
 +                QTAILQ_INSERT_TAIL(&clients, cli, next);
 +            }
 +            else {
 +                LOG("unsupported category is found: %s", msg->category);
 +                goto fail;
 +            }
 +        }
 +        pthread_mutex_unlock(&mutex_clilist);
 +
 +        msgproc_nfc_req(cli, msg);
 +    }
 +#if 0
 +    else if (master->type == ECS__MASTER__TYPE__CHECKVERSION_REQ)
 +    {
 +        ECS__CheckVersionReq* msg = master->checkversion_req;
 +        if (!msg)
 +            goto fail;
 +        msgproc_checkversion_req(cli, msg);
 +    }
 +#endif
 +    else if (master->type == ECS__MASTER__TYPE__KEEPALIVE_ANS)
 +    {
 +        ECS__KeepAliveAns* msg = master->keepalive_ans;
 +        if (!msg)
 +            goto fail;
 +        msgproc_keepalive_ans(cli, msg);
 +    }
 +    else if (master->type == ECS__MASTER__TYPE__TETHERING_REQ)
 +    {
 +        ECS__TetheringReq* msg = master->tethering_req;
 +        if (!msg)
 +            goto fail;
 +        msgproc_tethering_req(cli, msg);
 +    }
 +
 +    ecs__master__free_unpacked(master, NULL);
 +    return true;
 +fail:
 +    LOG("invalid message type");
 +    ecs__master__free_unpacked(master, NULL);
 +    return false;
 +} 
index e06ebbb,0000000..d0f8518
mode 100644,000000..100644
--- /dev/null
@@@ -1,359 -1,0 +1,164 @@@
- static bool has_pvpanic = true;
 +/*
 + * TIZEN base board
 + *
 + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
 + *
 + * Contact:
 + * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
 + * SeokYeon Hwang <syeon.hwang@samsung.com>
 + * SangJin Kim <sangjin3.kim@samsung.com>
 + * KiTae Kim <kt920.kim@samsung.com>
 + * JinHyung Jo <jinhyung.jo@samsung.com>
 + * SungMin Ha <sungmin82.ha@samsung.com>
 + * MunKyu Im <munkyu.im@samsung.com>
 + * JiHye Kim <jihye1128.kim@samsung.com>
 + * GiWoong Kim <giwoong.kim@samsung.com>
 + * DongKyun Yun
 + * DoHyung Hong
 + * Hyunjun Son
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + * x86 board from pc_piix.c...
 + * add some TIZEN-speciaized device...
 + */
 +
 +#include <glib.h>
 +
 +#include "hw/hw.h"
 +#include "hw/i386/pc.h"
 +#include "hw/i386/apic.h"
 +#include "hw/pci/pci.h"
 +#include "hw/pci/pci_ids.h"
 +#include "hw/usb.h"
 +#include "net/net.h"
 +#include "hw/boards.h"
 +#include "hw/ide.h"
 +#include "sysemu/kvm.h"
 +#include "hw/kvm/clock.h"
 +#include "sysemu/sysemu.h"
 +#include "hw/sysbus.h"
 +#include "hw/cpu/icc_bus.h"
 +#include "sysemu/arch_init.h"
 +#include "sysemu/blockdev.h"
 +#include "hw/i2c/smbus.h"
 +#include "hw/xen/xen.h"
 +#include "exec/memory.h"
 +#include "exec/address-spaces.h"
 +#include "hw/acpi/acpi.h"
 +#include "cpu.h"
 +#ifdef CONFIG_XEN
 +#  include <xen/hvm/hvm_info_table.h>
 +#endif
 +
 +#include "maru_common.h"
 +#include "guest_debug.h"
 +#include "maru_pm.h"
 +#include "maru_brightness.h"
 +#include "maru_overlay.h"
 +#if defined(__linux__)
 +#include <X11/Xlib.h>
 +#endif
 +#include "vigs/vigs_device.h"
 +extern int enable_yagl;
 +extern const char *yagl_backend;
 +extern int enable_vigs;
 +extern const char *vigs_backend;
 +extern int enable_spice;
 +
 +#define MAX_IDE_BUS 2
 +
 +int codec_init(PCIBus *bus);
 +int maru_brill_codec_pci_device_init(PCIBus *bus);
 +
 +static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
 +static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
 +static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
 +
- static void maru_x86_machine_init(MemoryRegion *system_memory,
-                      MemoryRegion *system_io,
-                      ram_addr_t ram_size,
-                      const char *boot_device,
-                      const char *kernel_filename,
-                      const char *kernel_cmdline,
-                      const char *initrd_filename,
-                      const char *cpu_model,
-                      int pci_enabled,
-                      int kvmclock_enabled)
 +static bool has_pci_info = true;
 +
 +MemoryRegion *global_ram_memory;
 +
 +MemoryRegion *get_ram_memory(void)
 +{
 +    return global_ram_memory;
 +}
 +
-     int i;
-     ram_addr_t below_4g_mem_size, above_4g_mem_size;
-     PCIBus *pci_bus;
-     ISABus *isa_bus;
-     PCII440FXState *i440fx_state;
-     int piix3_devfn = -1;
-     qemu_irq *cpu_irq;
-     qemu_irq *gsi;
-     qemu_irq *i8259;
-     qemu_irq *smi_irq;
-     GSIState *gsi_state;
-     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-     BusState *idebus[MAX_IDE_BUS];
-     ISADevice *rtc_state;
-     ISADevice *floppy;
-     MemoryRegion *ram_memory;
-     MemoryRegion *pci_memory;
-     MemoryRegion *rom_memory;
-     DeviceState *icc_bridge;
-     void *fw_cfg = NULL;
-     PcGuestInfo *guest_info;
++/* maru specialized device init */
++static void maru_device_init(void)
 +{
- #if defined(__linux__)
++    PCIBus *pci_bus = (PCIBus *) object_resolve_path_type("", TYPE_PCI_BUS, NULL);
 +
-     if (xen_enabled() && xen_hvm_init(&ram_memory) != 0) {
-         fprintf(stderr, "xen hardware virtual machine initialisation failed\n");
-         exit(1);
-     }
-     icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
-     object_property_add_child(qdev_get_machine(), "icc-bridge",
-                               OBJECT(icc_bridge), NULL);
-     pc_cpus_init(cpu_model, icc_bridge);
-     pc_acpi_init("acpi-dsdt.aml");
-     if (kvmclock_enabled) {
-         kvmclock_create();
-     }
-     if (ram_size >= QEMU_BELOW_4G_RAM_END ) {
-         above_4g_mem_size = ram_size - QEMU_BELOW_4G_RAM_END;
-         below_4g_mem_size = QEMU_BELOW_4G_RAM_END;
-     } else {
-         above_4g_mem_size = 0;
-         below_4g_mem_size = ram_size;
-     }
-     if (pci_enabled) {
-         pci_memory = g_new(MemoryRegion, 1);
-         memory_region_init(pci_memory, NULL, "pci", INT64_MAX);
-         rom_memory = pci_memory;
-     } else {
-         pci_memory = NULL;
-         rom_memory = system_memory;
-     }
-     guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
-     guest_info->has_pci_info = has_pci_info;
-     guest_info->isapc_ram_fw = !pci_enabled;
-     /* allocate ram and load rom/bios */
-     if (!xen_enabled()) {
-       // W/A for allocate larger continuous heap.
-         // see vl.c
-         if(preallocated_ptr != NULL) {
-             g_free(preallocated_ptr);
-         }
-       //
-         fw_cfg = pc_memory_init(system_memory,
-                        kernel_filename, kernel_cmdline, initrd_filename,
-                        below_4g_mem_size, above_4g_mem_size,
-                        rom_memory, &ram_memory, guest_info);
-     }
-     // for ramdump...
-     global_ram_memory = ram_memory;
-     gsi_state = g_malloc0(sizeof(*gsi_state));
-     if (kvm_irqchip_in_kernel()) {
-         kvm_pc_setup_irq_routing(pci_enabled);
-         gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
-                                  GSI_NUM_PINS);
-     } else {
-         gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
-     }
-     if (pci_enabled) {
-         pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi,
-                               system_memory, system_io, ram_size,
-                               below_4g_mem_size,
-                               0x100000000ULL - below_4g_mem_size,
-                               above_4g_mem_size,
-                               pci_memory, ram_memory);
-     } else {
-         pci_bus = NULL;
-         i440fx_state = NULL;
-         isa_bus = isa_bus_new(NULL, system_io);
-         no_hpet = 1;
-     }
-     isa_bus_irqs(isa_bus, gsi);
-     if (kvm_irqchip_in_kernel()) {
-         i8259 = kvm_i8259_init(isa_bus);
-     } else if (xen_enabled()) {
-         i8259 = xen_interrupt_controller_init();
-     } else {
-         cpu_irq = pc_allocate_cpu_irq();
-         i8259 = i8259_init(isa_bus, cpu_irq[0]);
-     }
-     for (i = 0; i < ISA_NUM_IRQS; i++) {
-         gsi_state->i8259_irq[i] = i8259[i];
-     }
-     if (pci_enabled) {
-         ioapic_init_gsi(gsi_state, "i440fx");
-     }
-     qdev_init_nofail(icc_bridge);
-     pc_register_ferr_irq(gsi[13]);
-     pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
-     if (xen_enabled()) {
-         pci_create_simple(pci_bus, -1, "xen-platform");
-     }
-     /* init basic PC hardware */
-     pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled());
-     pc_nic_init(isa_bus, pci_bus);
-     ide_drive_get(hd, MAX_IDE_BUS);
-     if (pci_enabled) {
-         PCIDevice *dev;
-         if (xen_enabled()) {
-             dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1);
-         } else {
-             dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
-         }
-         idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
-         idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
-     } else {
-         for(i = 0; i < MAX_IDE_BUS; i++) {
-             ISADevice *dev;
-             dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i],
-                                ide_irq[i],
-                                hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
-             idebus[i] = qdev_get_child_bus(DEVICE(dev), "ide.0");
-         }
-     }
-     pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
-                  floppy, idebus[0], idebus[1], rtc_state);
-     if (pci_enabled && usb_enabled(false)) {
-         pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci");
-     }
-     if (pci_enabled && acpi_enabled) {
-         i2c_bus *smbus;
-         smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
-         /* TODO: Populate SPD eeprom data.  */
-         smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
-                               gsi[9], *smi_irq,
-                               kvm_enabled(), fw_cfg);
-         smbus_eeprom_init(smbus, 8, NULL, 0);
-     }
-     if (pci_enabled) {
-         pc_pci_device_init(pci_bus);
-     }
-     if (has_pvpanic) {
-         pvpanic_init(isa_bus);
-     }
-     /* maru specialized device init */
-     if (pci_enabled) {
- //        codec_init(pci_bus);
-         pci_maru_overlay_init(pci_bus);
-         pci_maru_brightness_init(pci_bus);
-         maru_brill_codec_pci_device_init(pci_bus);
-     }
++#if defined(CONFIG_LINUX)
 +    Display *display = XOpenDisplay(0);
 +    if (!display && !enable_spice) {
 +        fprintf(stderr, "Cannot open X display\n");
 +        exit(1);
 +    }
 +#else
 +    void *display = NULL;
 +#endif
 +    struct winsys_interface *vigs_wsi = NULL;
 +
-     has_pci_info = false;
++    pci_maru_overlay_init(pci_bus);
++    pci_maru_brightness_init(pci_bus);
++    maru_brill_codec_pci_device_init(pci_bus);
 +
 +    if (enable_vigs) {
 +        PCIDevice *pci_dev = pci_create(pci_bus, -1, "vigs");
 +        qdev_prop_set_ptr(&pci_dev->qdev, "display", display);
 +        qdev_init_nofail(&pci_dev->qdev);
 +        vigs_wsi = DO_UPCAST(VIGSDevice, pci_dev, pci_dev)->wsi;
 +    }
 +
 +    if (enable_yagl) {
 +        PCIDevice *pci_dev = pci_create(pci_bus, -1, "yagl");
 +        qdev_prop_set_ptr(&pci_dev->qdev, "display", display);
 +        if (vigs_wsi &&
 +            (strcmp(yagl_backend, "vigs") == 0) &&
 +            (strcmp(vigs_backend, "gl") == 0)) {
 +            qdev_prop_set_ptr(&pci_dev->qdev, "winsys_gl_interface", vigs_wsi);
 +        }
 +        qdev_init_nofail(&pci_dev->qdev);
 +    }
 +}
 +
++extern void pc_init_pci(QEMUMachineInitArgs *args);
 +static void maru_x86_board_init(QEMUMachineInitArgs *args)
 +{
-     ram_addr_t ram_size = args->ram_size;
-     const char *cpu_model = args->cpu_model;
-     const char *kernel_filename = args->kernel_filename;
-     const char *kernel_cmdline = args->kernel_cmdline;
-     const char *initrd_filename = args->initrd_filename;
-     const char *boot_device = args->boot_device;
-     maru_x86_machine_init(get_system_memory(),
-              get_system_io(),
-              ram_size, boot_device,
-              kernel_filename, kernel_cmdline,
-              initrd_filename, cpu_model, 1, 1);
++    pc_init_pci(args);
 +
-     .max_cpus = 255,
-     DEFAULT_MACHINE_OPTIONS,
++    has_pci_info = false;
++    maru_device_init();
 +}
 +
 +static QEMUMachine maru_x86_machine = {
++    PC_DEFAULT_MACHINE_OPTIONS,
 +    .name = "maru-x86-machine",
 +    .alias = "maru-x86-machine",
 +    .desc = "Maru Board (x86)",
 +    .init = maru_x86_board_init,
 +    .hot_add_cpu = pc_hot_add_cpu,
 +};
 +
 +static void maru_machine_init(void)
 +{
 +    qemu_register_machine(&maru_x86_machine);
 +}
 +
 +machine_init(maru_machine_init);
index fad948f,0000000..702fefa
mode 100644,000000..100644
--- /dev/null
@@@ -1,1802 -1,0 +1,1802 @@@
-         qemu_irq_raise(s->dev.irq[0]);
 +/*
 + * Virtual Codec Device
 + *
 + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
 + *
 + * Contact:
 + *  Kitae Kim <kt920.kim@samsung.com>
 + *  SeokYeon Hwang <syeon.hwang@samsung.com>
 + *  YeongKyoon Lee <yeongkyoon.lee@samsung.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., 51 Franklin Street, Fifth Floor, Boston,
 + * MA 02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + */
 +
 +#include "maru_brill_codec.h"
 +
 +/* define debug channel */
 +MULTI_DEBUG_CHANNEL(qemu, brillcodec);
 +
 +// device
 +#define CODEC_DEVICE_NAME   "brilcodec"
 +#define CODEC_VERSION       1
 +
 +// device memory
 +#define CODEC_META_DATA_SIZE    (256)
 +
 +#define CODEC_MEM_SIZE          (32 * 1024 * 1024)
 +#define CODEC_REG_SIZE          (256)
 +
 +// libav
 +#define GEN_MASK(x) ((1 << (x)) - 1)
 +#define ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) & ~GEN_MASK(x))
 +#define ROUND_UP_2(x) ROUND_UP_X(x, 1)
 +#define ROUND_UP_4(x) ROUND_UP_X(x, 2)
 +#define ROUND_UP_8(x) ROUND_UP_X(x, 3)
 +#define DIV_ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) >> (x))
 +
 +#define DEFAULT_VIDEO_GOP_SIZE 15
 +
 +
 +// define a queue to manage ioparam, context data
 +typedef struct DeviceMemEntry {
 +    uint8_t *buf;
 +    uint32_t buf_size;
 +    uint32_t ctx_id;
 +
 +    QTAILQ_ENTRY(DeviceMemEntry) node;
 +} DeviceMemEntry;
 +
 +typedef struct CodecDataStg {
 +    CodecParam *param_buf;
 +    DeviceMemEntry *data_buf;
 +
 +    QTAILQ_ENTRY(CodecDataStg) node;
 +} CodecDataStg;
 +
 +// define two queue to store input and output buffers.
 +static QTAILQ_HEAD(codec_wq, DeviceMemEntry) codec_wq =
 +   QTAILQ_HEAD_INITIALIZER(codec_wq);
 +
 +static QTAILQ_HEAD(codec_rq, CodecDataStg) codec_rq =
 +   QTAILQ_HEAD_INITIALIZER(codec_rq);
 +
 +static DeviceMemEntry *entry[CODEC_CONTEXT_MAX];
 +
 +// pixel info
 +typedef struct PixFmtInfo {
 +    uint8_t x_chroma_shift;
 +    uint8_t y_chroma_shift;
 +} PixFmtInfo;
 +
 +static PixFmtInfo pix_fmt_info[PIX_FMT_NB];
 +
 +// thread
 +// static int idle_thread_cnt = 0;
 +#define DEFAULT_WORKER_THREAD_CNT 8
 +
 +static void *maru_brill_codec_threads(void *opaque);
 +
 +// static void maru_brill_codec_reset_parser_info(MaruBrillCodecState *s, int32_t ctx_index);
 +static int maru_brill_codec_query_list(MaruBrillCodecState *s);
 +static void maru_brill_codec_release_context(MaruBrillCodecState *s, int32_t value);
 +
 +// codec functions
 +static bool codec_init(MaruBrillCodecState *, int, void *);
 +static bool codec_deinit(MaruBrillCodecState *, int, void *);
 +static bool codec_decode_video(MaruBrillCodecState *, int, void *);
 +static bool codec_encode_video(MaruBrillCodecState *, int, void *);
 +static bool codec_decode_audio(MaruBrillCodecState *, int, void *);
 +static bool codec_encode_audio(MaruBrillCodecState *, int, void *);
 +static bool codec_picture_copy(MaruBrillCodecState *, int, void *);
 +static bool codec_flush_buffers(MaruBrillCodecState *, int, void *);
 +
 +typedef bool (*CodecFuncEntry)(MaruBrillCodecState *, int, void *);
 +static CodecFuncEntry codec_func_handler[] = {
 +    codec_init,
 +    codec_decode_video,
 +    codec_encode_video,
 +    codec_decode_audio,
 +    codec_encode_audio,
 +    codec_picture_copy,
 +    codec_deinit,
 +    codec_flush_buffers,
 +};
 +
 +static AVCodecParserContext *maru_brill_codec_parser_init(AVCodecContext *avctx);
 +#if 0
 +static int maru_brill_codec_parser_parse (AVCodecParserContext *pctx, AVCodecContext *avctx,
 +                            uint8_t *inbuf, int inbuf_size,
 +                            int64_t pts, int64_t dts, int64_t pos);
 +#endif
 +
 +static void maru_brill_codec_pop_writequeue(MaruBrillCodecState *s, uint32_t ctx_idx);
 +static void maru_brill_codec_push_readqueue(MaruBrillCodecState *s, CodecParam *ioparam);
 +static void maru_brill_codec_push_writequeue(MaruBrillCodecState *s, void* buf,
 +                                            uint32_t buf_size, int ctx_id);
 +
 +static void *maru_brill_codec_store_inbuf(uint8_t *mem_base_offset, CodecParam *ioparam);
 +
 +static void maru_brill_codec_reset(DeviceState *s);
 +
 +static void maru_brill_codec_get_cpu_cores(MaruBrillCodecState *s)
 +{
 +    s->worker_thread_cnt = get_number_of_processors();
 +    if (s->worker_thread_cnt < DEFAULT_WORKER_THREAD_CNT) {
 +        s->worker_thread_cnt = DEFAULT_WORKER_THREAD_CNT;
 +    }
 +
 +    TRACE("number of threads: %d\n", s->worker_thread_cnt);
 +}
 +
 +static void maru_brill_codec_threads_create(MaruBrillCodecState *s)
 +{
 +    int index;
 +    QemuThread *pthread = NULL;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    pthread = g_malloc(sizeof(QemuThread) * s->worker_thread_cnt);
 +    if (!pthread) {
 +        ERR("failed to allocate threadpool memory.\n");
 +        return;
 +    }
 +
 +    qemu_cond_init(&s->threadpool.cond);
 +    qemu_mutex_init(&s->threadpool.mutex);
 +
 +    s->is_thread_running = true;
 +    s->idle_thread_cnt = 0;
 +
 +    for (index = 0; index < s->worker_thread_cnt; index++) {
 +        qemu_thread_create(&pthread[index],
 +            maru_brill_codec_threads, (void *)s, QEMU_THREAD_JOINABLE);
 +    }
 +
 +    s->threadpool.threads = pthread;
 +
 +    TRACE("leave: %s\n", __func__);
 +}
 +
 +static void maru_brill_codec_thread_exit(MaruBrillCodecState *s)
 +{
 +    int index;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    /* stop to run dedicated threads. */
 +    s->is_thread_running = false;
 +
 +    for (index = 0; index < s->worker_thread_cnt; index++) {
 +        qemu_thread_join(&s->threadpool.threads[index]);
 +    }
 +
 +    TRACE("destroy mutex and conditional.\n");
 +    qemu_mutex_destroy(&s->threadpool.mutex);
 +    qemu_cond_destroy(&s->threadpool.cond);
 +
 +    if (s->threadpool.threads) {
 +        g_free(s->threadpool.threads);
 +        s->threadpool.threads = NULL;
 +    }
 +
 +    TRACE("leave: %s\n", __func__);
 +}
 +
 +static void maru_brill_codec_wakeup_threads(MaruBrillCodecState *s, int api_index)
 +{
 +    CodecParam *ioparam = NULL;
 +
 +    ioparam = g_malloc0(sizeof(CodecParam));
 +    if (!ioparam) {
 +        ERR("failed to allocate ioparam\n");
 +        return;
 +    }
 +
 +    memcpy(ioparam, &s->ioparam, sizeof(CodecParam));
 +
 +    TRACE("wakeup thread. ctx_id: %u, api_id: %u, mem_offset: 0x%x\n",
 +        ioparam->ctx_index, ioparam->api_index, ioparam->mem_offset);
 +
 +    maru_brill_codec_push_readqueue(s, ioparam);
 +
 +    qemu_mutex_lock(&s->context_mutex);
 +    // W/A for threads starvation.
 +    while (s->idle_thread_cnt == 0) {
 +        qemu_mutex_unlock(&s->context_mutex);
 +        TRACE("Worker threads are exhausted\n");
 +        usleep(2000); // wait 2ms.
 +        qemu_mutex_lock(&s->context_mutex);
 +    }
 +    qemu_cond_signal(&s->threadpool.cond);
 +    qemu_mutex_unlock(&s->context_mutex);
 +
 +    TRACE("after sending conditional signal\n");
 +}
 +
 +static void *maru_brill_codec_threads(void *opaque)
 +{
 +    MaruBrillCodecState *s = (MaruBrillCodecState *)opaque;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    while (s->is_thread_running) {
 +        int ctx_id, api_id;
 +        CodecDataStg *elem = NULL;
 +        DeviceMemEntry *indata_buf = NULL;
 +
 +        qemu_mutex_lock(&s->context_mutex);
 +        ++(s->idle_thread_cnt); // protected under mutex.
 +        qemu_cond_wait(&s->threadpool.cond, &s->context_mutex);
 +        --(s->idle_thread_cnt); // protected under mutex.
 +        qemu_mutex_unlock(&s->context_mutex);
 +
 +        qemu_mutex_lock(&s->ioparam_queue_mutex);
 +        elem = QTAILQ_FIRST(&codec_rq);
 +        if (elem) {
 +            QTAILQ_REMOVE(&codec_rq, elem, node);
 +            qemu_mutex_unlock(&s->ioparam_queue_mutex);
 +        } else {
 +            qemu_mutex_unlock(&s->ioparam_queue_mutex);
 +            continue;
 +        }
 +
 +        if (!elem->param_buf) {
 +            continue;
 +        }
 +
 +        api_id = elem->param_buf->api_index;
 +        ctx_id = elem->param_buf->ctx_index;
 +        indata_buf = elem->data_buf;
 +
 +        TRACE("api_id: %d ctx_id: %d\n", api_id, ctx_id);
 +
 +        if (!codec_func_handler[api_id](s, ctx_id, indata_buf)) {
 +            ERR("codec_func failure.\n");
 +            continue;
 +        }
 +
 +        TRACE("release a buffer of CodecParam\n");
 +        g_free(elem->param_buf);
 +
 +        if (elem->data_buf) {
 +
 +            if (elem->data_buf->buf) {
 +                TRACE("release inbuf\n");
 +                g_free(elem->data_buf->buf);
 +            }
 +
 +            TRACE("release a buffer indata_buf\n");
 +            g_free(elem->data_buf);
 +        }
 +
 +        TRACE("release an element of CodecDataStg\n");
 +        g_free(elem);
 +
 +        if (api_id == CODEC_DEINIT) {
 +            TRACE("deinit doesn't need to raise interrupt.\n");
 +        } else {
 +            TRACE("switch context to raise interrupt.\n");
 +            qemu_bh_schedule(s->codec_bh);
 +        }
 +    }
 +
 +    maru_brill_codec_thread_exit(s);
 +
 +    TRACE("leave: %s\n", __func__);
 +    return NULL;
 +}
 +
 +// queue
 +static void maru_brill_codec_push_readqueue(MaruBrillCodecState *s,
 +                                            CodecParam *ioparam)
 +{
 +    CodecDataStg *elem = NULL;
 +    DeviceMemEntry *data_buf = NULL;
 +
 +    elem = g_malloc0(sizeof(CodecDataStg));
 +    if (!elem) {
 +        ERR("failed to allocate ioparam_queue. %d\n", sizeof(CodecDataStg));
 +        return;
 +    }
 +
 +    elem->param_buf = ioparam;
 +
 +    switch(ioparam->api_index) {
 +    case CODEC_DECODE_VIDEO ... CODEC_ENCODE_AUDIO:
 +        data_buf = maru_brill_codec_store_inbuf((uint8_t *)s->vaddr, ioparam);
 +        break;
 +    default:
 +        TRACE("no buffer from guest\n");
 +        break;
 +    }
 +
 +    elem->data_buf = data_buf;
 +
 +    qemu_mutex_lock(&s->ioparam_queue_mutex);
 +    QTAILQ_INSERT_TAIL(&codec_rq, elem, node);
 +    qemu_mutex_unlock(&s->ioparam_queue_mutex);
 +}
 +
 +static void *maru_brill_codec_store_inbuf(uint8_t *mem_base_offset,
 +                                        CodecParam *ioparam)
 +{
 +    DeviceMemEntry *elem = NULL;
 +    int readbuf_size, size = 0;
 +    uint8_t *readbuf = NULL;
 +    uint8_t *device_mem = mem_base_offset + ioparam->mem_offset;
 +
 +    elem = g_malloc0(sizeof(DeviceMemEntry));
 +    if (!elem) {
 +        ERR("failed to allocate readqueue node. size: %d\n",
 +            sizeof(DeviceMemEntry));
 +        return NULL;
 +    }
 +
 +    memcpy(&readbuf_size, device_mem, sizeof(readbuf_size));
 +    size = sizeof(readbuf_size);
 +
 +    TRACE("readbuf size: %d\n", readbuf_size);
 +    if (readbuf_size <= 0) {
 +        TRACE("inbuf size is zero. api_id: %d, ctx_id: %d, mem_offset: %x\n",
 +            readbuf_size, ioparam->api_index, ioparam->ctx_index, ioparam->mem_offset);
 +    } else {
 +        readbuf = g_malloc0(readbuf_size);
 +        if (!readbuf) {
 +            ERR("failed to allocate a read buffer. size: %d\n", readbuf_size);
 +        } else {
 +            TRACE("copy input buffer from guest. ctx_id: %d, mem_offset: %x\n",
 +                ioparam->ctx_index, ioparam->mem_offset);
 +            memcpy(readbuf, device_mem + size, readbuf_size);
 +        }
 +    }
 +    memset(device_mem, 0x00, sizeof(readbuf_size));
 +
 +    elem->buf = readbuf;
 +    elem->buf_size = readbuf_size;
 +    elem->ctx_id = ioparam->ctx_index;
 +
 +    return elem;
 +}
 +
 +static void maru_brill_codec_push_writequeue(MaruBrillCodecState *s, void* buf,
 +                                            uint32_t buf_size, int ctx_id)
 +{
 +    DeviceMemEntry *elem = NULL;
 +    elem = g_malloc0(sizeof(DeviceMemEntry));
 +
 +    elem->buf = buf;
 +    elem->buf_size = buf_size;
 +    elem->ctx_id = ctx_id;
 +
 +    qemu_mutex_lock(&s->context_queue_mutex);
 +    QTAILQ_INSERT_TAIL(&codec_wq, elem, node);
 +    qemu_mutex_unlock(&s->context_queue_mutex);
 +}
 +
 +static void maru_brill_codec_pop_writequeue(MaruBrillCodecState *s, uint32_t ctx_idx)
 +{
 +    DeviceMemEntry *elem = NULL;
 +    uint32_t mem_offset = 0;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    if (ctx_idx < 1 || ctx_idx > (CODEC_CONTEXT_MAX - 1)) {
 +        ERR("invalid buffer index. %d\n", ctx_idx);
 +        return;
 +    }
 +
 +    TRACE("pop_writeqeue. context index: %d\n", ctx_idx);
 +    elem = entry[ctx_idx];
 +    if (elem) {
 +        mem_offset = s->ioparam.mem_offset;
 +
 +        // check corrupted mem_offset
 +        if (mem_offset < CODEC_MEM_SIZE) {
 +            if (elem->buf) {
 +                TRACE("write data %d to guest.  mem_offset: 0x%x\n",
 +                        elem->buf_size, mem_offset);
 +                memcpy(s->vaddr + mem_offset, elem->buf, elem->buf_size);
 +
 +                TRACE("release output buffer: %p\n", elem->buf);
 +                g_free(elem->buf);
 +            }
 +        } else {
 +            TRACE("mem_offset is corrupted!!\n");
 +        }
 +
 +        TRACE("pop_writequeue. release elem: %p\n", elem);
 +        g_free(elem);
 +
 +        entry[ctx_idx] = NULL;
 +    } else {
 +        TRACE("there is no buffer to copy data to guest\n");
 +    }
 +
 +    TRACE("leave: %s\n", __func__);
 +}
 +
 +static void serialize_video_data(const struct video_data *video,
 +                                AVCodecContext *avctx)
 +{
 +    if (video->width) {
 +        avctx->width = video->width;
 +    }
 +    if (video->height) {
 +        avctx->height = video->height;
 +    }
 +    if (video->fps_n) {
 +        avctx->time_base.num = video->fps_n;
 +    }
 +    if (video->fps_d) {
 +        avctx->time_base.den = video->fps_d;
 +    }
 +    if (video->pix_fmt > PIX_FMT_NONE) {
 +        avctx->pix_fmt = video->pix_fmt;
 +    }
 +    if (video->par_n) {
 +        avctx->sample_aspect_ratio.num = video->par_n;
 +    }
 +    if (video->par_d) {
 +        avctx->sample_aspect_ratio.den = video->par_d;
 +    }
 +    if (video->bpp) {
 +        avctx->bits_per_coded_sample = video->bpp;
 +    }
 +    if (video->ticks_per_frame) {
 +        avctx->ticks_per_frame = video->ticks_per_frame;
 +    }
 +}
 +
 +static void deserialize_video_data (const AVCodecContext *avctx,
 +                                    struct video_data *video)
 +{
 +    memset(video, 0x00, sizeof(struct video_data));
 +
 +    video->width = avctx->width;
 +    video->height = avctx->height;
 +    video->fps_n = avctx->time_base.num;
 +    video->fps_d = avctx->time_base.den;
 +    video->pix_fmt = avctx->pix_fmt;
 +    video->par_n = avctx->sample_aspect_ratio.num;
 +    video->par_d = avctx->sample_aspect_ratio.den;
 +    video->bpp = avctx->bits_per_coded_sample;
 +    video->ticks_per_frame = avctx->ticks_per_frame;
 +}
 +
 +static void serialize_audio_data (const struct audio_data *audio,
 +                                  AVCodecContext *avctx)
 +{
 +    if (audio->channels) {
 +        avctx->channels = audio->channels;
 +    }
 +    if (audio->sample_rate) {
 +        avctx->sample_rate = audio->sample_rate;
 +    }
 +    if (audio->block_align) {
 +        avctx->block_align = audio->block_align;
 +    }
 +
 +    if (audio->sample_fmt > AV_SAMPLE_FMT_NONE) {
 +        avctx->sample_fmt = audio->sample_fmt;
 +    }
 +}
 +
 +#if 0
 +static void maru_brill_codec_reset_parser_info(MaruBrillCodecState *s, int32_t ctx_index)
 +{
 +    s->context[ctx_index].parser_buf = NULL;
 +    s->context[ctx_index].parser_use = false;
 +}
 +#endif
 +
 +static void maru_brill_codec_release_context(MaruBrillCodecState *s, int32_t context_id)
 +{
 +    DeviceMemEntry *wq_elem = NULL, *wnext = NULL;
 +    CodecDataStg *rq_elem = NULL, *rnext = NULL;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    TRACE("release %d of context\n", context_id);
 +    codec_deinit(s, context_id, NULL);
 +    s->context[context_id].occupied = false;
 +
 +    // TODO: check if foreach statment needs lock or not.
 +    QTAILQ_FOREACH_SAFE(rq_elem, &codec_rq, node, rnext) {
 +        if (rq_elem && rq_elem->data_buf &&
 +            (rq_elem->data_buf->ctx_id == context_id)) {
 +
 +            TRACE("remove unused node from codec_rq. ctx_id: %d\n", context_id);
 +            qemu_mutex_lock(&s->context_queue_mutex);
 +            QTAILQ_REMOVE(&codec_rq, rq_elem, node);
 +            qemu_mutex_unlock(&s->context_queue_mutex);
 +            if (rq_elem && rq_elem->data_buf) {
 +                TRACE("release rq_buffer: %p\n", rq_elem->data_buf);
 +                g_free(rq_elem->data_buf);
 +            }
 +
 +            TRACE("release rq_elem: %p\n", rq_elem);
 +            g_free(rq_elem);
 +        } else {
 +            TRACE("no elem of %d context in the codec_rq.\n", context_id);
 +        }
 +    }
 +
 +    QTAILQ_FOREACH_SAFE(wq_elem, &codec_wq, node, wnext) {
 +        if (wq_elem && wq_elem->ctx_id == context_id) {
 +            TRACE("remove unused node from codec_wq. ctx_id: %d\n", context_id);
 +            qemu_mutex_lock(&s->context_queue_mutex);
 +            QTAILQ_REMOVE(&codec_wq, wq_elem, node);
 +            qemu_mutex_unlock(&s->context_queue_mutex);
 +
 +            if (wq_elem && wq_elem->buf) {
 +                TRACE("release wq_buffer: %p\n", wq_elem->buf);
 +                g_free(wq_elem->buf);
 +                wq_elem->buf = NULL;
 +            }
 +
 +            TRACE("release wq_elem: %p\n", wq_elem);
 +            g_free(wq_elem);
 +        } else {
 +            TRACE("no elem of %d context in the codec_wq.\n", context_id);
 +        }
 +    }
 +
 +    TRACE("leave: %s\n", __func__);
 +}
 +
 +
 +// initialize each pixel format.
 +static void maru_brill_codec_pixfmt_info_init(void)
 +{
 +    /* YUV formats */
 +    pix_fmt_info[PIX_FMT_YUV420P].x_chroma_shift = 1;
 +    pix_fmt_info[PIX_FMT_YUV420P].y_chroma_shift = 1;
 +
 +    pix_fmt_info[PIX_FMT_YUV422P].x_chroma_shift = 1;
 +    pix_fmt_info[PIX_FMT_YUV422P].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_YUV444P].x_chroma_shift = 0;
 +    pix_fmt_info[PIX_FMT_YUV444P].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_YUYV422].x_chroma_shift = 1;
 +    pix_fmt_info[PIX_FMT_YUYV422].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_YUV410P].x_chroma_shift = 2;
 +    pix_fmt_info[PIX_FMT_YUV410P].y_chroma_shift = 2;
 +
 +    pix_fmt_info[PIX_FMT_YUV411P].x_chroma_shift = 2;
 +    pix_fmt_info[PIX_FMT_YUV411P].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_YUVJ420P].x_chroma_shift = 1;
 +    pix_fmt_info[PIX_FMT_YUVJ420P].y_chroma_shift = 1;
 +
 +    pix_fmt_info[PIX_FMT_YUVJ422P].x_chroma_shift = 1;
 +    pix_fmt_info[PIX_FMT_YUVJ422P].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_YUVJ444P].x_chroma_shift = 0;
 +    pix_fmt_info[PIX_FMT_YUVJ444P].y_chroma_shift = 0;
 +
 +    /* RGB formats */
 +    pix_fmt_info[PIX_FMT_RGB24].x_chroma_shift = 0;
 +    pix_fmt_info[PIX_FMT_RGB24].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_BGR24].x_chroma_shift = 0;
 +    pix_fmt_info[PIX_FMT_BGR24].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_RGB32].x_chroma_shift = 0;
 +    pix_fmt_info[PIX_FMT_RGB32].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_RGB565].x_chroma_shift = 0;
 +    pix_fmt_info[PIX_FMT_RGB565].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_RGB555].x_chroma_shift = 0;
 +    pix_fmt_info[PIX_FMT_RGB555].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_YUVA420P].x_chroma_shift = 1;
 +    pix_fmt_info[PIX_FMT_YUVA420P].y_chroma_shift = 1;
 +}
 +
 +static int maru_brill_codec_get_picture_size(AVPicture *picture, uint8_t *ptr,
 +                                    int pix_fmt, int width,
 +                                    int height, bool encode)
 +{
 +    int size, w2, h2, size2;
 +    int stride, stride2;
 +    int fsize;
 +    PixFmtInfo *pinfo;
 +
 +    pinfo = &pix_fmt_info[pix_fmt];
 +
 +    switch (pix_fmt) {
 +    case PIX_FMT_YUV420P:
 +    case PIX_FMT_YUV422P:
 +    case PIX_FMT_YUV444P:
 +    case PIX_FMT_YUV410P:
 +    case PIX_FMT_YUV411P:
 +    case PIX_FMT_YUVJ420P:
 +    case PIX_FMT_YUVJ422P:
 +    case PIX_FMT_YUVJ444P:
 +        stride = ROUND_UP_4(width);
 +        h2 = ROUND_UP_X(height, pinfo->y_chroma_shift);
 +        size = stride * h2;
 +        w2 = DIV_ROUND_UP_X(width, pinfo->x_chroma_shift);
 +        stride2 = ROUND_UP_4(w2);
 +        h2 = DIV_ROUND_UP_X(height, pinfo->y_chroma_shift);
 +        size2 = stride2 * h2;
 +        fsize = size + 2 * size2;
 +        TRACE("stride: %d, stride2: %d, size: %d, size2: %d, fsize: %d\n",
 +            stride, stride2, size, size2, fsize);
 +
 +        if (!encode && !ptr) {
 +            TRACE("allocate a buffer for a decoded picture.\n");
 +            ptr = av_mallocz(fsize);
 +            if (!ptr) {
 +                ERR("[%d] failed to allocate memory.\n", __LINE__);
 +                return -1;
 +            }
 +        }
 +        picture->data[0] = ptr;
 +        picture->data[1] = picture->data[0] + size;
 +        picture->data[2] = picture->data[1] + size2;
 +        picture->data[3] = NULL;
 +        picture->linesize[0] = stride;
 +        picture->linesize[1] = stride2;
 +        picture->linesize[2] = stride2;
 +        picture->linesize[3] = 0;
 +        TRACE("planes %d %d %d\n", 0, size, size + size2);
 +        TRACE("strides %d %d %d\n", 0, stride, stride2, stride2);
 +        break;
 +    case PIX_FMT_YUVA420P:
 +        stride = ROUND_UP_4(width);
 +        h2 = ROUND_UP_X(height, pinfo->y_chroma_shift);
 +        size = stride * h2;
 +        w2 = DIV_ROUND_UP_X(width, pinfo->x_chroma_shift);
 +        stride2 = ROUND_UP_4(w2);
 +        h2 = DIV_ROUND_UP_X(height, pinfo->y_chroma_shift);
 +        size2 = stride2 * h2;
 +        fsize = 2 * size + 2 * size2;
 +        if (!encode && !ptr) {
 +            TRACE("allocate a buffer for a decoded picture.\n");
 +            ptr = av_mallocz(fsize);
 +            if (!ptr) {
 +                ERR("[%d] failed to allocate memory.\n", __LINE__);
 +                return -1;
 +            }
 +        }
 +        picture->data[0] = ptr;
 +        picture->data[1] = picture->data[0] + size;
 +        picture->data[2] = picture->data[1] + size2;
 +        picture->data[3] = picture->data[2] + size2;
 +        picture->linesize[0] = stride;
 +        picture->linesize[1] = stride2;
 +        picture->linesize[2] = stride2;
 +        picture->linesize[3] = stride;
 +        TRACE("planes %d %d %d\n", 0, size, size + size2);
 +        TRACE("strides %d %d %d\n", 0, stride, stride2, stride2);
 +        break;
 +    case PIX_FMT_RGB24:
 +    case PIX_FMT_BGR24:
 +        stride = ROUND_UP_4 (width * 3);
 +        fsize = stride * height;
 +        TRACE("stride: %d, size: %d\n", stride, fsize);
 +
 +        if (!encode && !ptr) {
 +            TRACE("allocate a buffer for a decoded picture.\n");
 +            ptr = av_mallocz(fsize);
 +            if (!ptr) {
 +                ERR("[%d] failed to allocate memory.\n", __LINE__);
 +                return -1;
 +            }
 +        }
 +        picture->data[0] = ptr;
 +        picture->data[1] = NULL;
 +        picture->data[2] = NULL;
 +        picture->data[3] = NULL;
 +        picture->linesize[0] = stride;
 +        picture->linesize[1] = 0;
 +        picture->linesize[2] = 0;
 +        picture->linesize[3] = 0;
 +        break;
 +    case PIX_FMT_RGB32:
 +        stride = width * 4;
 +        fsize = stride * height;
 +        TRACE("stride: %d, size: %d\n", stride, fsize);
 +
 +        if (!encode && !ptr) {
 +            TRACE("allocate a buffer for a decoded picture.\n");
 +            ptr = av_mallocz(fsize);
 +            if (!ptr) {
 +                ERR("[%d] failed to allocate memory.\n", __LINE__);
 +                return -1;
 +            }
 +        }
 +        picture->data[0] = ptr;
 +        picture->data[1] = NULL;
 +        picture->data[2] = NULL;
 +        picture->data[3] = NULL;
 +        picture->linesize[0] = stride;
 +        picture->linesize[1] = 0;
 +        picture->linesize[2] = 0;
 +        picture->linesize[3] = 0;
 +        break;
 +    case PIX_FMT_RGB555:
 +    case PIX_FMT_RGB565:
 +        stride = ROUND_UP_4 (width * 2);
 +        fsize = stride * height;
 +        TRACE("stride: %d, size: %d\n", stride, fsize);
 +
 +        if (!encode && !ptr) {
 +            TRACE("allocate a buffer for a decoded picture.\n");
 +            ptr = av_mallocz(fsize);
 +            if (!ptr) {
 +                ERR("[%d] failed to allocate memory.\n", __LINE__);
 +                return -1;
 +            }
 +        }
 +        picture->data[0] = ptr;
 +        picture->data[1] = NULL;
 +        picture->data[2] = NULL;
 +        picture->data[3] = NULL;
 +        picture->linesize[0] = stride;
 +        picture->linesize[1] = 0;
 +        picture->linesize[2] = 0;
 +        picture->linesize[3] = 0;
 +        break;
 +    case PIX_FMT_PAL8:
 +        stride = ROUND_UP_4(width);
 +        size = stride * height;
 +        fsize = size + 256 * 4;
 +        TRACE("stride: %d, size: %d\n", stride, fsize);
 +
 +        if (!encode && !ptr) {
 +            TRACE("allocate a buffer for a decoded picture.\n");
 +            ptr = av_mallocz(fsize);
 +            if (!ptr) {
 +                ERR("[%d] failed to allocate memory.\n", __LINE__);
 +                return -1;
 +            }
 +        }
 +        picture->data[0] = ptr;
 +        picture->data[1] = ptr + size;
 +        picture->data[2] = NULL;
 +        picture->data[3] = NULL;
 +        picture->linesize[0] = stride;
 +        picture->linesize[1] = 4;
 +        picture->linesize[2] = 0;
 +        picture->linesize[3] = 0;
 +        break;
 +    default:
 +        picture->data[0] = NULL;
 +        picture->data[1] = NULL;
 +        picture->data[2] = NULL;
 +        picture->data[3] = NULL;
 +        fsize = -1;
 +        ERR("pixel format: %d was wrong.\n", pix_fmt);
 +        break;
 +    }
 +
 +    return fsize;
 +}
 +
 +static int maru_brill_codec_query_list (MaruBrillCodecState *s)
 +{
 +    AVCodec *codec = NULL;
 +    uint32_t size = 0, mem_size = 0;
 +    uint32_t data_len = 0, length = 0;
 +    int32_t codec_type, media_type;
 +    int32_t codec_fmts[4], i;
 +
 +    /* register avcodec */
 +    TRACE("register avcodec\n");
 +    av_register_all();
 +
 +    codec = av_codec_next(NULL);
 +    if (!codec) {
 +        ERR("failed to get codec info.\n");
 +        return -1;
 +    }
 +
 +    // a region to store the number of codecs.
 +    length = 32 + 64 + 6 * sizeof(int32_t);
 +    mem_size = size = sizeof(uint32_t);
 +
 +    while (codec) {
 +        codec_type =
 +            codec->decode ? CODEC_TYPE_DECODE : CODEC_TYPE_ENCODE;
 +        media_type = codec->type;
 +
 +        memset(codec_fmts, -1, sizeof(codec_fmts));
 +        if (media_type == AVMEDIA_TYPE_VIDEO) {
 +            if (codec->pix_fmts) {
 +                for (i = 0; codec->pix_fmts[i] != -1; i++) {
 +                    codec_fmts[i] = codec->pix_fmts[i];
 +                }
 +            }
 +        } else if (media_type == AVMEDIA_TYPE_AUDIO) {
 +            if (codec->sample_fmts) {
 +                for (i = 0; codec->sample_fmts[i] != -1; i++) {
 +                    codec_fmts[i] = codec->sample_fmts[i];
 +                }
 +            }
 +        } else {
 +            ERR("%s of media type is unknown.\n", codec->name);
 +        }
 +
 +        memset(s->vaddr + mem_size, 0x00, length);
 +        mem_size += length;
 +
 +        data_len += length;
 +        memcpy(s->vaddr, &data_len, sizeof(data_len));
 +
 +        memcpy(s->vaddr + size, &codec_type, sizeof(codec_type));
 +        size += sizeof(codec_type);
 +        memcpy(s->vaddr + size, &media_type, sizeof(media_type));
 +        size += sizeof(media_type);
 +        memcpy(s->vaddr + size, codec->name, strlen(codec->name));
 +        size += 32;
 +        memcpy(s->vaddr + size,
 +           codec->long_name, strlen(codec->long_name));
 +        size += 64;
 +        memcpy(s->vaddr + size, codec_fmts, sizeof(codec_fmts));
 +        size += sizeof(codec_fmts);
 +
 +        codec = av_codec_next(codec);
 +    }
 +
 +    return 0;
 +}
 +
 +static int maru_brill_codec_get_context_index(MaruBrillCodecState *s)
 +{
 +    int index;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    for (index = 1; index < CODEC_CONTEXT_MAX; index++) {
 +        if (s->context[index].occupied == false) {
 +            TRACE("get %d of codec context successfully.\n", index);
 +            s->context[index].occupied = true;
 +            break;
 +        }
 +    }
 +
 +    if (index == CODEC_CONTEXT_MAX) {
 +        ERR("failed to get available codec context. ");
 +        ERR("try to run codec again.\n");
 +        index = -1;
 +    }
 +
 +    TRACE("leave: %s\n", __func__);
 +
 +    return index;
 +}
 +
 +// allocate avcontext and avframe struct.
 +static AVCodecContext *maru_brill_codec_alloc_context(MaruBrillCodecState *s, int index)
 +{
 +    TRACE("enter: %s\n", __func__);
 +
 +    TRACE("allocate %d of context and frame.\n", index);
 +    s->context[index].avctx = avcodec_alloc_context();
 +    s->context[index].frame = avcodec_alloc_frame();
 +    s->context[index].opened = false;
 +
 +    s->context[index].parser_buf = NULL;
 +    s->context[index].parser_use = false;
 +
 +    TRACE("leave: %s\n", __func__);
 +
 +    return s->context[index].avctx;
 +}
 +
 +static AVCodec *maru_brill_codec_find_avcodec(uint8_t *mem_buf)
 +{
 +    AVCodec *codec = NULL;
 +    int32_t encode, size = 0;
 +    char codec_name[32] = {0, };
 +
 +    memcpy(&encode, mem_buf, sizeof(encode));
 +    size = sizeof(encode);
 +    memcpy(codec_name, mem_buf + size, sizeof(codec_name));
 +    size += sizeof(codec_name);
 +
 +    TRACE("type: %d, name: %s\n", encode, codec_name);
 +
 +    if (encode) {
 +        codec = avcodec_find_encoder_by_name (codec_name);
 +    } else {
 +        codec = avcodec_find_decoder_by_name (codec_name);
 +    }
 +    INFO("%s!! find %s %s\n",
 +        codec ? "success" : "failure",
 +        codec_name, encode ? "encoder" : "decoder");
 +
 +    return codec;
 +}
 +
 +static void read_codec_init_data(AVCodecContext *avctx, uint8_t *mem_buf)
 +{
 +    struct video_data video = { 0, };
 +    struct audio_data audio = { 0, };
 +    int bitrate = 0, size = 0;
 +
 +    memcpy(&video, mem_buf + size, sizeof(video));
 +    size = sizeof(video);
 +    serialize_video_data(&video, avctx);
 +
 +    memcpy(&audio, mem_buf + size, sizeof(int32_t) * 6);
 +    size += sizeof(int32_t) * 6;
 +    memcpy(&audio.bits_per_smp_fmt, mem_buf + size, sizeof(int32_t));
 +    size += sizeof(int32_t);
 +    memcpy(&audio.channel_layout, mem_buf + size, sizeof(int64_t));
 +    size += sizeof(int64_t);
 +    serialize_audio_data(&audio, avctx);
 +
 +    memcpy(&bitrate, mem_buf + size, sizeof(bitrate));
 +    size += sizeof(bitrate);
 +    if (bitrate) {
 +        avctx->bit_rate = bitrate;
 +    }
 +    memcpy(&avctx->codec_tag, mem_buf + size, sizeof(avctx->codec_tag));
 +    size += sizeof(avctx->codec_tag);
 +    memcpy(&avctx->extradata_size,
 +            mem_buf + size, sizeof(avctx->extradata_size));
 +    size += sizeof(avctx->extradata_size);
 +    if (avctx->extradata_size > 0) {
 +        TRACE("extradata size: %d.\n", avctx->extradata_size);
 +        avctx->extradata =
 +            av_mallocz(ROUND_UP_X(avctx->extradata_size +
 +                        FF_INPUT_BUFFER_PADDING_SIZE, 4));
 +        if (avctx->extradata) {
 +            memcpy(avctx->extradata, mem_buf + size, avctx->extradata_size);
 +        }
 +    } else {
 +        TRACE("no extra data.\n");
 +        avctx->extradata =
 +            av_mallocz(ROUND_UP_X(FF_INPUT_BUFFER_PADDING_SIZE, 4));
 +    }
 +}
 +
 +// write the result of codec_init
 +static void write_codec_init_data(AVCodecContext *avctx, uint8_t *mem_buf)
 +{
 +    int size = 0;
 +
 +    if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) {
 +        int osize = 0;
 +
 +        TRACE("codec_init. audio sample_fmt: %d\n", avctx->sample_fmt);
 +
 +        memcpy(mem_buf, &avctx->sample_fmt, sizeof(avctx->sample_fmt));
 +        size = sizeof(avctx->sample_fmt);
 +        memcpy(mem_buf + size,
 +                &avctx->frame_size, sizeof(avctx->frame_size));
 +        size += sizeof(avctx->frame_size);
 +        osize = av_get_bits_per_sample(avctx->codec->id) / 8;
 +        memcpy(mem_buf + size, &osize, sizeof(osize));
 +    }
 +}
 +
 +// write the result of codec_decode_video
 +static void write_codec_decode_video_data(AVCodecContext *avctx, int len,
 +                                        int got_pic_ptr, uint8_t *mem_buf)
 +{
 +    struct video_data video;
 +    int size = 0;
 +
 +    memcpy(mem_buf, &len, sizeof(len));
 +    size = sizeof(len);
 +    memcpy(mem_buf + size, &got_pic_ptr, sizeof(got_pic_ptr));
 +    size += sizeof(got_pic_ptr);
 +    if (avctx) {
 +        deserialize_video_data(avctx, &video);
 +        memcpy(mem_buf + size, &video, sizeof(struct video_data));
 +    }
 +}
 +
 +// write the result of codec_decode_audio
 +static void write_codec_decode_audio_data(int sample_rate, int channel,
 +                                        int64_t channel_layout, int len,
 +                                        int frame_size_ptr, uint8_t *mem_buf)
 +{
 +    int size = 0;
 +
 +    TRACE("copy decode_audio. len %d, frame_size %d\n", len, frame_size_ptr);
 +
 +    memcpy(mem_buf, &sample_rate, sizeof(sample_rate));
 +    size = sizeof(sample_rate);
 +    memcpy(mem_buf + size, &channel, sizeof(channel));
 +    size += sizeof(channel);
 +    memcpy(mem_buf + size, &channel_layout, sizeof(channel_layout));
 +    size += sizeof(channel_layout);
 +    memcpy(mem_buf + size, &len, sizeof(len));
 +    size += sizeof(len);
 +    memcpy(mem_buf + size, &frame_size_ptr, sizeof(frame_size_ptr));
 +}
 +
 +// codec functions
 +static bool codec_init(MaruBrillCodecState *s, int ctx_id, void *elem)
 +{
 +    AVCodecContext *avctx = NULL;
 +    AVCodec *codec = NULL;
 +    int size = 0, ret = -1;
 +    uint8_t *meta_buf = NULL;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    // assign meta_buf
 +    meta_buf = s->vaddr + ((ctx_id - 1) * CODEC_META_DATA_SIZE);
 +    meta_buf += 8; // skipped header.
 +
 +    // allocate AVCodecContext
 +    avctx = maru_brill_codec_alloc_context(s, ctx_id);
 +    if (!avctx) {
 +        ERR("[%d] failed to allocate context.\n", __LINE__);
 +        ret = -1;
 +    } else {
 +        codec = maru_brill_codec_find_avcodec(meta_buf);
 +        if (codec) {
 +            size = sizeof(int32_t) + 32; // buffer size of codec_name
 +            read_codec_init_data(avctx, meta_buf + size);
 +
 +            ret = avcodec_open(avctx, codec);
 +            INFO("avcodec_open done. ctx_id: %d\n", ctx_id);
 +
 +            s->context[ctx_id].opened = true;
 +            s->context[ctx_id].parser_ctx =
 +                maru_brill_codec_parser_init(avctx);
 +        } else {
 +            ERR("failed to find codec. ctx_id: %d\n", ctx_id);
 +        }
 +    }
 +
 +    // return the result of avcodec_open
 +    memcpy(meta_buf, &ret, sizeof(ret));
 +    size = sizeof(ret);
 +    if (ret < 0) {
 +        ERR("failed to open codec contex.\n");
 +    } else {
 +        write_codec_init_data(avctx, meta_buf + size);
 +    }
 +
 +    maru_brill_codec_push_writequeue(s, NULL, 0, ctx_id);
 +
 +    TRACE("leave: %s\n", __func__);
 +
 +    return true;
 +}
 +
 +static bool codec_deinit(MaruBrillCodecState *s, int ctx_id, void *data_buf)
 +{
 +    AVCodecContext *avctx = NULL;
 +    AVFrame *frame = NULL;
 +    AVCodecParserContext *parserctx = NULL;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    avctx = s->context[ctx_id].avctx;
 +    frame = s->context[ctx_id].frame;
 +    parserctx = s->context[ctx_id].parser_ctx;
 +    if (!avctx || !frame) {
 +        TRACE("%d of AVCodecContext or AVFrame is NULL. "
 +            " Those resources have been released before.\n", ctx_id);
 +        return false;
 +    } else {
 +        qemu_mutex_lock(&s->threadpool.mutex);
 +        if (!s->context[ctx_id].opened) {
 +            TRACE("%d of context has already been closed\n", ctx_id);
 +            qemu_mutex_unlock(&s->threadpool.mutex);
 +            return false;
 +        }
 +        avcodec_close(avctx);
 +        INFO("close avcontext of %d\n", ctx_id);
 +        s->context[ctx_id].opened = false;
 +        qemu_mutex_unlock(&s->threadpool.mutex);
 +
 +        if (avctx->extradata) {
 +            TRACE("free context extradata\n");
 +            av_free(avctx->extradata);
 +            s->context[ctx_id].avctx->extradata = NULL;
 +        }
 +
 +        if (avctx->palctrl) {
 +            TRACE("free context palctrl \n");
 +            av_free(avctx->palctrl);
 +            s->context[ctx_id].avctx->palctrl = NULL;
 +        }
 +
 +        if (frame) {
 +            TRACE("free frame\n");
 +            av_free(frame);
 +            s->context[ctx_id].frame = NULL;
 +        }
 +
 +        if (avctx) {
 +            TRACE("free codec context\n");
 +            av_free(avctx);
 +            s->context[ctx_id].avctx = NULL;
 +        }
 +
 +        if (parserctx) {
 +            av_parser_close(parserctx);
 +            s->context[ctx_id].parser_ctx = NULL;
 +        }
 +    }
 +
 +    TRACE("leave: %s\n", __func__);
 +
 +    return true;
 +}
 +
 +//
 +static bool codec_flush_buffers(MaruBrillCodecState *s, int ctx_id, void *data_buf)
 +{
 +    AVCodecContext *avctx = NULL;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    avctx = s->context[ctx_id].avctx;
 +    if (!avctx) {
 +        ERR("%d of AVCodecContext is NULL.\n", ctx_id);
 +        return false;
 +    } else {
 +        avcodec_flush_buffers(avctx);
 +        TRACE("flush %d context of buffers.\n", ctx_id);
 +    }
 +
 +    TRACE("leave: %s\n", __func__);
 +
 +    return true;
 +}
 +
 +static bool codec_decode_video(MaruBrillCodecState *s, int ctx_id, void *data_buf)
 +{
 +    AVCodecContext *avctx = NULL;
 +    AVFrame *picture = NULL;
 +    AVPacket avpkt;
 +    int got_pic_ptr = 0, len = 0;
 +    uint8_t *inbuf = NULL;
 +    int inbuf_size, idx, size = 0;
 +    int64_t in_offset;
 +
 +    DeviceMemEntry *elem = NULL;
 +    uint8_t *meta_buf = NULL;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    meta_buf = s->vaddr + ((ctx_id - 1) * CODEC_META_DATA_SIZE);
 +    meta_buf += 8; // skipped header.
 +
 +    memcpy(&inbuf_size, meta_buf, sizeof(inbuf_size));
 +    size = sizeof(inbuf_size);
 +    memcpy(&idx, meta_buf + size, sizeof(idx));
 +    size += sizeof(idx);
 +    memcpy(&in_offset, meta_buf + size, sizeof(in_offset));
 +    size += sizeof(in_offset);
 +    TRACE("decode_video. input buffer size: %d\n", inbuf_size);
 +
 +    elem = (DeviceMemEntry *)data_buf;
 +    if (elem && elem->buf) {
 +        inbuf = elem->buf;
 +    } else if (elem) {
 +        inbuf_size = 0;
 +        TRACE("decode_video. no input buffer. ctx_id: %d, %p, %d\n",
 +            ctx_id, inbuf, elem->buf_size);
 +    } else {
 +        ERR("wrong input data\n");
 +        return false;
 +    }
 +
 +    av_init_packet(&avpkt);
 +    avpkt.data = inbuf;
 +    avpkt.size = inbuf_size;
 +
 +    avctx = s->context[ctx_id].avctx;
 +    picture = s->context[ctx_id].frame;
 +    if (!avctx || !picture) {
 +        ERR("%d of AVCodecContext or AVFrame is NULL.\n", ctx_id);
 +        len = -1;
 +    } else if (!avctx->codec) {
 +        ERR("%d of AVCodec is NULL.\n", ctx_id);
 +        len = -1;
 +    } else {
 +        // in case of skipping frames
 +        picture->pict_type = -1;
 +
 +        len = avcodec_decode_video2(avctx, picture, &got_pic_ptr, &avpkt);
 +        if (len < 0) {
 +            ERR("failed to decode video. ctx index: %d\n", ctx_id);
 +        }
 +    }
 +
 +    TRACE("after decoding video. len: %d, have_data: %d\n",
 +        len, got_pic_ptr);
 +
 +    write_codec_decode_video_data(avctx, len, got_pic_ptr, meta_buf);
 +    maru_brill_codec_push_writequeue(s, NULL, 0, ctx_id);
 +
 +    TRACE("leave: %s\n", __func__);
 +
 +    return true;
 +}
 +
 +static bool codec_picture_copy (MaruBrillCodecState *s, int ctx_id, void *elem)
 +{
 +    AVCodecContext *avctx;
 +    AVPicture *src;
 +    AVPicture dst;
 +    uint8_t *out_buffer = NULL, *tempbuf = NULL;
 +    int pict_size = 0;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    TRACE("copy decoded image of %d context.\n", ctx_id);
 +
 +    avctx = s->context[ctx_id].avctx;
 +    src = (AVPicture *)s->context[ctx_id].frame;
 +    if (!avctx || !src) {
 +        ERR("%d of AVCodecContext or AVFrame is NULL.\n", ctx_id);
 +    } else if (!avctx->codec) {
 +        ERR("%d of AVCodec is NULL.\n", ctx_id);
 +    } else {
 +        TRACE("decoded image. pix_fmt: %d width: %d, height: %d\n",
 +                avctx->pix_fmt, avctx->width, avctx->height);
 +
 +        pict_size =
 +            maru_brill_codec_get_picture_size(&dst, NULL, avctx->pix_fmt,
 +                    avctx->width, avctx->height, false);
 +        if ((pict_size) < 0) {
 +            ERR("picture size: %d\n", pict_size);
 +        } else {
 +            TRACE("picture size: %d\n", pict_size);
 +            av_picture_copy(&dst, src, avctx->pix_fmt,
 +                            avctx->width, avctx->height);
 +
 +            tempbuf = g_malloc0(pict_size);
 +            if (!tempbuf) {
 +                ERR("failed to allocate a picture buffer. size: %d\n", pict_size);
 +            } else {
 +                out_buffer = dst.data[0];
 +                memcpy(tempbuf, out_buffer, pict_size);
 +            }
 +            av_free(out_buffer);
 +        }
 +    }
 +    maru_brill_codec_push_writequeue(s, tempbuf, pict_size, ctx_id);
 +
 +    TRACE("leave: %s\n", __func__);
 +
 +    return true;
 +}
 +
 +static bool codec_decode_audio(MaruBrillCodecState *s, int ctx_id, void *data_buf)
 +{
 +    AVCodecContext *avctx;
 +    AVPacket avpkt;
 +    int16_t *samples = NULL;
 +    uint8_t *inbuf = NULL;
 +    int inbuf_size = 0;
 +    int len = 0, frame_size_ptr = 0;
 +    uint8_t *meta_buf = NULL;
 +    DeviceMemEntry *elem = NULL;
 +    uint8_t *tempbuf = NULL;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    meta_buf = s->vaddr + ((ctx_id - 1) * CODEC_META_DATA_SIZE);
 +    meta_buf += 8; // skipped header.
 +
 +    memcpy(&inbuf_size, meta_buf, sizeof(inbuf_size));
 +    TRACE("before decoding audio. inbuf_size: %d\n", inbuf_size);
 +
 +    elem = (DeviceMemEntry *)data_buf;
 +    if (elem && elem->buf) {
 +        inbuf = elem->buf;
 +    } else if (elem) {
 +        inbuf_size = 0;
 +        TRACE("decode_audio. no input buffer.\n");
 +    } else {
 +        ERR("wrong input data\n");
 +        return false;
 +    }
 +
 +    av_init_packet(&avpkt);
 +    avpkt.data = inbuf;
 +    avpkt.size = inbuf_size;
 +
 +    avctx = s->context[ctx_id].avctx;
 +    if (!avctx) {
 +        ERR("[%s] %d of AVCodecContext is NULL!\n", __func__, ctx_id);
 +        write_codec_decode_audio_data(0, 0, 0, -1, 0, meta_buf);
 +    } else if (!avctx->codec) {
 +        ERR("%d of AVCodec is NULL.\n", ctx_id);
 +        write_codec_decode_audio_data(0, 0, 0, -1, 0, meta_buf);
 +    } else {
 +        frame_size_ptr = AVCODEC_MAX_AUDIO_FRAME_SIZE;
 +        samples = av_mallocz(frame_size_ptr);
 +        if (!samples) {
 +            ERR("failed to allocate an outbuf of audio.\n");
 +            len = -1;
 +        } else {
 +            len =
 +                avcodec_decode_audio3(avctx, samples, &frame_size_ptr, &avpkt);
 +
 +            TRACE("audio. len %d, channel_layout %lld, frame_size %d\n",
 +                len, avctx->channel_layout, frame_size_ptr);
 +        }
 +
 +        write_codec_decode_audio_data(avctx->sample_rate, avctx->channels,
 +                                    avctx->channel_layout, len,
 +                                    frame_size_ptr, meta_buf);
 +    }
 +
 +    if (len < 0) {
 +        ERR("failed to decode audio. ctx_id: %d, len: %d\n", ctx_id, len);
 +        frame_size_ptr = 0;
 +    } else {
 +        if (frame_size_ptr > 0) {
 +            tempbuf = g_malloc0(frame_size_ptr);
 +            if (!tempbuf) {
 +                ERR("failed to allocate decoded audio buffer. "
 +                    "ctx_id: %d, outbuf_size: %d\n", ctx_id, frame_size_ptr);
 +            } else {
 +                memcpy(tempbuf, samples, frame_size_ptr);
 +            }
 +            av_free(samples);
 +        }
 +    }
 +
 +    maru_brill_codec_push_writequeue(s, tempbuf, frame_size_ptr, ctx_id);
 +
 +    TRACE("leave: %s\n", __func__);
 +
 +    return true;
 +}
 +
 +static bool codec_encode_video(MaruBrillCodecState *s, int ctx_id, void *data_buf)
 +{
 +    AVCodecContext *avctx = NULL;
 +    AVFrame *pict = NULL;
 +    uint8_t *inbuf = NULL, *outbuf = NULL;
 +    int inbuf_size, outbuf_size, len = 0;
 +    int ret;
 +    int64_t in_timestamp;
 +
 +    uint8_t *meta_buf = NULL;
 +    DeviceMemEntry *elem = NULL;
 +    uint8_t *tempbuf = NULL;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    meta_buf = s->vaddr + ((ctx_id - 1) * CODEC_META_DATA_SIZE);
 +    meta_buf += 8; // skipped header.
 +
 +    memcpy(&inbuf_size, meta_buf, sizeof(inbuf_size));
 +    memcpy(&in_timestamp, meta_buf + sizeof(inbuf_size), sizeof(in_timestamp));
 +    TRACE("input buffer size: %d\n", inbuf_size);
 +
 +    elem = (DeviceMemEntry *)data_buf;
 +    if (elem && elem->buf) {
 +        inbuf = elem->buf;
 +    } else if (elem) {
 +        TRACE("encode_video. no input buffer.\n");
 +        inbuf_size = 0;
 +    } else {
 +        ERR("wrong input data\n");
 +        return false;
 +    }
 +
 +    avctx = s->context[ctx_id].avctx;
 +    pict = s->context[ctx_id].frame;
 +    if (!avctx || !pict) {
 +        ERR("%d of context or frame is NULL\n", ctx_id);
 +        len = -1;
 +    } else if (!avctx->codec) {
 +        ERR("%d of AVCodec is NULL.\n", ctx_id);
 +        len = -1;
 +    } else {
 +        TRACE("pixel format: %d inbuf: %p, picture data: %p\n",
 +                avctx->pix_fmt, inbuf, pict->data[0]);
 +
 +        ret =
 +            maru_brill_codec_get_picture_size((AVPicture *)pict, inbuf,
 +                                            avctx->pix_fmt, avctx->width,
 +                                            avctx->height, true);
 +        if (ret < 0) {
 +            ERR("after avpicture_fill, ret:%d\n", ret);
 +            len = -1;
 +        } else {
 +            if (avctx->time_base.num == 0) {
 +                pict->pts = AV_NOPTS_VALUE;
 +            } else {
 +                AVRational bq =
 +                    {1, (G_USEC_PER_SEC * G_GINT64_CONSTANT(1000))};
 +                pict->pts = av_rescale_q(in_timestamp, bq, avctx->time_base);
 +            }
 +            TRACE("before encode video, ticks_per_frame:%d, pts:%lld\n",
 +                    avctx->ticks_per_frame, pict->pts);
 +
 +            outbuf_size =
 +                (avctx->width * avctx->height * 6) + FF_MIN_BUFFER_SIZE;
 +            outbuf = g_malloc0(outbuf_size);
 +            if (!outbuf) {
 +                ERR("failed to allocate a buffer of encoding video.\n");
 +                len = -1;
 +            } else {
 +                len = avcodec_encode_video(avctx, outbuf, outbuf_size, pict);
 +
 +                TRACE("encode video! len:%d pts:%lld outbuf:%p outbuf size: %d\n",
 +                        len, pict->pts, outbuf, outbuf_size);
 +           }
 +        }
 +    }
 +
 +    // write encoded video data
 +    memcpy(meta_buf, &len, sizeof(len));
 +    if (len < 0) {
 +        ERR("failed to encode video. len: %d\n", len);
 +    } else {
 +        tempbuf = g_malloc0(len);
 +        if (!tempbuf) {
 +            ERR("failed to allocate an element of writequeue.\n");
 +        } else {
 +            memcpy(tempbuf, outbuf, len);
 +        }
 +    }
 +
 +    if (outbuf) {
 +        TRACE("release encoded output buffer. %p\n", outbuf);
 +        g_free(outbuf);
 +    }
 +
 +    maru_brill_codec_push_writequeue(s, tempbuf, len, ctx_id);
 +
 +    TRACE("leave: %s\n", __func__);
 +    return true;
 +}
 +
 +static bool codec_encode_audio(MaruBrillCodecState *s, int ctx_id, void *data_buf)
 +{
 +    AVCodecContext *avctx;
 +    uint8_t *inbuf = NULL, *outbuf = NULL;
 +    int32_t inbuf_size, max_size;
 +    int len = 0;
 +    uint8_t *meta_buf = NULL;
 +
 +    DeviceMemEntry *elem = NULL;
 +    uint8_t *tempbuf = NULL;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    meta_buf = s->vaddr + ((ctx_id - 1) * CODEC_META_DATA_SIZE);
 +    meta_buf += 8; // skipped header.
 +
 +    memcpy(&inbuf_size, meta_buf, sizeof(inbuf_size));
 +    memcpy(&max_size, meta_buf + sizeof(inbuf_size), sizeof(max_size));
 +    TRACE("encoding audio. in_size: %d, max_size: %d\n", inbuf_size, max_size);
 +
 +    elem = (DeviceMemEntry *)data_buf;
 +    if (elem && elem->buf) {
 +        inbuf = elem->buf;
 +    } else if (elem) {
 +        TRACE("no input buffer to encode audio.\n");
 +        inbuf_size = 0;
 +    } else {
 +        ERR("wrong input data\n");
 +        return false;
 +    }
 +
 +    avctx = s->context[ctx_id].avctx;
 +    if (!avctx) {
 +        ERR("[%s] %d of Context is NULL!\n", __func__, ctx_id);
 +    } else if (!avctx->codec) {
 +        ERR("%d of AVCodec is NULL.\n", ctx_id);
 +    } else {
 +        outbuf = g_malloc0(max_size + FF_MIN_BUFFER_SIZE);
 +        if (!outbuf) {
 +            ERR("failed to allocate a buffer of encoding audio.\n");
 +            len = -1;
 +        } else {
 +            len =
 +                avcodec_encode_audio(avctx, outbuf, max_size, (short *)inbuf);
 +            TRACE("after encoding audio. len: %d\n", len);
 +        }
 +    }
 +
 +    // write encoded audio data
 +    memcpy(meta_buf, &len, sizeof(len));
 +    if (len < 0) {
 +        ERR("failed to encode audio. ctx_id: %d len: %d\n", ctx_id, len);
 +    } else {
 +        tempbuf = g_malloc0(len);
 +        if (!tempbuf) {
 +            ERR("encode_audio. failed to allocate temporary buffer.\n");
 +        } else {
 +            memcpy(tempbuf, outbuf, len);
 +        }
 +    }
 +
 +    if (outbuf) {
 +        av_free(outbuf);
 +    }
 +
 +    maru_brill_codec_push_writequeue(s, tempbuf, len, ctx_id);
 +
 +    TRACE("[%s] leave:\n", __func__);
 +    return true;
 +}
 +
 +static AVCodecParserContext *maru_brill_codec_parser_init(AVCodecContext *avctx)
 +{
 +    AVCodecParserContext *parser = NULL;
 +
 +    if (!avctx) {
 +        ERR("context is NULL\n");
 +        return NULL;
 +    }
 +
 +    switch (avctx->codec_id) {
 +    case CODEC_ID_MPEG4:
 +    case CODEC_ID_VC1:
 +        TRACE("not using parser.\n");
 +        break;
 +    case CODEC_ID_H264:
 +        if (avctx->extradata_size == 0) {
 +            TRACE("H.264 with no extradata, creating parser.\n");
 +            parser = av_parser_init (avctx->codec_id);
 +        }
 +        break;
 +    default:
 +        parser = av_parser_init (avctx->codec_id);
 +        if (parser) {
 +            INFO("using parser. %d\n", avctx->codec_id);
 +        }
 +        break;
 +    }
 +
 +    return parser;
 +}
 +
 +//
 +static void maru_brill_codec_bh_callback(void *opaque)
 +{
 +    MaruBrillCodecState *s = (MaruBrillCodecState *)opaque;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    qemu_mutex_lock(&s->context_queue_mutex);
 +    if (!QTAILQ_EMPTY(&codec_wq)) {
 +        qemu_mutex_unlock(&s->context_queue_mutex);
 +
 +        TRACE("raise irq\n");
-             qemu_irq_lower(s->dev.irq[0]);
++        pci_set_irq(&s->dev, 1);
 +        s->irq_raised = 1;
 +    } else {
 +        qemu_mutex_unlock(&s->context_queue_mutex);
 +        TRACE("codec_wq is empty!!\n");
 +    }
 +
 +    TRACE("leave: %s\n", __func__);
 +}
 +
 +/*
 + *  Codec Device APIs
 + */
 +static uint64_t maru_brill_codec_read(void *opaque,
 +                                        hwaddr addr,
 +                                        unsigned size)
 +{
 +    MaruBrillCodecState *s = (MaruBrillCodecState *)opaque;
 +    uint64_t ret = 0;
 +
 +    switch (addr) {
 +    case CODEC_CMD_GET_THREAD_STATE:
 +        qemu_mutex_lock(&s->context_queue_mutex);
 +        if (s->irq_raised) {
 +            ret = CODEC_TASK_END;
++            pci_set_irq(&s->dev, 0);
 +            s->irq_raised = 0;
 +        }
 +        qemu_mutex_unlock(&s->context_queue_mutex);
 +
 +        TRACE("get thread_state. ret: %d\n", ret);
 +        break;
 +
 +    case CODEC_CMD_GET_CTX_FROM_QUEUE:
 +    {
 +        DeviceMemEntry *head = NULL;
 +
 +        qemu_mutex_lock(&s->context_queue_mutex);
 +        head = QTAILQ_FIRST(&codec_wq);
 +        if (head) {
 +            ret = head->ctx_id;
 +            QTAILQ_REMOVE(&codec_wq, head, node);
 +            entry[ret] = head;
 +            TRACE("get a elem from codec_wq. 0x%x\n", head);
 +        } else {
 +            ret = 0;
 +        }
 +        qemu_mutex_unlock(&s->context_queue_mutex);
 +
 +        TRACE("get a head from a writequeue. head: %x\n", ret);
 +    }
 +        break;
 +
 +    case CODEC_CMD_GET_VERSION:
 +        ret = CODEC_VERSION;
 +        TRACE("codec version: %d\n", ret);
 +        break;
 +
 +    case CODEC_CMD_GET_ELEMENT:
 +        ret = maru_brill_codec_query_list(s);
 +        break;
 +
 +    case CODEC_CMD_GET_CONTEXT_INDEX:
 +        ret = maru_brill_codec_get_context_index(s);
 +        TRACE("get context index: %d\n", ret);
 +        break;
 +
 +    default:
 +        ERR("no avaiable command for read. %d\n", addr);
 +    }
 +
 +    return ret;
 +}
 +
 +static void maru_brill_codec_write(void *opaque, hwaddr addr,
 +                                    uint64_t value, unsigned size)
 +{
 +    MaruBrillCodecState *s = (MaruBrillCodecState *)opaque;
 +
 +    switch (addr) {
 +    case CODEC_CMD_API_INDEX:
 +        TRACE("set codec_cmd value: %d\n", value);
 +        s->ioparam.api_index = value;
 +        maru_brill_codec_wakeup_threads(s, value);
 +        break;
 +
 +    case CODEC_CMD_CONTEXT_INDEX:
 +        TRACE("set context_index value: %d\n", value);
 +        s->ioparam.ctx_index = value;
 +        break;
 +
 +    case CODEC_CMD_DEVICE_MEM_OFFSET:
 +        TRACE("set mem_offset value: 0x%x\n", value);
 +        s->ioparam.mem_offset = value;
 +        break;
 +
 +    case CODEC_CMD_RELEASE_CONTEXT:
 +        maru_brill_codec_release_context(s, (int32_t)value);
 +        break;
 +
 +    case CODEC_CMD_GET_DATA_FROM_QUEUE:
 +        maru_brill_codec_pop_writequeue(s, (uint32_t)value);
 +        break;
 +
 +    default:
 +        ERR("no available command for write. %d\n", addr);
 +    }
 +}
 +
 +static const MemoryRegionOps maru_brill_codec_mmio_ops = {
 +    .read = maru_brill_codec_read,
 +    .write = maru_brill_codec_write,
 +    .valid = {
 +        .min_access_size = 4,
 +        .max_access_size = 4,
 +        .unaligned = false
 +    },
 +    .endianness = DEVICE_LITTLE_ENDIAN,
 +};
 +
 +static int maru_brill_codec_initfn(PCIDevice *dev)
 +{
 +    MaruBrillCodecState *s = DO_UPCAST(MaruBrillCodecState, dev, dev);
 +    uint8_t *pci_conf = s->dev.config;
 +
 +    INFO("device initialization.\n");
 +    pci_config_set_interrupt_pin(pci_conf, 1);
 +
 +    memory_region_init_ram(&s->vram, OBJECT(s), "maru_brill_codec.vram", CODEC_MEM_SIZE);
 +    s->vaddr = (uint8_t *)memory_region_get_ram_ptr(&s->vram);
 +
 +    memory_region_init_io(&s->mmio, OBJECT(s), &maru_brill_codec_mmio_ops, s,
 +                        "maru_brill_codec.mmio", CODEC_REG_SIZE);
 +
 +    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
 +    pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio);
 +
 +//    maru_brill_codec_reset(&s->dev.qdev);
 +
 +    qemu_mutex_init(&s->context_mutex);
 +    qemu_mutex_init(&s->context_queue_mutex);
 +    qemu_mutex_init(&s->ioparam_queue_mutex);
 +
 +    maru_brill_codec_get_cpu_cores(s);
 +    maru_brill_codec_threads_create(s);
 +
 +    // register a function to qemu bottom-halves to switch context.
 +    s->codec_bh = qemu_bh_new(maru_brill_codec_bh_callback, s);
 +
 +    return 0;
 +}
 +
 +static void maru_brill_codec_exitfn(PCIDevice *dev)
 +{
 +    MaruBrillCodecState *s = DO_UPCAST(MaruBrillCodecState, dev, dev);
 +    INFO("device exit\n");
 +
 +    qemu_mutex_destroy(&s->context_mutex);
 +    qemu_mutex_destroy(&s->context_queue_mutex);
 +    qemu_mutex_destroy(&s->ioparam_queue_mutex);
 +
 +    qemu_bh_delete(s->codec_bh);
 +
 +    memory_region_destroy(&s->vram);
 +    memory_region_destroy(&s->mmio);
 +}
 +
 +static void maru_brill_codec_reset(DeviceState *d)
 +{
 +    MaruBrillCodecState *s = (MaruBrillCodecState *)d;
 +    INFO("device reset\n");
 +
 +    s->irq_raised = 0;
 +
 +    memset(&s->context, 0, sizeof(CodecContext) * CODEC_CONTEXT_MAX);
 +    memset(&s->ioparam, 0, sizeof(CodecParam));
 +
 +    maru_brill_codec_pixfmt_info_init();
 +}
 +
 +static void maru_brill_codec_class_init(ObjectClass *klass, void *data)
 +{
 +    DeviceClass *dc = DEVICE_CLASS(klass);
 +    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = maru_brill_codec_initfn;
 +    k->exit = maru_brill_codec_exitfn;
 +    k->vendor_id = PCI_VENDOR_ID_TIZEN;
 +    k->device_id = PCI_DEVICE_ID_VIRTUAL_BRILL_CODEC;
 +    k->class_id = PCI_CLASS_OTHERS;
 +    dc->reset = maru_brill_codec_reset;
 +    dc->desc = "Virtual new codec device for Tizen emulator";
 +}
 +
 +static TypeInfo codec_device_info = {
 +    .name          = CODEC_DEVICE_NAME,
 +    .parent        = TYPE_PCI_DEVICE,
 +    .instance_size = sizeof(MaruBrillCodecState),
 +    .class_init    = maru_brill_codec_class_init,
 +};
 +
 +static void codec_register_types(void)
 +{
 +    type_register_static(&codec_device_info);
 +}
 +
 +type_init(codec_register_types)
 +
 +int maru_brill_codec_pci_device_init(PCIBus *bus)
 +{
 +    INFO("device create.\n");
 +    pci_create_simple(bus, -1, CODEC_DEVICE_NAME);
 +    return 0;
 +}
index 840f4da,0000000..dd6c4fa
mode 100644,000000..100644
--- /dev/null
@@@ -1,157 -1,0 +1,158 @@@
 +/*
 + * Virtual Codec device
 + *
 + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
 + *
 + * Contact:
 + *  Kitae Kim <kt920.kim@samsung.com>
 + *  SeokYeon Hwang <syeon.hwang@samsung.com>
 + *  YeongKyoon Lee <yeongkyoon.lee@samsung.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., 51 Franklin Street, Fifth Floor, Boston,
 + * MA 02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + */
 +
 +#include <stdio.h>
 +#include <sys/types.h>
 +
 +#include "hw/hw.h"
 +#include "sysemu/kvm.h"
++#include "qemu/main-loop.h"
 +#include "hw/pci/pci.h"
 +#include "hw/pci/pci_ids.h"
 +#include "qemu-common.h"
 +#include "qemu/thread.h"
 +
 +#include "osutil.h"
 +#include "tizen/src/debug_ch.h"
 +#include "maru_device_ids.h"
 +#include "libavformat/avformat.h"
 +
 +#define CODEC_CONTEXT_MAX           1024
 +
 +/*
 + *  Codec Device Structures
 + */
 +typedef struct CodecParam {
 +    int32_t     api_index;
 +    int32_t     ctx_index;
 +    uint32_t    mem_offset;
 +} CodecParam;
 +
 +struct video_data {
 +    int32_t width;
 +    int32_t height;
 +    int32_t fps_n;
 +    int32_t fps_d;
 +    int32_t par_n;
 +    int32_t par_d;
 +    int32_t pix_fmt;
 +    int32_t bpp;
 +    int32_t ticks_per_frame;
 +};
 +
 +struct audio_data {
 +    int32_t channels;
 +    int32_t sample_rate;
 +    int32_t block_align;
 +    int32_t depth;
 +    int32_t sample_fmt;
 +    int32_t frame_size;
 +    int32_t bits_per_smp_fmt;
 +    int64_t channel_layout;
 +};
 +
 +typedef struct CodecContext {
 +    AVCodecContext          *avctx;
 +    AVFrame                 *frame;
 +    AVCodecParserContext    *parser_ctx;
 +    uint8_t                 *parser_buf;
 +    uint16_t                parser_use;
 +    bool                    occupied;
 +    bool                    opened;
 +} CodecContext;
 +
 +typedef struct CodecThreadPool {
 +    QemuThread          *threads;
 +    QemuMutex           mutex;
 +    QemuCond            cond;
 +} CodecThreadPool;
 +
 +typedef struct MaruBrillCodecState {
 +    PCIDevice           dev;
 +
 +    uint8_t             *vaddr;
 +    MemoryRegion        vram;
 +    MemoryRegion        mmio;
 +
 +    QEMUBH              *codec_bh;
 +    QemuMutex           context_mutex;
 +    QemuMutex           context_queue_mutex;
 +    QemuMutex           ioparam_queue_mutex;
 +
 +    CodecThreadPool     threadpool;
 +    bool                is_thread_running;
 +    uint32_t            worker_thread_cnt;
 +    uint32_t            idle_thread_cnt;
 +
 +    int                 irq_raised;
 +
 +    CodecContext        context[CODEC_CONTEXT_MAX];
 +    CodecParam          ioparam;
 +} MaruBrillCodecState;
 +
 +enum codec_io_cmd {
 +    CODEC_CMD_API_INDEX             = 0x28,
 +    CODEC_CMD_CONTEXT_INDEX         = 0x2C,
 +    CODEC_CMD_DEVICE_MEM_OFFSET     = 0x34,
 +    CODEC_CMD_GET_THREAD_STATE      = 0x38,
 +    CODEC_CMD_GET_CTX_FROM_QUEUE    = 0x3C,
 +    CODEC_CMD_GET_DATA_FROM_QUEUE   = 0x40,
 +    CODEC_CMD_RELEASE_CONTEXT       = 0x44,
 +    CODEC_CMD_GET_VERSION           = 0x50,
 +    CODEC_CMD_GET_ELEMENT           = 0x54,
 +    CODEC_CMD_GET_CONTEXT_INDEX     = 0x58,
 +};
 +
 +enum codec_api_type {
 +    CODEC_INIT = 0,
 +    CODEC_DECODE_VIDEO,
 +    CODEC_ENCODE_VIDEO,
 +    CODEC_DECODE_AUDIO,
 +    CODEC_ENCODE_AUDIO,
 +    CODEC_PICTURE_COPY,
 +    CODEC_DEINIT,
 +    CODEC_FLUSH_BUFFERS,
 + };
 +
 +enum codec_type {
 +    CODEC_TYPE_UNKNOWN = -1,
 +    CODEC_TYPE_DECODE,
 +    CODEC_TYPE_ENCODE,
 +};
 +
 +enum thread_state {
 +    CODEC_TASK_START    = 0,
 +    CODEC_TASK_END      = 0x1f,
 +};
 +
 +/*
 + *  Codec Device Functions
 + */
 +int maru_brill_codec_pci_device_init(PCIBus *bus);
index 23f7e66,0000000..7e32e83
mode 100644,000000..100644
--- /dev/null
@@@ -1,288 -1,0 +1,289 @@@
-             qemu_irq_lower(state->dev.irq[2]);
 +/*
 + * Common implementation of MARU Virtual Camera device by PCI bus.
 + *
 + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
 + *
 + * Contact:
 + * JinHyung Jo <jinhyung.jo@samsung.com>
 + * YeongKyoon Lee <yeongkyoon.lee@samsung.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., 51 Franklin Street, Fifth Floor, Boston,
 + * MA  02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + */
 +
 +
 +#include <stdarg.h>
 +#include <stdlib.h>
 +#include <stdio.h>
 +#include <string.h>
 +#include <inttypes.h>
 +#include <signal.h>
 +
 +#include "qemu-common.h"
++#include "qemu/main-loop.h"
 +#include "exec/cpu-common.h"
 +
 +#include "maru_camera_common.h"
 +#include "maru_device_ids.h"
 +#include "tizen/src/debug_ch.h"
 +
 +MULTI_DEBUG_CHANNEL(tizen, camera_pci);
 +
 +#define MARU_PCI_CAMERA_DEVICE_NAME     "maru_camera_pci"
 +
 +#define MARUCAM_MEM_SIZE    (4 * 1024 * 1024)   /* 4MB */
 +#define MARUCAM_REG_SIZE    (256)               /* 64 * 4Byte */
 +
 +/*
 + *  I/O functions
 + */
 +static inline uint32_t
 +marucam_mmio_read(void *opaque, hwaddr offset)
 +{
 +    uint32_t ret = 0;
 +    MaruCamState *state = (MaruCamState *)opaque;
 +
 +    switch (offset & 0xFF) {
 +    case MARUCAM_CMD_ISR:
 +        qemu_mutex_lock(&state->thread_mutex);
 +        ret = state->isr;
 +        if (ret != 0) {
-         qemu_irq_raise(state->dev.irq[2]);
++            pci_set_irq(&state->dev, 0);
 +            state->isr = 0;
 +        }
 +        qemu_mutex_unlock(&state->thread_mutex);
 +        break;
 +    case MARUCAM_CMD_G_DATA:
 +        ret = state->param->stack[state->param->top++];
 +        break;
 +    case MARUCAM_CMD_OPEN:
 +    case MARUCAM_CMD_CLOSE:
 +    case MARUCAM_CMD_START_PREVIEW:
 +    case MARUCAM_CMD_STOP_PREVIEW:
 +    case MARUCAM_CMD_S_PARAM:
 +    case MARUCAM_CMD_G_PARAM:
 +    case MARUCAM_CMD_ENUM_FMT:
 +    case MARUCAM_CMD_TRY_FMT:
 +    case MARUCAM_CMD_S_FMT:
 +    case MARUCAM_CMD_G_FMT:
 +    case MARUCAM_CMD_QCTRL:
 +    case MARUCAM_CMD_S_CTRL:
 +    case MARUCAM_CMD_G_CTRL:
 +    case MARUCAM_CMD_ENUM_FSIZES:
 +    case MARUCAM_CMD_ENUM_FINTV:
 +        ret = state->param->errCode;
 +        state->param->errCode = 0;
 +        break;
 +    default:
 +        ERR("Not supported command: 0x%x\n", offset);
 +        ret = EINVAL;
 +        break;
 +    }
 +    return ret;
 +}
 +
 +static inline void
 +marucam_mmio_write(void *opaque, hwaddr offset, uint32_t value)
 +{
 +    MaruCamState *state = (MaruCamState *)opaque;
 +
 +    switch (offset & 0xFF) {
 +    case MARUCAM_CMD_OPEN:
 +        marucam_device_open(state);
 +        break;
 +    case MARUCAM_CMD_CLOSE:
 +        marucam_device_close(state);
 +        break;
 +    case MARUCAM_CMD_START_PREVIEW:
 +        marucam_device_start_preview(state);
 +        break;
 +    case MARUCAM_CMD_STOP_PREVIEW:
 +        marucam_device_stop_preview(state);
 +        memset(state->vaddr, 0, MARUCAM_MEM_SIZE);
 +        break;
 +    case MARUCAM_CMD_S_PARAM:
 +        marucam_device_s_param(state);
 +        break;
 +    case MARUCAM_CMD_G_PARAM:
 +        marucam_device_g_param(state);
 +        break;
 +    case MARUCAM_CMD_ENUM_FMT:
 +        marucam_device_enum_fmt(state);
 +        break;
 +    case MARUCAM_CMD_TRY_FMT:
 +        marucam_device_try_fmt(state);
 +        break;
 +    case MARUCAM_CMD_S_FMT:
 +        marucam_device_s_fmt(state);
 +        break;
 +    case MARUCAM_CMD_G_FMT:
 +        marucam_device_g_fmt(state);
 +        break;
 +    case MARUCAM_CMD_QCTRL:
 +        marucam_device_qctrl(state);
 +        break;
 +    case MARUCAM_CMD_S_CTRL:
 +        marucam_device_s_ctrl(state);
 +        break;
 +    case MARUCAM_CMD_G_CTRL:
 +        marucam_device_g_ctrl(state);
 +        break;
 +    case MARUCAM_CMD_ENUM_FSIZES:
 +        marucam_device_enum_fsizes(state);
 +        break;
 +    case MARUCAM_CMD_ENUM_FINTV:
 +        marucam_device_enum_fintv(state);
 +        break;
 +    case MARUCAM_CMD_S_DATA:
 +        state->param->stack[state->param->top++] = value;
 +        break;
 +    case MARUCAM_CMD_DATACLR:
 +        memset(state->param, 0, sizeof(MaruCamParam));
 +        break;
 +    case MARUCAM_CMD_REQFRAME:
 +        qemu_mutex_lock(&state->thread_mutex);
 +        state->req_frame = value + 1;
 +        qemu_mutex_unlock(&state->thread_mutex);
 +        break;
 +    default:
 +        ERR("Not supported command: 0x%x\n", offset);
 +        break;
 +    }
 +}
 +
 +static const MemoryRegionOps maru_camera_mmio_ops = {
 +    .old_mmio = {
 +        .read = {
 +            marucam_mmio_read,
 +            marucam_mmio_read,
 +            marucam_mmio_read,
 +        },
 +        .write = {
 +            marucam_mmio_write,
 +            marucam_mmio_write,
 +            marucam_mmio_write,
 +        },
 +    },
 +    .endianness = DEVICE_LITTLE_ENDIAN,
 +};
 +
 +/*
 + *  QEMU bottom half funtion
 + */
 +static void marucam_tx_bh(void *opaque)
 +{
 +    MaruCamState *state = (MaruCamState *)opaque;
 +
 +    qemu_mutex_lock(&state->thread_mutex);
 +    if (state->isr) {
++        pci_set_irq(&state->dev, 1);
 +    }
 +    qemu_mutex_unlock(&state->thread_mutex);
 +}
 +
 +/*
 + *  Initialization function
 + */
 +static int marucam_initfn(PCIDevice *dev)
 +{
 +    MaruCamState *s = DO_UPCAST(MaruCamState, dev, dev);
 +    uint8_t *pci_conf = s->dev.config;
 +
 +    pci_config_set_interrupt_pin(pci_conf, 0x03);
 +
 +    memory_region_init_ram(&s->vram, OBJECT(s), "marucamera.ram", MARUCAM_MEM_SIZE);
 +    s->vaddr = memory_region_get_ram_ptr(&s->vram);
 +    memset(s->vaddr, 0, MARUCAM_MEM_SIZE);
 +
 +    memory_region_init_io(&s->mmio, OBJECT(s),
 +                          &maru_camera_mmio_ops,
 +                          s,
 +                          "maru-camera-mmio",
 +                          MARUCAM_REG_SIZE);
 +
 +    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
 +    pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio);
 +
 +    /* for worker thread */
 +    s->param = (MaruCamParam *)g_malloc0(sizeof(MaruCamParam));
 +    qemu_cond_init(&s->thread_cond);
 +    qemu_mutex_init(&s->thread_mutex);
 +
 +    marucam_device_init(s);
 +
 +    s->tx_bh = qemu_bh_new(marucam_tx_bh, s);
 +    INFO("[%s] camera device was initialized.\n", __func__);
 +
 +    return 0;
 +}
 +
 +/*
 + *  Termination function
 + */
 +static void marucam_exitfn(PCIDevice *pci_dev)
 +{
 +    MaruCamState *s =
 +        OBJECT_CHECK(MaruCamState, pci_dev, MARU_PCI_CAMERA_DEVICE_NAME);
 +
 +    marucam_device_exit(s);
 +    g_free(s->param);
 +    qemu_cond_destroy(&s->thread_cond);
 +    qemu_mutex_destroy(&s->thread_mutex);
 +
 +    memory_region_destroy(&s->vram);
 +    memory_region_destroy(&s->mmio);
 +
 +
 +    INFO("[%s] camera device was released.\n", __func__);
 +}
 +
 +int maru_camera_pci_init(PCIBus *bus)
 +{
 +    INFO("[%s] camera device was initialized.\n", __func__);
 +    pci_create_simple(bus, -1, MARU_PCI_CAMERA_DEVICE_NAME);
 +    return 0;
 +}
 +
 +static void maru_camera_pci_class_init(ObjectClass *klass, void *data)
 +{
 +    DeviceClass *dc = DEVICE_CLASS(klass);
 +    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 +
 +    k->no_hotplug = 1;
 +    k->init = marucam_initfn;
 +    k->exit = marucam_exitfn;
 +    k->vendor_id = PCI_VENDOR_ID_TIZEN;
 +    k->device_id = PCI_DEVICE_ID_VIRTUAL_CAMERA;
 +    k->class_id = PCI_CLASS_OTHERS;
 +    dc->desc = "MARU Virtual Camera device for Tizen emulator";
 +}
 +
 +static TypeInfo maru_camera_info = {
 +    .name          = MARU_PCI_CAMERA_DEVICE_NAME,
 +    .parent        = TYPE_PCI_DEVICE,
 +    .instance_size = sizeof(MaruCamState),
 +    .class_init    = maru_camera_pci_class_init,
 +};
 +
 +static void maru_camera_pci_register_types(void)
 +{
 +    type_register_static(&maru_camera_info);
 +}
 +
 +type_init(maru_camera_pci_register_types)
index db547c6,0000000..e8ea00c
mode 100644,000000..100644
--- /dev/null
@@@ -1,1461 -1,0 +1,1461 @@@
-         cur_tick = qemu_get_clock_ns(vm_clock);
 +/*
 + * Maru vga device
 + * Based on qemu/hw/vga.c
 + *
 + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
 + *
 + * Contact:
 + * JinHyung Jo <jinhyung.jo@samsung.com>
 + * GiWoong Kim <giwoong.kim@samsung.com>
 + * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
 + * HyunJun Son
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + */
 +
 +#include "hw/hw.h"
 +#include "display/vga.h"
 +#include "ui/console.h"
 +#include "hw/i386/pc.h"
 +#include "hw/pci/pci.h"
 +#include "display/vga_int.h"
 +#include "ui/pixel_ops.h"
 +#include "qemu/timer.h"
 +#include "hw/xen/xen.h"
 +#include "trace.h"
 +
 +#include <pthread.h>
 +
 +#define MARU_VGA
 +#include "maru_common.h"
 +#include "maru_vga_int.h"
 +#include "debug_ch.h"
 +
 +MULTI_DEBUG_CHANNEL(qemu, maru_vga);
 +
 +//#define DEBUG_VGA
 +//#define DEBUG_VGA_MEM
 +//#define DEBUG_VGA_REG
 +
 +//#define DEBUG_BOCHS_VBE
 +
 +/* 16 state changes per vertical frame @60 Hz */
 +#define VGA_TEXT_CURSOR_PERIOD_MS       (1000 * 2 * 16 / 60)
 +
 +#define cbswap_32(__x) \
 +((uint32_t)( \
 +        (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
 +        (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
 +        (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
 +        (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
 +
 +#ifdef HOST_WORDS_BIGENDIAN
 +#define PAT(x) cbswap_32(x)
 +#else
 +#define PAT(x) (x)
 +#endif
 +
 +#ifdef HOST_WORDS_BIGENDIAN
 +#define BIG 1
 +#else
 +#define BIG 0
 +#endif
 +
 +#ifdef HOST_WORDS_BIGENDIAN
 +#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
 +#else
 +#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
 +#endif
 +
 +static const uint32_t mask16[16] = {
 +    PAT(0x00000000),
 +    PAT(0x000000ff),
 +    PAT(0x0000ff00),
 +    PAT(0x0000ffff),
 +    PAT(0x00ff0000),
 +    PAT(0x00ff00ff),
 +    PAT(0x00ffff00),
 +    PAT(0x00ffffff),
 +    PAT(0xff000000),
 +    PAT(0xff0000ff),
 +    PAT(0xff00ff00),
 +    PAT(0xff00ffff),
 +    PAT(0xffff0000),
 +    PAT(0xffff00ff),
 +    PAT(0xffffff00),
 +    PAT(0xffffffff),
 +};
 +
 +#undef PAT
 +
 +#ifdef HOST_WORDS_BIGENDIAN
 +#define PAT(x) (x)
 +#else
 +#define PAT(x) cbswap_32(x)
 +#endif
 +
 +static const uint32_t dmask16[16] = {
 +    PAT(0x00000000),
 +    PAT(0x000000ff),
 +    PAT(0x0000ff00),
 +    PAT(0x0000ffff),
 +    PAT(0x00ff0000),
 +    PAT(0x00ff00ff),
 +    PAT(0x00ffff00),
 +    PAT(0x00ffffff),
 +    PAT(0xff000000),
 +    PAT(0xff0000ff),
 +    PAT(0xff00ff00),
 +    PAT(0xff00ffff),
 +    PAT(0xffff0000),
 +    PAT(0xffff00ff),
 +    PAT(0xffffff00),
 +    PAT(0xffffffff),
 +};
 +
 +static const uint32_t dmask4[4] = {
 +    PAT(0x00000000),
 +    PAT(0x0000ffff),
 +    PAT(0xffff0000),
 +    PAT(0xffffffff),
 +};
 +
 +static uint32_t expand4[256];
 +static uint16_t expand2[256];
 +static uint8_t expand4to8[16];
 +
 +static void vga_dumb_update_retrace_info(VGACommonState *s)
 +{
 +    (void) s;
 +}
 +
 +static void vga_precise_update_retrace_info(VGACommonState *s)
 +{
 +    int htotal_chars;
 +    int hretr_start_char;
 +    int hretr_skew_chars;
 +    int hretr_end_char;
 +
 +    int vtotal_lines;
 +    int vretr_start_line;
 +    int vretr_end_line;
 +
 +    int dots;
 +#if 0
 +    int div2, sldiv2;
 +#endif
 +    int clocking_mode;
 +    int clock_sel;
 +    const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
 +    int64_t chars_per_sec;
 +    struct vga_precise_retrace *r = &s->retrace_info.precise;
 +
 +    htotal_chars = s->cr[VGA_CRTC_H_TOTAL] + 5;
 +    hretr_start_char = s->cr[VGA_CRTC_H_SYNC_START];
 +    hretr_skew_chars = (s->cr[VGA_CRTC_H_SYNC_END] >> 5) & 3;
 +    hretr_end_char = s->cr[VGA_CRTC_H_SYNC_END] & 0x1f;
 +
 +    vtotal_lines = (s->cr[VGA_CRTC_V_TOTAL] |
 +                    (((s->cr[VGA_CRTC_OVERFLOW] & 1) |
 +                      ((s->cr[VGA_CRTC_OVERFLOW] >> 4) & 2)) << 8)) + 2;
 +    vretr_start_line = s->cr[VGA_CRTC_V_SYNC_START] |
 +        ((((s->cr[VGA_CRTC_OVERFLOW] >> 2) & 1) |
 +          ((s->cr[VGA_CRTC_OVERFLOW] >> 6) & 2)) << 8);
 +    vretr_end_line = s->cr[VGA_CRTC_V_SYNC_END] & 0xf;
 +
 +    clocking_mode = (s->sr[VGA_SEQ_CLOCK_MODE] >> 3) & 1;
 +    clock_sel = (s->msr >> 2) & 3;
 +    dots = (s->msr & 1) ? 8 : 9;
 +
 +    chars_per_sec = clk_hz[clock_sel] / dots;
 +
 +    htotal_chars <<= clocking_mode;
 +
 +    r->total_chars = vtotal_lines * htotal_chars;
 +    if (r->freq) {
 +        r->ticks_per_char = get_ticks_per_sec() / (r->total_chars * r->freq);
 +    } else {
 +        r->ticks_per_char = get_ticks_per_sec() / chars_per_sec;
 +    }
 +
 +    r->vstart = vretr_start_line;
 +    r->vend = r->vstart + vretr_end_line + 1;
 +
 +    r->hstart = hretr_start_char + hretr_skew_chars;
 +    r->hend = r->hstart + hretr_end_char + 1;
 +    r->htotal = htotal_chars;
 +
 +#if 0
 +    div2 = (s->cr[VGA_CRTC_MODE] >> 2) & 1;
 +    sldiv2 = (s->cr[VGA_CRTC_MODE] >> 3) & 1;
 +    printf (
 +        "hz=%f\n"
 +        "htotal = %d\n"
 +        "hretr_start = %d\n"
 +        "hretr_skew = %d\n"
 +        "hretr_end = %d\n"
 +        "vtotal = %d\n"
 +        "vretr_start = %d\n"
 +        "vretr_end = %d\n"
 +        "div2 = %d sldiv2 = %d\n"
 +        "clocking_mode = %d\n"
 +        "clock_sel = %d %d\n"
 +        "dots = %d\n"
 +        "ticks/char = %" PRId64 "\n"
 +        "\n",
 +        (double) get_ticks_per_sec() / (r->ticks_per_char * r->total_chars),
 +        htotal_chars,
 +        hretr_start_char,
 +        hretr_skew_chars,
 +        hretr_end_char,
 +        vtotal_lines,
 +        vretr_start_line,
 +        vretr_end_line,
 +        div2, sldiv2,
 +        clocking_mode,
 +        clock_sel,
 +        clk_hz[clock_sel],
 +        dots,
 +        r->ticks_per_char
 +        );
 +#endif
 +}
 +
 +static uint8_t vga_precise_retrace(VGACommonState *s)
 +{
 +    struct vga_precise_retrace *r = &s->retrace_info.precise;
 +    uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
 +
 +    if (r->total_chars) {
 +        int cur_line, cur_line_char, cur_char;
 +        int64_t cur_tick;
 +
-     int64_t now = qemu_get_clock_ms(vm_clock);
++        cur_tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 +
 +        cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
 +        cur_line = cur_char / r->htotal;
 +
 +        if (cur_line >= r->vstart && cur_line <= r->vend) {
 +            val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
 +        } else {
 +            cur_line_char = cur_char % r->htotal;
 +            if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
 +                val |= ST01_DISP_ENABLE;
 +            }
 +        }
 +
 +        return val;
 +    } else {
 +        return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
 +    }
 +}
 +
 +static uint8_t vga_dumb_retrace(VGACommonState *s)
 +{
 +    return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
 +}
 +
 +typedef void maru_vga_draw_glyph8_func(uint8_t *d, int linesize,
 +                             const uint8_t *font_ptr, int h,
 +                             uint32_t fgcol, uint32_t bgcol);
 +typedef void maru_vga_draw_glyph9_func(uint8_t *d, int linesize,
 +                                  const uint8_t *font_ptr, int h,
 +                                  uint32_t fgcol, uint32_t bgcol, int dup9);
 +typedef void maru_vga_draw_line_func(VGACommonState *s1, uint8_t *d,
 +                                const uint8_t *s, int width);
 +
 +#define DEPTH 8
 +#include "maru_vga_template.h"
 +
 +#define DEPTH 15
 +#include "maru_vga_template.h"
 +
 +#define BGR_FORMAT
 +#define DEPTH 15
 +#include "maru_vga_template.h"
 +
 +#define DEPTH 16
 +#include "maru_vga_template.h"
 +
 +#define BGR_FORMAT
 +#define DEPTH 16
 +#include "maru_vga_template.h"
 +
 +#define DEPTH 32
 +#include "maru_vga_template.h"
 +
 +#define BGR_FORMAT
 +#define DEPTH 32
 +#include "maru_vga_template.h"
 +
 +static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
 +{
 +    unsigned int col;
 +    col = rgb_to_pixel8(r, g, b);
 +    col |= col << 8;
 +    col |= col << 16;
 +    return col;
 +}
 +
 +static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
 +{
 +    unsigned int col;
 +    col = rgb_to_pixel15(r, g, b);
 +    col |= col << 16;
 +    return col;
 +}
 +
 +static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
 +                                          unsigned int b)
 +{
 +    unsigned int col;
 +    col = rgb_to_pixel15bgr(r, g, b);
 +    col |= col << 16;
 +    return col;
 +}
 +
 +static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
 +{
 +    unsigned int col;
 +    col = rgb_to_pixel16(r, g, b);
 +    col |= col << 16;
 +    return col;
 +}
 +
 +static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
 +                                          unsigned int b)
 +{
 +    unsigned int col;
 +    col = rgb_to_pixel16bgr(r, g, b);
 +    col |= col << 16;
 +    return col;
 +}
 +
 +static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
 +{
 +    unsigned int col;
 +    col = rgb_to_pixel32(r, g, b);
 +    return col;
 +}
 +
 +static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
 +{
 +    unsigned int col;
 +    col = rgb_to_pixel32bgr(r, g, b);
 +    return col;
 +}
 +
 +/* return true if the palette was modified */
 +static int update_palette16(VGACommonState *s)
 +{
 +    int full_update, i;
 +    uint32_t v, col, *palette;
 +
 +    full_update = 0;
 +    palette = s->last_palette;
 +    for(i = 0; i < 16; i++) {
 +        v = s->ar[i];
 +        if (s->ar[VGA_ATC_MODE] & 0x80) {
 +            v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xf) << 4) | (v & 0xf);
 +        } else {
 +            v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xc) << 4) | (v & 0x3f);
 +        }
 +        v = v * 3;
 +        col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
 +                              c6_to_8(s->palette[v + 1]),
 +                              c6_to_8(s->palette[v + 2]));
 +        if (col != palette[i]) {
 +            full_update = 1;
 +            palette[i] = col;
 +        }
 +    }
 +    return full_update;
 +}
 +
 +/* return true if the palette was modified */
 +static int update_palette256(VGACommonState *s)
 +{
 +    int full_update, i;
 +    uint32_t v, col, *palette;
 +
 +    full_update = 0;
 +    palette = s->last_palette;
 +    v = 0;
 +    for(i = 0; i < 256; i++) {
 +        if (s->dac_8bit) {
 +          col = s->rgb_to_pixel(s->palette[v],
 +                                s->palette[v + 1],
 +                                s->palette[v + 2]);
 +        } else {
 +          col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
 +                                c6_to_8(s->palette[v + 1]),
 +                                c6_to_8(s->palette[v + 2]));
 +        }
 +        if (col != palette[i]) {
 +            full_update = 1;
 +            palette[i] = col;
 +        }
 +        v += 3;
 +    }
 +    return full_update;
 +}
 +
 +static void vga_get_offsets(VGACommonState *s,
 +                            uint32_t *pline_offset,
 +                            uint32_t *pstart_addr,
 +                            uint32_t *pline_compare)
 +{
 +    uint32_t start_addr, line_offset, line_compare;
 +
 +    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
 +        line_offset = s->vbe_line_offset;
 +        start_addr = s->vbe_start_addr;
 +        line_compare = 65535;
 +    } else {
 +        /* compute line_offset in bytes */
 +        line_offset = s->cr[VGA_CRTC_OFFSET];
 +        line_offset <<= 3;
 +
 +        /* starting address */
 +        start_addr = s->cr[VGA_CRTC_START_LO] |
 +            (s->cr[VGA_CRTC_START_HI] << 8);
 +
 +        /* line compare */
 +        line_compare = s->cr[VGA_CRTC_LINE_COMPARE] |
 +            ((s->cr[VGA_CRTC_OVERFLOW] & 0x10) << 4) |
 +            ((s->cr[VGA_CRTC_MAX_SCAN] & 0x40) << 3);
 +    }
 +    *pline_offset = line_offset;
 +    *pstart_addr = start_addr;
 +    *pline_compare = line_compare;
 +}
 +
 +/* update start_addr and line_offset. Return TRUE if modified */
 +static int update_basic_params(VGACommonState *s)
 +{
 +    int full_update;
 +    uint32_t start_addr, line_offset, line_compare;
 +
 +    full_update = 0;
 +
 +    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
 +
 +    if (line_offset != s->line_offset ||
 +        start_addr != s->start_addr ||
 +        line_compare != s->line_compare) {
 +        s->line_offset = line_offset;
 +        s->start_addr = start_addr;
 +        s->line_compare = line_compare;
 +        full_update = 1;
 +    }
 +    return full_update;
 +}
 +
 +#define NB_DEPTHS 7
 +
 +static inline int get_depth_index(DisplaySurface *s)
 +{
 +    switch (surface_bits_per_pixel(s)) {
 +    default:
 +    case 8:
 +        return 0;
 +    case 15:
 +        return 1;
 +    case 16:
 +        return 2;
 +    case 32:
 +        if (is_surface_bgr(s)) {
 +            return 4;
 +        } else {
 +            return 3;
 +        }
 +    }
 +}
 +
 +static maru_vga_draw_glyph8_func * const maru_vga_draw_glyph8_table[NB_DEPTHS] = {
 +    maru_vga_draw_glyph8_8,
 +    maru_vga_draw_glyph8_16,
 +    maru_vga_draw_glyph8_16,
 +    maru_vga_draw_glyph8_32,
 +    maru_vga_draw_glyph8_32,
 +    maru_vga_draw_glyph8_16,
 +    maru_vga_draw_glyph8_16,
 +};
 +
 +static maru_vga_draw_glyph8_func * const maru_vga_draw_glyph16_table[NB_DEPTHS] = {
 +    maru_vga_draw_glyph16_8,
 +    maru_vga_draw_glyph16_16,
 +    maru_vga_draw_glyph16_16,
 +    maru_vga_draw_glyph16_32,
 +    maru_vga_draw_glyph16_32,
 +    maru_vga_draw_glyph16_16,
 +    maru_vga_draw_glyph16_16,
 +};
 +
 +static maru_vga_draw_glyph9_func * const maru_vga_draw_glyph9_table[NB_DEPTHS] = {
 +    maru_vga_draw_glyph9_8,
 +    maru_vga_draw_glyph9_16,
 +    maru_vga_draw_glyph9_16,
 +    maru_vga_draw_glyph9_32,
 +    maru_vga_draw_glyph9_32,
 +    maru_vga_draw_glyph9_16,
 +    maru_vga_draw_glyph9_16,
 +};
 +
 +static const uint8_t cursor_glyph[32 * 4] = {
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +};
 +
 +static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight,
 +                                    int *pcwidth, int *pcheight)
 +{
 +    int width, cwidth, height, cheight;
 +
 +    /* total width & height */
 +    cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
 +    cwidth = 8;
 +    if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
 +        cwidth = 9;
 +    }
 +    if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
 +        cwidth = 16; /* NOTE: no 18 pixel wide */
 +    }
 +    width = (s->cr[VGA_CRTC_H_DISP] + 1);
 +    if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
 +        /* ugly hack for CGA 160x100x16 - explain me the logic */
 +        height = 100;
 +    } else {
 +        height = s->cr[VGA_CRTC_V_DISP_END] |
 +            ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
 +            ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
 +        height = (height + 1) / cheight;
 +    }
 +
 +    *pwidth = width;
 +    *pheight = height;
 +    *pcwidth = cwidth;
 +    *pcheight = cheight;
 +}
 +
 +typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
 +
 +static rgb_to_pixel_dup_func * const rgb_to_pixel_dup_table[NB_DEPTHS] = {
 +    rgb_to_pixel8_dup,
 +    rgb_to_pixel15_dup,
 +    rgb_to_pixel16_dup,
 +    rgb_to_pixel32_dup,
 +    rgb_to_pixel32bgr_dup,
 +    rgb_to_pixel15bgr_dup,
 +    rgb_to_pixel16bgr_dup,
 +};
 +
 +/*
 + * Text mode update
 + * Missing:
 + * - double scan
 + * - double width
 + * - underline
 + * - flashing
 + */
 +static void vga_draw_text(VGACommonState *s, int full_update)
 +{
 +    DisplaySurface *surface = qemu_console_surface(s->con);
 +    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
 +    int cx_min, cx_max, linesize, x_incr, line, line1;
 +    uint32_t offset, fgcol, bgcol, v, cursor_offset;
 +    uint8_t *d1, *d, *src, *dest, *cursor_ptr;
 +    const uint8_t *font_ptr, *font_base[2];
 +    int dup9, line_offset, depth_index;
 +    uint32_t *palette;
 +    uint32_t *ch_attr_ptr;
 +    maru_vga_draw_glyph8_func *maru_vga_draw_glyph8;
 +    maru_vga_draw_glyph9_func *maru_vga_draw_glyph9;
-             s->cursor_blink_time = qemu_get_clock_ms(vm_clock);
++    int64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
 +
 +    /* compute font data address (in plane 2) */
 +    v = s->sr[VGA_SEQ_CHARACTER_MAP];
 +    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
 +    if (offset != s->font_offsets[0]) {
 +        s->font_offsets[0] = offset;
 +        full_update = 1;
 +    }
 +    font_base[0] = s->vram_ptr + offset;
 +
 +    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
 +    font_base[1] = s->vram_ptr + offset;
 +    if (offset != s->font_offsets[1]) {
 +        s->font_offsets[1] = offset;
 +        full_update = 1;
 +    }
 +    if (s->plane_updated & (1 << 2) || s->chain4_alias) {
 +        /* if the plane 2 was modified since the last display, it
 +           indicates the font may have been modified */
 +        s->plane_updated = 0;
 +        full_update = 1;
 +    }
 +    full_update |= update_basic_params(s);
 +
 +    line_offset = s->line_offset;
 +
 +    vga_get_text_resolution(s, &width, &height, &cw, &cheight);
 +    if ((height * width) <= 1) {
 +        /* better than nothing: exit if transient size is too small */
 +        return;
 +    }
 +    if ((height * width) > CH_ATTR_SIZE) {
 +        /* better than nothing: exit if transient size is too big */
 +        return;
 +    }
 +
 +    if (width != s->last_width || height != s->last_height ||
 +        cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
 +        s->last_scr_width = width * cw;
 +        s->last_scr_height = height * cheight;
 +        qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
 +        surface = qemu_console_surface(s->con);
 +        dpy_text_resize(s->con, width, height);
 +        s->last_depth = 0;
 +        s->last_width = width;
 +        s->last_height = height;
 +        s->last_ch = cheight;
 +        s->last_cw = cw;
 +        full_update = 1;
 +    }
 +    s->rgb_to_pixel =
 +        rgb_to_pixel_dup_table[get_depth_index(surface)];
 +    full_update |= update_palette16(s);
 +    palette = s->last_palette;
 +    x_incr = cw * surface_bytes_per_pixel(surface);
 +
 +    if (full_update) {
 +        s->full_update_text = 1;
 +    }
 +    if (s->full_update_gfx) {
 +        s->full_update_gfx = 0;
 +        full_update |= 1;
 +    }
 +
 +    cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
 +                     s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
 +    if (cursor_offset != s->cursor_offset ||
 +        s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
 +        s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end) {
 +      /* if the cursor position changed, we update the old and new
 +         chars */
 +        if (s->cursor_offset < CH_ATTR_SIZE)
 +            s->last_ch_attr[s->cursor_offset] = -1;
 +        if (cursor_offset < CH_ATTR_SIZE)
 +            s->last_ch_attr[cursor_offset] = -1;
 +        s->cursor_offset = cursor_offset;
 +        s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
 +        s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
 +    }
 +    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
 +    if (now >= s->cursor_blink_time) {
 +        s->cursor_blink_time = now + VGA_TEXT_CURSOR_PERIOD_MS / 2;
 +        s->cursor_visible_phase = !s->cursor_visible_phase;
 +    }
 +
 +    depth_index = get_depth_index(surface);
 +    if (cw == 16)
 +        maru_vga_draw_glyph8 = maru_vga_draw_glyph16_table[depth_index];
 +    else
 +        maru_vga_draw_glyph8 = maru_vga_draw_glyph8_table[depth_index];
 +    maru_vga_draw_glyph9 = maru_vga_draw_glyph9_table[depth_index];
 +
 +    dest = surface_data(surface);
 +    linesize = surface_stride(surface);
 +    ch_attr_ptr = s->last_ch_attr;
 +    line = 0;
 +    offset = s->start_addr * 4;
 +    for(cy = 0; cy < height; cy++) {
 +        d1 = dest;
 +        src = s->vram_ptr + offset;
 +        cx_min = width;
 +        cx_max = -1;
 +        for(cx = 0; cx < width; cx++) {
 +            ch_attr = *(uint16_t *)src;
 +            if (full_update || ch_attr != *ch_attr_ptr || src == cursor_ptr) {
 +                if (cx < cx_min)
 +                    cx_min = cx;
 +                if (cx > cx_max)
 +                    cx_max = cx;
 +                *ch_attr_ptr = ch_attr;
 +#ifdef HOST_WORDS_BIGENDIAN
 +                ch = ch_attr >> 8;
 +                cattr = ch_attr & 0xff;
 +#else
 +                ch = ch_attr & 0xff;
 +                cattr = ch_attr >> 8;
 +#endif
 +                font_ptr = font_base[(cattr >> 3) & 1];
 +                font_ptr += 32 * 4 * ch;
 +                bgcol = palette[cattr >> 4];
 +                fgcol = palette[cattr & 0x0f];
 +                if (cw != 9) {
 +                    maru_vga_draw_glyph8(d1, linesize,
 +                                    font_ptr, cheight, fgcol, bgcol);
 +                } else {
 +                    dup9 = 0;
 +                    if (ch >= 0xb0 && ch <= 0xdf &&
 +                        (s->ar[VGA_ATC_MODE] & 0x04)) {
 +                        dup9 = 1;
 +                    }
 +                    maru_vga_draw_glyph9(d1, linesize,
 +                                    font_ptr, cheight, fgcol, bgcol, dup9);
 +                }
 +                if (src == cursor_ptr &&
 +                    !(s->cr[VGA_CRTC_CURSOR_START] & 0x20) &&
 +                    s->cursor_visible_phase) {
 +                    int line_start, line_last, h;
 +                    /* draw the cursor */
 +                    line_start = s->cr[VGA_CRTC_CURSOR_START] & 0x1f;
 +                    line_last = s->cr[VGA_CRTC_CURSOR_END] & 0x1f;
 +                    /* XXX: check that */
 +                    if (line_last > cheight - 1)
 +                        line_last = cheight - 1;
 +                    if (line_last >= line_start && line_start < cheight) {
 +                        h = line_last - line_start + 1;
 +                        d = d1 + linesize * line_start;
 +                        if (cw != 9) {
 +                            maru_vga_draw_glyph8(d, linesize,
 +                                            cursor_glyph, h, fgcol, bgcol);
 +                        } else {
 +                            maru_vga_draw_glyph9(d, linesize,
 +                                            cursor_glyph, h, fgcol, bgcol, 1);
 +                        }
 +                    }
 +                }
 +            }
 +            d1 += x_incr;
 +            src += 4;
 +            ch_attr_ptr++;
 +        }
 +        if (cx_max != -1) {
 +            dpy_gfx_update(s->con, cx_min * cw, cy * cheight,
 +                           (cx_max - cx_min + 1) * cw, cheight);
 +        }
 +        dest += linesize * cheight;
 +        line1 = line + cheight;
 +        offset += line_offset;
 +        if (line < s->line_compare && line1 >= s->line_compare) {
 +            offset = 0;
 +        }
 +        line = line1;
 +    }
 +}
 +
 +enum {
 +    maru_vga_draw_line2,
 +    maru_vga_draw_line2D2,
 +    maru_vga_draw_line4,
 +    maru_vga_draw_line4D2,
 +    maru_vga_draw_line8D2,
 +    maru_vga_draw_line8,
 +    maru_vga_draw_line15,
 +    maru_vga_draw_line16,
 +    maru_vga_draw_line24,
 +    maru_vga_draw_line32,
 +    maru_vga_draw_line_NB,
 +};
 +
 +static maru_vga_draw_line_func * const maru_vga_draw_line_table[NB_DEPTHS * maru_vga_draw_line_NB] = {
 +    maru_vga_draw_line2_8,
 +    maru_vga_draw_line2_16,
 +    maru_vga_draw_line2_16,
 +    maru_vga_draw_line2_32,
 +    maru_vga_draw_line2_32,
 +    maru_vga_draw_line2_16,
 +    maru_vga_draw_line2_16,
 +
 +    maru_vga_draw_line2d2_8,
 +    maru_vga_draw_line2d2_16,
 +    maru_vga_draw_line2d2_16,
 +    maru_vga_draw_line2d2_32,
 +    maru_vga_draw_line2d2_32,
 +    maru_vga_draw_line2d2_16,
 +    maru_vga_draw_line2d2_16,
 +
 +    maru_vga_draw_line4_8,
 +    maru_vga_draw_line4_16,
 +    maru_vga_draw_line4_16,
 +    maru_vga_draw_line4_32,
 +    maru_vga_draw_line4_32,
 +    maru_vga_draw_line4_16,
 +    maru_vga_draw_line4_16,
 +
 +    maru_vga_draw_line4d2_8,
 +    maru_vga_draw_line4d2_16,
 +    maru_vga_draw_line4d2_16,
 +    maru_vga_draw_line4d2_32,
 +    maru_vga_draw_line4d2_32,
 +    maru_vga_draw_line4d2_16,
 +    maru_vga_draw_line4d2_16,
 +
 +    maru_vga_draw_line8d2_8,
 +    maru_vga_draw_line8d2_16,
 +    maru_vga_draw_line8d2_16,
 +    maru_vga_draw_line8d2_32,
 +    maru_vga_draw_line8d2_32,
 +    maru_vga_draw_line8d2_16,
 +    maru_vga_draw_line8d2_16,
 +
 +    maru_vga_draw_line8_8,
 +    maru_vga_draw_line8_16,
 +    maru_vga_draw_line8_16,
 +    maru_vga_draw_line8_32,
 +    maru_vga_draw_line8_32,
 +    maru_vga_draw_line8_16,
 +    maru_vga_draw_line8_16,
 +
 +    maru_vga_draw_line15_8,
 +    maru_vga_draw_line15_15,
 +    maru_vga_draw_line15_16,
 +    maru_vga_draw_line15_32,
 +    maru_vga_draw_line15_32bgr,
 +    maru_vga_draw_line15_15bgr,
 +    maru_vga_draw_line15_16bgr,
 +
 +    maru_vga_draw_line16_8,
 +    maru_vga_draw_line16_15,
 +    maru_vga_draw_line16_16,
 +    maru_vga_draw_line16_32,
 +    maru_vga_draw_line16_32bgr,
 +    maru_vga_draw_line16_15bgr,
 +    maru_vga_draw_line16_16bgr,
 +
 +    maru_vga_draw_line24_8,
 +    maru_vga_draw_line24_15,
 +    maru_vga_draw_line24_16,
 +    maru_vga_draw_line24_32,
 +    maru_vga_draw_line24_32bgr,
 +    maru_vga_draw_line24_15bgr,
 +    maru_vga_draw_line24_16bgr,
 +
 +    maru_vga_draw_line32_8,
 +    maru_vga_draw_line32_15,
 +    maru_vga_draw_line32_16,
 +    maru_vga_draw_line32_32,
 +    maru_vga_draw_line32_32bgr,
 +    maru_vga_draw_line32_15bgr,
 +    maru_vga_draw_line32_16bgr,
 +};
 +
 +static int vga_get_bpp(VGACommonState *s)
 +{
 +    int ret;
 +
 +    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
 +        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
 +    } else {
 +        ret = 0;
 +    }
 +    return ret;
 +}
 +
 +static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
 +{
 +    int width, height;
 +
 +    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
 +        width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
 +        height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
 +    } else {
 +        width = (s->cr[VGA_CRTC_H_DISP] + 1) * 8;
 +        height = s->cr[VGA_CRTC_V_DISP_END] |
 +            ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
 +            ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
 +        height = (height + 1);
 +    }
 +    *pwidth = width;
 +    *pheight = height;
 +}
 +
 +/*
 + * graphic modes
 + */
 +static void vga_draw_graphic(VGACommonState *s, int full_update)
 +{
 +    DisplaySurface *surface = qemu_console_surface(s->con);
 +    int y1, y, update, linesize, y_start, double_scan, mask, depth;
 +    int width, height, shift_control, line_offset, bwidth, bits;
 +    ram_addr_t page0, page1, page_min, page_max;
 +    int disp_width, multi_scan, multi_run;
 +    uint8_t *d;
 +    uint32_t v, addr1, addr;
 +    maru_vga_draw_line_func *maru_vga_draw_line;
 +#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
 +    static const bool byteswap = false;
 +#else
 +    static const bool byteswap = true;
 +#endif
 +
 +    full_update |= update_basic_params(s);
 +
 +    if (!full_update)
 +        vga_sync_dirty_bitmap(s);
 +
 +    s->get_resolution(s, &width, &height);
 +    disp_width = width;
 +
 +    shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
 +    double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
 +    if (shift_control != 1) {
 +        multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan)
 +            - 1;
 +    } else {
 +        /* in CGA modes, multi_scan is ignored */
 +        /* XXX: is it correct ? */
 +        multi_scan = double_scan;
 +    }
 +    multi_run = multi_scan;
 +    if (shift_control != s->shift_control ||
 +        double_scan != s->double_scan) {
 +        full_update = 1;
 +        s->shift_control = shift_control;
 +        s->double_scan = double_scan;
 +    }
 +
 +    if (shift_control == 0) {
 +        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
 +            disp_width <<= 1;
 +        }
 +    } else if (shift_control == 1) {
 +        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
 +            disp_width <<= 1;
 +        }
 +    }
 +
 +    depth = s->get_bpp(s);
 +    if (s->line_offset != s->last_line_offset ||
 +        disp_width != s->last_width ||
 +        height != s->last_height ||
 +        s->last_depth != depth) {
 +        if (depth == 32 || (depth == 16 && !byteswap)) {
 +#ifdef MARU_VGA /* create new sufrace by g_new0 in MARU VGA */
 +            TRACE("create the display surface\n");
 +            surface = qemu_create_displaysurface(disp_width, height);
 +#else /* MARU_VGA */
 +            surface = qemu_create_displaysurface_from(disp_width,
 +                    height, depth, s->line_offset,
 +                    s->vram_ptr + (s->start_addr * 4), byteswap);
 +#endif /* MARU_VGA */
 +            dpy_gfx_replace_surface(s->con, surface);
 +        } else {
 +            qemu_console_resize(s->con, disp_width, height);
 +            surface = qemu_console_surface(s->con);
 +        }
 +        s->last_scr_width = disp_width;
 +        s->last_scr_height = height;
 +        s->last_width = disp_width;
 +        s->last_height = height;
 +        s->last_line_offset = s->line_offset;
 +        s->last_depth = depth;
 +        full_update = 1;
 +    } else if (is_buffer_shared(surface) &&
 +               (full_update || surface_data(surface) != s->vram_ptr
 +                + (s->start_addr * 4))) {
 +        DisplaySurface *surface;
 +        surface = qemu_create_displaysurface_from(disp_width,
 +                height, depth, s->line_offset,
 +                s->vram_ptr + (s->start_addr * 4), byteswap);
 +        dpy_gfx_replace_surface(s->con, surface);
 +    }
 +
 +    s->rgb_to_pixel =
 +        rgb_to_pixel_dup_table[get_depth_index(surface)];
 +
 +    if (shift_control == 0) {
 +        full_update |= update_palette16(s);
 +        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
 +            v = maru_vga_draw_line4D2;
 +        } else {
 +            v = maru_vga_draw_line4;
 +        }
 +        bits = 4;
 +    } else if (shift_control == 1) {
 +        full_update |= update_palette16(s);
 +        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
 +            v = maru_vga_draw_line2D2;
 +        } else {
 +            v = maru_vga_draw_line2;
 +        }
 +        bits = 4;
 +    } else {
 +        switch(s->get_bpp(s)) {
 +        default:
 +        case 0:
 +            full_update |= update_palette256(s);
 +            v = maru_vga_draw_line8D2;
 +            bits = 4;
 +            break;
 +        case 8:
 +            full_update |= update_palette256(s);
 +            v = maru_vga_draw_line8;
 +            bits = 8;
 +            break;
 +        case 15:
 +            v = maru_vga_draw_line15;
 +            bits = 16;
 +            break;
 +        case 16:
 +            v = maru_vga_draw_line16;
 +            bits = 16;
 +            break;
 +        case 24:
 +            v = maru_vga_draw_line24;
 +            bits = 24;
 +            break;
 +        case 32:
 +            v = maru_vga_draw_line32;
 +            bits = 32;
 +            break;
 +        }
 +    }
 +    maru_vga_draw_line = maru_vga_draw_line_table[v * NB_DEPTHS +
 +                                        get_depth_index(surface)];
 +
 +    if (!is_buffer_shared(surface) && s->cursor_invalidate) {
 +        s->cursor_invalidate(s);
 +    }
 +
 +    line_offset = s->line_offset;
 +#if 0
 +    printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
 +           width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE],
 +           s->line_compare, s->sr[VGA_SEQ_CLOCK_MODE]);
 +#endif
 +    addr1 = (s->start_addr * 4);
 +    bwidth = (width * bits + 7) / 8;
 +    y_start = -1;
 +    page_min = -1;
 +    page_max = 0;
 +    d = surface_data(surface);
 +    linesize = surface_stride(surface);
 +    y1 = 0;
 +    for(y = 0; y < height; y++) {
 +        addr = addr1;
 +        if (!(s->cr[VGA_CRTC_MODE] & 1)) {
 +            int shift;
 +            /* CGA compatibility handling */
 +            shift = 14 + ((s->cr[VGA_CRTC_MODE] >> 6) & 1);
 +            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
 +        }
 +        if (!(s->cr[VGA_CRTC_MODE] & 2)) {
 +            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
 +        }
 +        update = full_update;
 +        page0 = addr;
 +        page1 = addr + bwidth - 1;
 +        update |= memory_region_get_dirty(&s->vram, page0, page1 - page0,
 +                                          DIRTY_MEMORY_VGA);
 +        /* explicit invalidation for the hardware cursor */
 +        update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
 +#ifdef MARU_VGA /* needs full update */
 +        update |= 1;
 +#endif
 +        if (update) {
 +            if (y_start < 0)
 +                y_start = y;
 +            if (page0 < page_min)
 +                page_min = page0;
 +            if (page1 > page_max)
 +                page_max = page1;
 +            if (!(is_buffer_shared(surface))) {
 +                maru_vga_draw_line(s, d, s->vram_ptr + addr, width);
 +                if (s->cursor_draw_line)
 +                    s->cursor_draw_line(s, d, y);
 +            }
 +        } else {
 +            if (y_start >= 0) {
 +                /* flush to display */
 +                dpy_gfx_update(s->con, 0, y_start,
 +                               disp_width, y - y_start);
 +                y_start = -1;
 +            }
 +        }
 +        if (!multi_run) {
 +            mask = (s->cr[VGA_CRTC_MODE] & 3) ^ 3;
 +            if ((y1 & mask) == mask)
 +                addr1 += line_offset;
 +            y1++;
 +            multi_run = multi_scan;
 +        } else {
 +            multi_run--;
 +        }
 +        /* line compare acts on the displayed lines */
 +        if (y == s->line_compare)
 +            addr1 = 0;
 +        d += linesize;
 +    }
 +    if (y_start >= 0) {
 +        /* flush to display */
 +        dpy_gfx_update(s->con, 0, y_start,
 +                       disp_width, y - y_start);
 +    }
 +    /* reset modified pages */
 +    if (page_max >= page_min) {
 +        memory_region_reset_dirty(&s->vram,
 +                                  page_min,
 +                                  page_max - page_min,
 +                                  DIRTY_MEMORY_VGA);
 +    }
 +    memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
 +}
 +
 +static void vga_draw_blank(VGACommonState *s, int full_update)
 +{
 +    DisplaySurface *surface = qemu_console_surface(s->con);
 +    int i, w, val;
 +    uint8_t *d;
 +
 +    if (!full_update)
 +        return;
 +    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
 +        return;
 +
 +    s->rgb_to_pixel =
 +        rgb_to_pixel_dup_table[get_depth_index(surface)];
 +    if (surface_bits_per_pixel(surface) == 8) {
 +        val = s->rgb_to_pixel(0, 0, 0);
 +    } else {
 +        val = 0;
 +    }
 +    w = s->last_scr_width * surface_bytes_per_pixel(surface);
 +    d = surface_data(surface);
 +    for(i = 0; i < s->last_scr_height; i++) {
 +        memset(d, val, w);
 +        d += surface_stride(surface);
 +    }
 +    dpy_gfx_update(s->con, 0, 0,
 +                   s->last_scr_width, s->last_scr_height);
 +}
 +
 +#define GMODE_TEXT     0
 +#define GMODE_GRAPH    1
 +#define GMODE_BLANK 2
 +
 +static void vga_update_display(void *opaque)
 +{
 +    VGACommonState *s = opaque;
 +    DisplaySurface *surface = qemu_console_surface(s->con);
 +    int full_update, graphic_mode;
 +
 +    qemu_flush_coalesced_mmio_buffer();
 +
 +    if (surface_bits_per_pixel(surface) == 0) {
 +        /* nothing to do */
 +    } else {
 +        full_update = 0;
 +        if (!(s->ar_index & 0x20)) {
 +            graphic_mode = GMODE_BLANK;
 +        } else {
 +            graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
 +        }
 +        if (graphic_mode != s->graphic_mode) {
 +            s->graphic_mode = graphic_mode;
++            s->cursor_blink_time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
 +            full_update = 1;
 +        }
 +        switch(graphic_mode) {
 +        case GMODE_TEXT:
 +            vga_draw_text(s, full_update);
 +            break;
 +        case GMODE_GRAPH:
 +            vga_draw_graphic(s, full_update);
 +            break;
 +        case GMODE_BLANK:
 +        default:
 +            vga_draw_blank(s, full_update);
 +            break;
 +        }
 +    }
 +}
 +
 +/* force a full display refresh */
 +static void vga_invalidate_display(void *opaque)
 +{
 +    VGACommonState *s = opaque;
 +
 +    s->last_width = -1;
 +    s->last_height = -1;
 +}
 +
 +#define TEXTMODE_X(x)    ((x) % width)
 +#define TEXTMODE_Y(x)    ((x) / width)
 +#define VMEM2CHTYPE(v)   ((v & 0xff0007ff) | \
 +        ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
 +/* relay text rendering to the display driver
 + * instead of doing a full vga_update_display() */
 +static void vga_update_text(void *opaque, console_ch_t *chardata)
 +{
 +    VGACommonState *s =  opaque;
 +    int graphic_mode, i, cursor_offset, cursor_visible;
 +    int cw, cheight, width, height, size, c_min, c_max;
 +    uint32_t *src;
 +    console_ch_t *dst, val;
 +    char msg_buffer[80];
 +    int full_update = 0;
 +
 +    qemu_flush_coalesced_mmio_buffer();
 +
 +    if (!(s->ar_index & 0x20)) {
 +        graphic_mode = GMODE_BLANK;
 +    } else {
 +        graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
 +    }
 +    if (graphic_mode != s->graphic_mode) {
 +        s->graphic_mode = graphic_mode;
 +        full_update = 1;
 +    }
 +    if (s->last_width == -1) {
 +        s->last_width = 0;
 +        full_update = 1;
 +    }
 +
 +    switch (graphic_mode) {
 +    case GMODE_TEXT:
 +        /* TODO: update palette */
 +        full_update |= update_basic_params(s);
 +
 +        /* total width & height */
 +        cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
 +        cw = 8;
 +        if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
 +            cw = 9;
 +        }
 +        if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
 +            cw = 16; /* NOTE: no 18 pixel wide */
 +        }
 +        width = (s->cr[VGA_CRTC_H_DISP] + 1);
 +        if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
 +            /* ugly hack for CGA 160x100x16 - explain me the logic */
 +            height = 100;
 +        } else {
 +            height = s->cr[VGA_CRTC_V_DISP_END] |
 +                ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
 +                ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
 +            height = (height + 1) / cheight;
 +        }
 +
 +        size = (height * width);
 +        if (size > CH_ATTR_SIZE) {
 +            if (!full_update)
 +                return;
 +
 +            snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
 +                     width, height);
 +            break;
 +        }
 +
 +        if (width != s->last_width || height != s->last_height ||
 +            cw != s->last_cw || cheight != s->last_ch) {
 +            s->last_scr_width = width * cw;
 +            s->last_scr_height = height * cheight;
 +            qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
 +            dpy_text_resize(s->con, width, height);
 +            s->last_depth = 0;
 +            s->last_width = width;
 +            s->last_height = height;
 +            s->last_ch = cheight;
 +            s->last_cw = cw;
 +            full_update = 1;
 +        }
 +
 +        if (full_update) {
 +            s->full_update_gfx = 1;
 +        }
 +        if (s->full_update_text) {
 +            s->full_update_text = 0;
 +            full_update |= 1;
 +        }
 +
 +        /* Update "hardware" cursor */
 +        cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
 +                         s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
 +        if (cursor_offset != s->cursor_offset ||
 +            s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
 +            s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) {
 +            cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
 +            if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
 +                dpy_text_cursor(s->con,
 +                                TEXTMODE_X(cursor_offset),
 +                                TEXTMODE_Y(cursor_offset));
 +            else
 +                dpy_text_cursor(s->con, -1, -1);
 +            s->cursor_offset = cursor_offset;
 +            s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
 +            s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
 +        }
 +
 +        src = (uint32_t *) s->vram_ptr + s->start_addr;
 +        dst = chardata;
 +
 +        if (full_update) {
 +            for (i = 0; i < size; src ++, dst ++, i ++)
 +                console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
 +
 +            dpy_text_update(s->con, 0, 0, width, height);
 +        } else {
 +            c_max = 0;
 +
 +            for (i = 0; i < size; src ++, dst ++, i ++) {
 +                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
 +                if (*dst != val) {
 +                    *dst = val;
 +                    c_max = i;
 +                    break;
 +                }
 +            }
 +            c_min = i;
 +            for (; i < size; src ++, dst ++, i ++) {
 +                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
 +                if (*dst != val) {
 +                    *dst = val;
 +                    c_max = i;
 +                }
 +            }
 +
 +            if (c_min <= c_max) {
 +                i = TEXTMODE_Y(c_min);
 +                dpy_text_update(s->con, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
 +            }
 +        }
 +
 +        return;
 +    case GMODE_GRAPH:
 +        if (!full_update)
 +            return;
 +
 +        s->get_resolution(s, &width, &height);
 +        snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
 +                 width, height);
 +        break;
 +    case GMODE_BLANK:
 +    default:
 +        if (!full_update)
 +            return;
 +
 +        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
 +        break;
 +    }
 +
 +    /* Display a message */
 +    s->last_width = 60;
 +    s->last_height = height = 3;
 +    dpy_text_cursor(s->con, -1, -1);
 +    dpy_text_resize(s->con, s->last_width, height);
 +
 +    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
 +        console_write_ch(dst ++, ' ');
 +
 +    size = strlen(msg_buffer);
 +    width = (s->last_width - size) / 2;
 +    dst = chardata + s->last_width + width;
 +    for (i = 0; i < size; i ++)
 +        console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
 +
 +    dpy_text_update(s->con, 0, 0, s->last_width, height);
 +}
 +
 +static const GraphicHwOps vga_ops = {
 +    .invalidate  = vga_invalidate_display,
 +    .gfx_update  = vga_update_display,
 +    .text_update = vga_update_text,
 +};
 +
 +void maru_vga_common_init(VGACommonState *s, Object *obj)
 +{
 +    int i, j, v, b;
 +
 +    for(i = 0;i < 256; i++) {
 +        v = 0;
 +        for(j = 0; j < 8; j++) {
 +            v |= ((i >> j) & 1) << (j * 4);
 +        }
 +        expand4[i] = v;
 +
 +        v = 0;
 +        for(j = 0; j < 4; j++) {
 +            v |= ((i >> (2 * j)) & 3) << (j * 4);
 +        }
 +        expand2[i] = v;
 +    }
 +    for(i = 0; i < 16; i++) {
 +        v = 0;
 +        for(j = 0; j < 4; j++) {
 +            b = ((i >> j) & 1);
 +            v |= b << (2 * j);
 +            v |= b << (2 * j + 1);
 +        }
 +        expand4to8[i] = v;
 +    }
 +
 +    /* valid range: 1 MB -> 256 MB */
 +    s->vram_size = 1024 * 1024;
 +    while (s->vram_size < (s->vram_size_mb << 20) &&
 +           s->vram_size < (256 << 20)) {
 +        s->vram_size <<= 1;
 +    }
 +    s->vram_size_mb = s->vram_size >> 20;
 +
 +    s->is_vbe_vmstate = 1;
 +    memory_region_init_ram(&s->vram, obj, "maru_vga.vram", s->vram_size);
 +    vmstate_register_ram_global(&s->vram);
 +    xen_register_framebuffer(&s->vram);
 +    s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
 +    s->get_bpp = vga_get_bpp;
 +    s->get_offsets = vga_get_offsets;
 +    s->get_resolution = vga_get_resolution;
 +    s->hw_ops = &vga_ops;
 +    switch (vga_retrace_method) {
 +    case VGA_RETRACE_DUMB:
 +        s->retrace = vga_dumb_retrace;
 +        s->update_retrace_info = vga_dumb_update_retrace_info;
 +        break;
 +
 +    case VGA_RETRACE_PRECISE:
 +        s->retrace = vga_precise_retrace;
 +        s->update_retrace_info = vga_precise_update_retrace_info;
 +        break;
 +    }
 +    vga_dirty_log_start(s);
 +    TRACE("%s\n", __func__);
 +}
 +
 +void maru_vga_common_fini(void)
 +{
 +    /* do nothing */
 +    TRACE("%s\n", __func__);
 +}
index 126036e,0000000..8772b9e
mode 100644,000000..100644
--- /dev/null
@@@ -1,465 -1,0 +1,465 @@@
-         cpu_to_32wu((uint32_t *)d, (dmask16[(font_data >> 4)] & xorcol) ^ bgcol);
 +/*
 + *  vga device
 + * Based on qemu/hw/vga_template.h
 + *
 + * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
 + *
 + * Contact:
 + * GiWoong Kim <giwoong.kim@samsung.com>
 + * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
 + * Hyunjun Son
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + */
 +
 +#if DEPTH == 8
 +#define BPP 1
 +#define PIXEL_TYPE uint8_t
 +#elif DEPTH == 15 || DEPTH == 16
 +#define BPP 2
 +#define PIXEL_TYPE uint16_t
 +#elif DEPTH == 32
 +#define BPP 4
 +#define PIXEL_TYPE uint32_t
 +#else
 +#error unsupport depth
 +#endif
 +
 +#ifdef BGR_FORMAT
 +#define PIXEL_NAME glue(DEPTH, bgr)
 +#else
 +#define PIXEL_NAME DEPTH
 +#endif /* BGR_FORMAT */
 +
 +#if DEPTH != 15 && !defined(BGR_FORMAT)
 +
 +static inline void glue(maru_vga_draw_glyph_line_, DEPTH)(uint8_t *d,
 +                                                     uint32_t font_data,
 +                                                     uint32_t xorcol,
 +                                                     uint32_t bgcol)
 +{
 +#if BPP == 1
 +        ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
 +#elif BPP == 2
 +        ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
 +#else
 +        ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
 +#endif
 +}
 +
 +static void glue(maru_vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize,
 +                                          const uint8_t *font_ptr, int h,
 +                                          uint32_t fgcol, uint32_t bgcol)
 +{
 +    uint32_t font_data, xorcol;
 +
 +    xorcol = bgcol ^ fgcol;
 +    do {
 +        font_data = font_ptr[0];
 +        glue(maru_vga_draw_glyph_line_, DEPTH)(d, font_data, xorcol, bgcol);
 +        font_ptr += 4;
 +        d += linesize;
 +    } while (--h);
 +}
 +
 +static void glue(maru_vga_draw_glyph16_, DEPTH)(uint8_t *d, int linesize,
 +                                          const uint8_t *font_ptr, int h,
 +                                          uint32_t fgcol, uint32_t bgcol)
 +{
 +    uint32_t font_data, xorcol;
 +
 +    xorcol = bgcol ^ fgcol;
 +    do {
 +        font_data = font_ptr[0];
 +        glue(maru_vga_draw_glyph_line_, DEPTH)(d,
 +                                          expand4to8[font_data >> 4],
 +                                          xorcol, bgcol);
 +        glue(maru_vga_draw_glyph_line_, DEPTH)(d + 8 * BPP,
 +                                          expand4to8[font_data & 0x0f],
 +                                          xorcol, bgcol);
 +        font_ptr += 4;
 +        d += linesize;
 +    } while (--h);
 +}
 +
 +static void glue(maru_vga_draw_glyph9_, DEPTH)(uint8_t *d, int linesize,
 +                                          const uint8_t *font_ptr, int h,
 +                                          uint32_t fgcol, uint32_t bgcol, int dup9)
 +{
 +    uint32_t font_data, xorcol, v;
 +
 +    xorcol = bgcol ^ fgcol;
 +    do {
 +        font_data = font_ptr[0];
 +#if BPP == 1
-         cpu_to_32wu(((uint32_t *)d)+1, v);
++        stl_p((uint32_t *)d, (dmask16[(font_data >> 4)] & xorcol) ^ bgcol);
 +        v = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
-         cpu_to_32wu(((uint32_t *)d)+0, (dmask4[(font_data >> 6)] & xorcol) ^ bgcol);
-         cpu_to_32wu(((uint32_t *)d)+1, (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol);
-         cpu_to_32wu(((uint32_t *)d)+2, (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol);
++        stl_p(((uint32_t *)d)+1, v);
 +        if (dup9)
 +            ((uint8_t *)d)[8] = v >> (24 * (1 - BIG));
 +        else
 +            ((uint8_t *)d)[8] = bgcol;
 +
 +#elif BPP == 2
-         cpu_to_32wu(((uint32_t *)d)+3, v);
++        stl_p(((uint32_t *)d)+0, (dmask4[(font_data >> 6)] & xorcol) ^ bgcol);
++        stl_p(((uint32_t *)d)+1, (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol);
++        stl_p(((uint32_t *)d)+2, (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol);
 +        v = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
++        stl_p(((uint32_t *)d)+3, v);
 +        if (dup9)
 +            ((uint16_t *)d)[8] = v >> (16 * (1 - BIG));
 +        else
 +            ((uint16_t *)d)[8] = bgcol;
 +#else
 +        ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
 +        v = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[7] = v;
 +        if (dup9)
 +            ((uint32_t *)d)[8] = v;
 +        else
 +            ((uint32_t *)d)[8] = bgcol;
 +#endif
 +        font_ptr += 4;
 +        d += linesize;
 +    } while (--h);
 +}
 +
 +/*
 + * 4 color mode
 + */
 +static void glue(maru_vga_draw_line2_, DEPTH)(VGACommonState *s1, uint8_t *d,
 +                                         const uint8_t *s, int width)
 +{
 +    uint32_t plane_mask, *palette, data, v;
 +    int x;
 +
 +    palette = s1->last_palette;
 +    plane_mask = mask16[s1->ar[0x12] & 0xf];
 +    width >>= 3;
 +    for(x = 0; x < width; x++) {
 +        data = ((uint32_t *)s)[0];
 +        data &= plane_mask;
 +        v = expand2[GET_PLANE(data, 0)];
 +        v |= expand2[GET_PLANE(data, 2)] << 2;
 +        ((PIXEL_TYPE *)d)[0] = palette[v >> 12];
 +        ((PIXEL_TYPE *)d)[1] = palette[(v >> 8) & 0xf];
 +        ((PIXEL_TYPE *)d)[2] = palette[(v >> 4) & 0xf];
 +        ((PIXEL_TYPE *)d)[3] = palette[(v >> 0) & 0xf];
 +
 +        v = expand2[GET_PLANE(data, 1)];
 +        v |= expand2[GET_PLANE(data, 3)] << 2;
 +        ((PIXEL_TYPE *)d)[4] = palette[v >> 12];
 +        ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf];
 +        ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf];
 +        ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf];
 +        d += BPP * 8;
 +        s += 4;
 +    }
 +}
 +
 +#if BPP == 1
 +#define PUT_PIXEL2(d, n, v) ((uint16_t *)d)[(n)] = (v)
 +#elif BPP == 2
 +#define PUT_PIXEL2(d, n, v) ((uint32_t *)d)[(n)] = (v)
 +#else
 +#define PUT_PIXEL2(d, n, v) \
 +((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v)
 +#endif
 +
 +/*
 + * 4 color mode, dup2 horizontal
 + */
 +static void glue(maru_vga_draw_line2d2_, DEPTH)(VGACommonState *s1, uint8_t *d,
 +                                           const uint8_t *s, int width)
 +{
 +    uint32_t plane_mask, *palette, data, v;
 +    int x;
 +
 +    palette = s1->last_palette;
 +    plane_mask = mask16[s1->ar[0x12] & 0xf];
 +    width >>= 3;
 +    for(x = 0; x < width; x++) {
 +        data = ((uint32_t *)s)[0];
 +        data &= plane_mask;
 +        v = expand2[GET_PLANE(data, 0)];
 +        v |= expand2[GET_PLANE(data, 2)] << 2;
 +        PUT_PIXEL2(d, 0, palette[v >> 12]);
 +        PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]);
 +        PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]);
 +        PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]);
 +
 +        v = expand2[GET_PLANE(data, 1)];
 +        v |= expand2[GET_PLANE(data, 3)] << 2;
 +        PUT_PIXEL2(d, 4, palette[v >> 12]);
 +        PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
 +        PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
 +        PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
 +        d += BPP * 16;
 +        s += 4;
 +    }
 +}
 +
 +/*
 + * 16 color mode
 + */
 +static void glue(maru_vga_draw_line4_, DEPTH)(VGACommonState *s1, uint8_t *d,
 +                                         const uint8_t *s, int width)
 +{
 +    uint32_t plane_mask, data, v, *palette;
 +    int x;
 +
 +    palette = s1->last_palette;
 +    plane_mask = mask16[s1->ar[0x12] & 0xf];
 +    width >>= 3;
 +    for(x = 0; x < width; x++) {
 +        data = ((uint32_t *)s)[0];
 +        data &= plane_mask;
 +        v = expand4[GET_PLANE(data, 0)];
 +        v |= expand4[GET_PLANE(data, 1)] << 1;
 +        v |= expand4[GET_PLANE(data, 2)] << 2;
 +        v |= expand4[GET_PLANE(data, 3)] << 3;
 +        ((PIXEL_TYPE *)d)[0] = palette[v >> 28];
 +        ((PIXEL_TYPE *)d)[1] = palette[(v >> 24) & 0xf];
 +        ((PIXEL_TYPE *)d)[2] = palette[(v >> 20) & 0xf];
 +        ((PIXEL_TYPE *)d)[3] = palette[(v >> 16) & 0xf];
 +        ((PIXEL_TYPE *)d)[4] = palette[(v >> 12) & 0xf];
 +        ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf];
 +        ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf];
 +        ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf];
 +        d += BPP * 8;
 +        s += 4;
 +    }
 +}
 +
 +/*
 + * 16 color mode, dup2 horizontal
 + */
 +static void glue(maru_vga_draw_line4d2_, DEPTH)(VGACommonState *s1, uint8_t *d,
 +                                           const uint8_t *s, int width)
 +{
 +    uint32_t plane_mask, data, v, *palette;
 +    int x;
 +
 +    palette = s1->last_palette;
 +    plane_mask = mask16[s1->ar[0x12] & 0xf];
 +    width >>= 3;
 +    for(x = 0; x < width; x++) {
 +        data = ((uint32_t *)s)[0];
 +        data &= plane_mask;
 +        v = expand4[GET_PLANE(data, 0)];
 +        v |= expand4[GET_PLANE(data, 1)] << 1;
 +        v |= expand4[GET_PLANE(data, 2)] << 2;
 +        v |= expand4[GET_PLANE(data, 3)] << 3;
 +        PUT_PIXEL2(d, 0, palette[v >> 28]);
 +        PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]);
 +        PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]);
 +        PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]);
 +        PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]);
 +        PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
 +        PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
 +        PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
 +        d += BPP * 16;
 +        s += 4;
 +    }
 +}
 +
 +/*
 + * 256 color mode, double pixels
 + *
 + * XXX: add plane_mask support (never used in standard VGA modes)
 + */
 +static void glue(maru_vga_draw_line8d2_, DEPTH)(VGACommonState *s1, uint8_t *d,
 +                                           const uint8_t *s, int width)
 +{
 +    uint32_t *palette;
 +    int x;
 +
 +    palette = s1->last_palette;
 +    width >>= 3;
 +    for(x = 0; x < width; x++) {
 +        PUT_PIXEL2(d, 0, palette[s[0]]);
 +        PUT_PIXEL2(d, 1, palette[s[1]]);
 +        PUT_PIXEL2(d, 2, palette[s[2]]);
 +        PUT_PIXEL2(d, 3, palette[s[3]]);
 +        d += BPP * 8;
 +        s += 4;
 +    }
 +}
 +
 +/*
 + * standard 256 color mode
 + *
 + * XXX: add plane_mask support (never used in standard VGA modes)
 + */
 +static void glue(maru_vga_draw_line8_, DEPTH)(VGACommonState *s1, uint8_t *d,
 +                                         const uint8_t *s, int width)
 +{
 +    uint32_t *palette;
 +    int x;
 +
 +    palette = s1->last_palette;
 +    width >>= 3;
 +    for(x = 0; x < width; x++) {
 +        ((PIXEL_TYPE *)d)[0] = palette[s[0]];
 +        ((PIXEL_TYPE *)d)[1] = palette[s[1]];
 +        ((PIXEL_TYPE *)d)[2] = palette[s[2]];
 +        ((PIXEL_TYPE *)d)[3] = palette[s[3]];
 +        ((PIXEL_TYPE *)d)[4] = palette[s[4]];
 +        ((PIXEL_TYPE *)d)[5] = palette[s[5]];
 +        ((PIXEL_TYPE *)d)[6] = palette[s[6]];
 +        ((PIXEL_TYPE *)d)[7] = palette[s[7]];
 +        d += BPP * 8;
 +        s += 8;
 +    }
 +}
 +
 +#endif /* DEPTH != 15 */
 +
 +
 +/* XXX: optimize */
 +
 +/*
 + * 15 bit color
 + */
 +static void glue(maru_vga_draw_line15_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
 +                                          const uint8_t *s, int width)
 +{
 +#if DEPTH == 15 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
 +    memcpy(d, s, width * 2);
 +#else
 +    int w;
 +    uint32_t v, r, g, b;
 +
 +    w = width;
 +    do {
 +        v = lduw_raw((void *)s);
 +        r = (v >> 7) & 0xf8;
 +        g = (v >> 2) & 0xf8;
 +        b = (v << 3) & 0xf8;
 +        ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
 +        s += 2;
 +        d += BPP;
 +    } while (--w != 0);
 +#endif
 +}
 +
 +/*
 + * 16 bit color
 + */
 +static void glue(maru_vga_draw_line16_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
 +                                          const uint8_t *s, int width)
 +{
 +#if DEPTH == 16 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
 +    memcpy(d, s, width * 2);
 +#else
 +    int w;
 +    uint32_t v, r, g, b;
 +
 +    w = width;
 +    do {
 +        v = lduw_raw((void *)s);
 +        r = (v >> 8) & 0xf8;
 +        g = (v >> 3) & 0xfc;
 +        b = (v << 3) & 0xf8;
 +        ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
 +        s += 2;
 +        d += BPP;
 +    } while (--w != 0);
 +#endif
 +}
 +
 +/*
 + * 24 bit color
 + */
 +static void glue(maru_vga_draw_line24_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
 +                                          const uint8_t *s, int width)
 +{
 +    int w;
 +    uint32_t r, g, b;
 +
 +    w = width;
 +    do {
 +#if defined(TARGET_WORDS_BIGENDIAN)
 +        r = s[0];
 +        g = s[1];
 +        b = s[2];
 +#else
 +        b = s[0];
 +        g = s[1];
 +        r = s[2];
 +#endif
 +        ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
 +        s += 3;
 +        d += BPP;
 +    } while (--w != 0);
 +}
 +
 +/*
 + * 32 bit color
 + */
 +static void glue(maru_vga_draw_line32_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
 +                                          const uint8_t *s, int width)
 +{
 +#if DEPTH == 32 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) && !defined(BGR_FORMAT)
 +    memcpy(d, s, width * 4);
 +#else
 +    int w;
 +    uint32_t r, g, b;
 +
 +    w = width;
 +    do {
 +#if defined(TARGET_WORDS_BIGENDIAN)
 +        r = s[1];
 +        g = s[2];
 +        b = s[3];
 +#else
 +        b = s[0];
 +        g = s[1];
 +        r = s[2];
 +#endif
 +        ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
 +        s += 4;
 +        d += BPP;
 +    } while (--w != 0);
 +#endif
 +}
 +
 +#undef PUT_PIXEL2
 +#undef DEPTH
 +#undef BPP
 +#undef PIXEL_TYPE
 +#undef PIXEL_NAME
 +#undef BGR_FORMAT
index 5b37ebf,0000000..b3f1cff
mode 100644,000000..100644
--- /dev/null
@@@ -1,892 -1,0 +1,893 @@@
 +/*
 + * SDL_WINDOWID hack
 + *
 + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
 + *
 + * Contact:
 + * Jinhyung Jo <jinhyung.jo@samsung.com>
 + * GiWoong Kim <giwoong.kim@samsung.com>
 + * SeokYeon Hwang <syeon.hwang@samsung.com>
 + * YeongKyoon Lee <yeongkyoon.lee@samsung.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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + */
 +
 +
 +#include <pthread.h>
 +#include <math.h>
 +#include <png.h>
 +#include "ui/console.h"
++#include "qemu/main-loop.h"
 +#include "maru_sdl.h"
 +#include "maru_display.h"
 +#include "emul_state.h"
 +#include "emulator.h"
 +#include "maru_finger.h"
 +#include "hw/maru_pm.h"
 +#include "hw/maru_brightness.h"
 +#include "hw/maru_overlay.h"
 +#include "debug_ch.h"
 +
 +MULTI_DEBUG_CHANNEL(tizen, maru_sdl);
 +
 +static QEMUBH *sdl_init_bh;
 +static QEMUBH *sdl_resize_bh;
 +static DisplaySurface *dpy_surface;
 +
 +static SDL_Surface *surface_screen;
 +static SDL_Surface *surface_qemu;
 +static SDL_Surface *scaled_screen;
 +static SDL_Surface *rotated_screen;
 +static SDL_Surface *surface_guide; /* blank guide image */
 +
 +static double current_scale_factor = 1.0;
 +static double current_screen_degree;
 +static pixman_filter_t sdl_pixman_filter;
 +
 +static int sdl_alteration;
 +
 +static unsigned int sdl_skip_update;
 +static unsigned int sdl_skip_count;
 +
 +static bool blank_guide_enable;
 +static unsigned int blank_cnt;
 +#define MAX_BLANK_FRAME_CNT 10
 +#define BLANK_GUIDE_IMAGE_PATH "../images/"
 +#define BLANK_GUIDE_IMAGE_NAME "blank-guide.png"
 +
 +
 +#define SDL_THREAD
 +
 +static pthread_mutex_t sdl_mutex = PTHREAD_MUTEX_INITIALIZER;
 +#ifdef SDL_THREAD
 +static pthread_cond_t sdl_cond = PTHREAD_COND_INITIALIZER;
 +static int sdl_thread_initialized;
 +#endif
 +
 +#define SDL_FLAGS (SDL_SWSURFACE | SDL_ASYNCBLIT | SDL_NOFRAME)
 +#define SDL_BPP 32
 +
 +/* Image processing functions using the pixman library */
 +static void maru_do_pixman_dpy_surface(pixman_image_t *dst_image)
 +{
 +    /* overlay0 */
 +    if (overlay0_power) {
 +        pixman_image_composite(PIXMAN_OP_OVER,
 +                               overlay0_image, NULL, dst_image,
 +                               0, 0, 0, 0, overlay0_left, overlay0_top,
 +                               overlay0_width, overlay0_height);
 +    }
 +    /* overlay1 */
 +    if (overlay1_power) {
 +        pixman_image_composite(PIXMAN_OP_OVER,
 +                               overlay1_image, NULL, dst_image,
 +                               0, 0, 0, 0, overlay1_left, overlay1_top,
 +                               overlay1_width, overlay1_height);
 +    }
 +    /* apply the brightness level */
 +    if (brightness_level < BRIGHTNESS_MAX) {
 +        pixman_image_composite(PIXMAN_OP_OVER,
 +                               brightness_image, NULL, dst_image,
 +                               0, 0, 0, 0, 0, 0,
 +                               pixman_image_get_width(dst_image),
 +                               pixman_image_get_height(dst_image));
 +    }
 +}
 +
 +static SDL_Surface *maru_do_pixman_scale(SDL_Surface *rz_src,
 +                                         SDL_Surface *rz_dst,
 +                                         pixman_filter_t filter)
 +{
 +    pixman_image_t *src = NULL;
 +    pixman_image_t *dst = NULL;
 +    double sx = 0;
 +    double sy = 0;
 +    pixman_transform_t matrix;
 +    struct pixman_f_transform matrix_f;
 +
 +    SDL_LockSurface(rz_src);
 +    SDL_LockSurface(rz_dst);
 +
 +    src = pixman_image_create_bits(PIXMAN_a8r8g8b8,
 +        rz_src->w, rz_src->h, rz_src->pixels, rz_src->w * 4);
 +    dst = pixman_image_create_bits(PIXMAN_a8r8g8b8,
 +        rz_dst->w, rz_dst->h, rz_dst->pixels, rz_dst->w * 4);
 +
 +    sx = (double)rz_src->w / (double)rz_dst->w;
 +    sy = (double)rz_src->h / (double)rz_dst->h;
 +    pixman_f_transform_init_identity(&matrix_f);
 +    pixman_f_transform_scale(&matrix_f, NULL, sx, sy);
 +    pixman_transform_from_pixman_f_transform(&matrix, &matrix_f);
 +    pixman_image_set_transform(src, &matrix);
 +    pixman_image_set_filter(src, filter, NULL, 0);
 +    pixman_image_composite(PIXMAN_OP_SRC, src, NULL, dst,
 +                           0, 0, 0, 0, 0, 0,
 +                           rz_dst->w, rz_dst->h);
 +
 +    pixman_image_unref(src);
 +    pixman_image_unref(dst);
 +
 +    SDL_UnlockSurface(rz_src);
 +    SDL_UnlockSurface(rz_dst);
 +
 +    return rz_dst;
 +}
 +
 +static SDL_Surface *maru_do_pixman_rotate(SDL_Surface *rz_src,
 +                                          SDL_Surface *rz_dst,
 +                                          int angle)
 +{
 +    pixman_image_t *src = NULL;
 +    pixman_image_t *dst = NULL;
 +    pixman_transform_t matrix;
 +    struct pixman_f_transform matrix_f;
 +
 +    SDL_LockSurface(rz_src);
 +    SDL_LockSurface(rz_dst);
 +
 +    src = pixman_image_create_bits(PIXMAN_a8r8g8b8,
 +        rz_src->w, rz_src->h, rz_src->pixels, rz_src->w * 4);
 +    dst = pixman_image_create_bits(PIXMAN_a8r8g8b8,
 +        rz_dst->w, rz_dst->h, rz_dst->pixels, rz_dst->w * 4);
 +
 +    pixman_f_transform_init_identity(&matrix_f);
 +    switch(angle) {
 +        case 0:
 +            pixman_f_transform_rotate(&matrix_f, NULL, 1.0, 0.0);
 +            pixman_f_transform_translate(&matrix_f, NULL, 0.0, 0.0);
 +            break;
 +        case 90:
 +            pixman_f_transform_rotate(&matrix_f, NULL, 0.0, 1.0);
 +            pixman_f_transform_translate(&matrix_f, NULL,
 +                                         (double)rz_dst->h, 0.0);
 +            break;
 +        case 180:
 +            pixman_f_transform_rotate(&matrix_f, NULL, -1.0, 0.0);
 +            pixman_f_transform_translate(&matrix_f, NULL,
 +                                         (double)rz_dst->w, (double)rz_dst->h);
 +            break;
 +        case 270:
 +            pixman_f_transform_rotate(&matrix_f, NULL, 0.0, -1.0);
 +            pixman_f_transform_translate(&matrix_f, NULL,
 +                                         0.0, (double)rz_dst->w);
 +            break;
 +        default:
 +            fprintf(stdout, "not supported angle factor (angle=%d)\n", angle);
 +            break;
 +    }
 +    pixman_transform_from_pixman_f_transform(&matrix, &matrix_f);
 +    pixman_image_set_transform(src, &matrix);
 +    //pixman_image_set_filter(src, PIXMAN_FILTER_BILINEAR, NULL, 0);
 +    pixman_image_composite(PIXMAN_OP_SRC, src, NULL, dst,
 +                           0, 0, 0, 0, 0, 0,
 +                           rz_dst->w, rz_dst->h);
 +
 +    pixman_image_unref(src);
 +    pixman_image_unref(dst);
 +
 +    SDL_UnlockSurface(rz_src);
 +    SDL_UnlockSurface(rz_dst);
 +
 +    return rz_dst;
 +}
 +
 +static void qemu_ds_sdl_update(DisplayChangeListener *dcl,
 +                               int x, int y, int w, int h)
 +{
 +    /* call sdl update */
 +#ifdef SDL_THREAD
 +    pthread_mutex_lock(&sdl_mutex);
 +
 +    pthread_cond_signal(&sdl_cond);
 +
 +    pthread_mutex_unlock(&sdl_mutex);
 +#else
 +    qemu_update();
 +#endif
 +}
 +
 +static void qemu_ds_sdl_switch(DisplayChangeListener *dcl,
 +                               struct DisplaySurface *new_surface)
 +{
 +    int console_width = 0, console_height = 0;
 +
 +    sdl_skip_update = 0;
 +    sdl_skip_count = 0;
 +
 +    if (!new_surface) {
 +        ERR("qemu_ds_sdl_switch : new_surface is NULL\n");
 +        return;
 +    }
 +
 +    dpy_surface = new_surface;
 +    console_width = surface_width(new_surface);
 +    console_height = surface_height(new_surface);
 +
 +    INFO("qemu_ds_sdl_switch : (%d, %d)\n",
 +        console_width, console_height);
 +
 +#ifdef SDL_THREAD
 +    pthread_mutex_lock(&sdl_mutex);
 +#endif
 +
 +    if (surface_qemu != NULL) {
 +        SDL_FreeSurface(surface_qemu);
 +        surface_qemu = NULL;
 +    }
 +
 +    /* create surface_qemu */
 +    if (console_width == get_emul_resolution_width() &&
 +        console_height == get_emul_resolution_height()) {
 +        INFO("create SDL screen : (%d, %d)\n",
 +             console_width, console_height);
 +
 +        surface_qemu = SDL_CreateRGBSurfaceFrom(
 +            surface_data(dpy_surface),
 +            console_width, console_height,
 +            surface_bits_per_pixel(dpy_surface),
 +            surface_stride(dpy_surface),
 +            dpy_surface->pf.rmask,
 +            dpy_surface->pf.gmask,
 +            dpy_surface->pf.bmask,
 +            dpy_surface->pf.amask);
 +    } else {
 +        INFO("create blank screen : (%d, %d)\n",
 +             get_emul_resolution_width(), get_emul_resolution_height());
 +
 +        surface_qemu = SDL_CreateRGBSurface(
 +            SDL_SWSURFACE,
 +            console_width, console_height,
 +            surface_bits_per_pixel(dpy_surface),
 +            0, 0, 0, 0);
 +    }
 +
 +#ifdef SDL_THREAD
 +    pthread_mutex_unlock(&sdl_mutex);
 +#endif
 +
 +    if (surface_qemu == NULL) {
 +        ERR("Unable to set the RGBSurface: %s\n", SDL_GetError());
 +        return;
 +    }
 +}
 +
 +static png_bytep read_png_file(const char *file_name,
 +    unsigned int *width_out, unsigned int *height_out)
 +{
 +#define PNG_HEADER_SIZE 8
 +
 +    FILE *fp = NULL;
 +    png_byte header[PNG_HEADER_SIZE] = { 0, };
 +    png_structp png_ptr = NULL;
 +
 +    png_infop info_ptr = NULL;
 +    png_uint_32 width = 0;
 +    png_uint_32 height = 0;
 +    png_byte channels = 0;
 +    unsigned int stride = 0;
 +    int bit_depth = 0;
 +    int color_type = 0;
 +    int i = 0;
 +
 +    png_bytep pixel_data = NULL;
 +    png_bytepp row_ptr_data = NULL;
 +
 +    if (file_name == NULL) {
 +        ERR("file name is empty\n");
 +        return NULL;
 +    }
 +
 +    fp = fopen(file_name, "rb");
 +    if (fp == NULL) {
 +        ERR("file %s could not be opened\n", file_name);
 +        return NULL;
 +    }
 +
 +    if (fread(header, sizeof(png_byte), PNG_HEADER_SIZE, fp) != PNG_HEADER_SIZE) {
 +        ERR("failed to read header from png file\n");
 +        fclose(fp);
 +        return NULL;
 +    }
 +
 +    if (png_sig_cmp(header, 0, PNG_HEADER_SIZE) != 0) {
 +        ERR("file %s is not recognized as a PNG image\n", file_name);
 +        fclose(fp);
 +        return NULL;
 +    }
 +
 +    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
 +    if (png_ptr == NULL) {
 +        ERR("failed to allocate png read struct\n");
 +        fclose(fp);
 +        return NULL;
 +    }
 +
 +    info_ptr = png_create_info_struct(png_ptr);
 +    if (info_ptr == NULL) {
 +        ERR("failed to allocate png info struct\n");
 +        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
 +        fclose(fp);
 +        return NULL;
 +    }
 +
 +    if (setjmp(png_jmpbuf(png_ptr)) != 0) {
 +        ERR("error during init_io\n");
 +        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
 +        png_destroy_info_struct(png_ptr, &info_ptr);
 +        fclose(fp);
 +        return NULL;
 +    }
 +
 +    png_init_io(png_ptr, fp);
 +    png_set_sig_bytes(png_ptr, PNG_HEADER_SIZE);
 +
 +    /* read the PNG image information */
 +    png_read_info(png_ptr, info_ptr);
 +    png_get_IHDR(png_ptr, info_ptr,
 +        &width, &height, &bit_depth, &color_type,
 +        NULL, NULL, NULL);
 +
 +    channels = png_get_channels(png_ptr, info_ptr);
 +    stride = width * bit_depth * channels / 8;
 +
 +    pixel_data = (png_bytep) g_malloc0(stride * height);
 +    if (pixel_data == NULL) {
 +        ERR("could not allocate data buffer for pixels\n");
 +
 +        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
 +        png_destroy_info_struct(png_ptr, &info_ptr);
 +        fclose(fp);
 +        return NULL;
 +    }
 +
 +    row_ptr_data = (png_bytepp) g_malloc0(sizeof(png_bytep) * height);
 +    if (row_ptr_data == NULL) {
 +        ERR("could not allocate data buffer for row_ptr\n");
 +
 +        g_free(pixel_data);
 +        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
 +        png_destroy_info_struct(png_ptr, &info_ptr);
 +        fclose(fp);
 +        return NULL;
 +    }
 +
 +    switch(color_type) {
 +        case PNG_COLOR_TYPE_PALETTE :
 +            png_set_palette_to_rgb(png_ptr);
 +            break;
 +        case PNG_COLOR_TYPE_RGB :
 +            if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
 +                /* transparency data for image */
 +                png_set_tRNS_to_alpha(png_ptr);
 +            } else {
 +                png_set_filter(png_ptr, 0xff, PNG_FILLER_AFTER);
 +            }
 +            break;
 +        case PNG_COLOR_TYPE_RGB_ALPHA :
 +            break;
 +        default :
 +            INFO("png file has an unsupported color type\n");
 +            break;
 +    }
 +
 +    for (i = 0; i < height; i++) {
 +        row_ptr_data[i] = pixel_data + (stride * i);
 +    }
 +
 +    /* read the entire image into memory */
 +    png_read_image(png_ptr, row_ptr_data);
 +
 +    /* image information */
 +    INFO("=== blank guide image was loaded ===============\n");
 +    INFO("file path : %s\n", file_name);
 +    INFO("width : %d, height : %d, stride : %d\n",
 +        width, height, stride);
 +    INFO("color type : %d, channels : %d, bit depth : %d\n",
 +        color_type, channels, bit_depth);
 +    INFO("================================================\n");
 +
 +    if (width_out != NULL) {
 +        *width_out = (unsigned int) width;
 +    }
 +    if (height_out != NULL) {
 +        *height_out = (unsigned int) height;
 +    }
 +
 +    g_free(row_ptr_data);
 +    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
 +    png_destroy_info_struct(png_ptr, &info_ptr);
 +    fclose(fp);
 +
 +    return pixel_data;
 +}
 +
 +static SDL_Surface *get_blank_guide_image(void)
 +{
 +    if (surface_guide == NULL) {
 +        unsigned int width = 0;
 +        unsigned int height = 0;
 +        char *guide_image_path = NULL;
 +        void *guide_image_data = NULL;
 +
 +        /* load png image */
 +        int path_len = strlen(get_bin_path()) +
 +            strlen(BLANK_GUIDE_IMAGE_PATH) +
 +            strlen(BLANK_GUIDE_IMAGE_NAME) + 1;
 +        guide_image_path = g_malloc0(sizeof(char) * path_len);
 +        snprintf(guide_image_path, path_len, "%s%s%s",
 +            get_bin_path(), BLANK_GUIDE_IMAGE_PATH,
 +            BLANK_GUIDE_IMAGE_NAME);
 +
 +        guide_image_data = (void *) read_png_file(
 +            guide_image_path, &width, &height);
 +
 +        if (guide_image_data != NULL) {
 +            surface_guide = SDL_CreateRGBSurfaceFrom(
 +                guide_image_data, width, height,
 +                get_emul_sdl_bpp(), width * 4,
 +                dpy_surface->pf.bmask,
 +                dpy_surface->pf.gmask,
 +                dpy_surface->pf.rmask,
 +                dpy_surface->pf.amask);
 +        } else {
 +            ERR("failed to draw a blank guide image\n");
 +        }
 +
 +        g_free(guide_image_path);
 +    }
 +
 +    return surface_guide;
 +}
 +
 +static void qemu_ds_sdl_refresh(DisplayChangeListener *dcl)
 +{
 +    if (sdl_alteration == 1) {
 +        sdl_alteration = 0;
 +        sdl_skip_update = 0;
 +        sdl_skip_count = 0;
 +    }
 +
 +    /* If the display is turned off,
 +       the screen does not update until the display is turned on */
 +    if (sdl_skip_update && brightness_off) {
 +        if (blank_cnt > MAX_BLANK_FRAME_CNT) {
 +            /* do nothing */
 +            return;
 +        } else if (blank_cnt == MAX_BLANK_FRAME_CNT) {
 +            if (blank_guide_enable == true) {
 +                INFO("draw a blank guide image\n");
 +
 +                SDL_Surface *guide = get_blank_guide_image();
 +                if (guide != NULL && get_emul_skin_enable() == 1) {
 +                    /* draw guide image */
 +                    int dst_x = 0; int dst_y = 0;
 +                    int dst_w = 0; int dst_h = 0;
 +
 +                    unsigned int screen_width =
 +                        get_emul_resolution_width() * current_scale_factor;
 +                    unsigned int screen_height =
 +                        get_emul_resolution_height() * current_scale_factor;
 +
 +                    int margin_w = screen_width - guide->w;
 +                    int margin_h = screen_height - guide->h;
 +
 +                    if (margin_w < 0 || margin_h < 0) {
 +                        /* guide image scaling */
 +                        int margin = (margin_w < margin_h)? margin_w : margin_h;
 +                        dst_w = guide->w + margin;
 +                        dst_h = guide->h + margin;
 +
 +                        SDL_Surface *scaled_guide = SDL_CreateRGBSurface(
 +                            SDL_SWSURFACE, dst_w, dst_h, get_emul_sdl_bpp(),
 +                            guide->format->Rmask, guide->format->Gmask,
 +                            guide->format->Bmask, guide->format->Amask);
 +
 +                        scaled_guide = maru_do_pixman_scale(
 +                            guide, scaled_guide, PIXMAN_FILTER_BEST);
 +
 +                        dst_x = (surface_screen->w - dst_w) / 2;
 +                        dst_y = (surface_screen->h - dst_h) / 2;
 +                        SDL_Rect dst_rect = { dst_x, dst_y, dst_w, dst_h };
 +
 +                        SDL_BlitSurface(scaled_guide, NULL,
 +                            surface_screen, &dst_rect);
 +                        SDL_UpdateRect(surface_screen, 0, 0, 0, 0);
 +
 +                        SDL_FreeSurface(scaled_guide);
 +                    } else {
 +                        dst_w = guide->w;
 +                        dst_h = guide->h;
 +                        dst_x = (surface_screen->w - dst_w) / 2;
 +                        dst_y = (surface_screen->h - dst_h) / 2;
 +                        SDL_Rect dst_rect = { dst_x, dst_y, dst_w, dst_h };
 +
 +                        SDL_BlitSurface(guide, NULL,
 +                            surface_screen, &dst_rect);
 +                        SDL_UpdateRect(surface_screen, 0, 0, 0, 0);
 +                    }
 +                }
 +            }
 +        } else if (blank_cnt == 0) {
 +            INFO("skipping of the display updating is started\n");
 +        }
 +
 +        blank_cnt++;
 +
 +        return;
 +    } else {
 +        if (blank_cnt != 0) {
 +            INFO("skipping of the display updating is ended\n");
 +            blank_cnt = 0;
 +        }
 +    }
 +
 +    graphic_hw_update(NULL);
 +
 +    /* Usually, continuously updated.
 +       When the display is turned off,
 +       ten more updates the screen for a black screen. */
 +    if (brightness_off) {
 +        if (++sdl_skip_count > 10) {
 +            sdl_skip_update = 1;
 +        } else {
 +            sdl_skip_update = 0;
 +        }
 +    } else {
 +        sdl_skip_count = 0;
 +        sdl_skip_update = 0;
 +    }
 +
 +#ifdef TARGET_ARM
 +#ifdef SDL_THREAD
 +    pthread_mutex_lock(&sdl_mutex);
 +#endif
 +
 +    /*
 +    * It is necessary only for exynos4210 FIMD in connection with
 +    * some WM (xfwm4, for example)
 +    */
 +
 +    SDL_UpdateRect(surface_screen, 0, 0, 0, 0);
 +
 +#ifdef SDL_THREAD
 +    pthread_mutex_unlock(&sdl_mutex);
 +#endif
 +#endif
 +}
 +
 +DisplayChangeListenerOps maru_dcl_ops = {
 +    .dpy_name          = "maru_sdl",
 +    .dpy_gfx_update    = qemu_ds_sdl_update,
 +    .dpy_gfx_switch    = qemu_ds_sdl_switch,
 +    .dpy_refresh       = qemu_ds_sdl_refresh,
 +};
 +
 +void maruskin_sdl_interpolation(bool on)
 +{
 +    if (on == true) {
 +        INFO("set PIXMAN_FILTER_BEST filter for image processing\n");
 +
 +        /* PIXMAN_FILTER_BILINEAR */
 +        sdl_pixman_filter = PIXMAN_FILTER_BEST;
 +    } else {
 +        INFO("set PIXMAN_FILTER_FAST filter for image processing\n");
 +
 +        /* PIXMAN_FILTER_NEAREST */
 +        sdl_pixman_filter = PIXMAN_FILTER_FAST;
 +    }
 +}
 +
 +static void qemu_update(void)
 +{
 +    if (sdl_alteration == -1) {
 +        SDL_FreeSurface(scaled_screen);
 +        SDL_FreeSurface(rotated_screen);
 +        SDL_FreeSurface(surface_qemu);
 +        surface_qemu = NULL;
 +
 +        return;
 +    }
 +
 +    if (surface_qemu != NULL) {
 +        int i = 0;
 +
 +        maru_do_pixman_dpy_surface(dpy_surface->image);
 +        set_maru_screenshot(dpy_surface);
 +
 +        if (current_scale_factor != 1.0) {
 +            rotated_screen = maru_do_pixman_rotate(
 +                surface_qemu, rotated_screen,
 +                (int)current_screen_degree);
 +            scaled_screen = maru_do_pixman_scale(
 +                rotated_screen, scaled_screen, sdl_pixman_filter);
 +
 +            SDL_BlitSurface(scaled_screen, NULL, surface_screen, NULL);
 +        }
 +        else {/* current_scale_factor == 1.0 */
 +            if (current_screen_degree != 0.0) {
 +                rotated_screen = maru_do_pixman_rotate(
 +                    surface_qemu, rotated_screen,
 +                    (int)current_screen_degree);
 +
 +                SDL_BlitSurface(rotated_screen, NULL, surface_screen, NULL);
 +            } else {
 +                /* as-is */
 +                SDL_BlitSurface(surface_qemu, NULL, surface_screen, NULL);
 +            }
 +        }
 +
 +        /* draw multi-touch finger points */
 +        MultiTouchState *mts = get_emul_multi_touch_state();
 +        if (mts->multitouch_enable != 0 && mts->finger_point_surface != NULL) {
 +            FingerPoint *finger = NULL;
 +            int finger_point_size_half = mts->finger_point_size / 2;
 +            SDL_Rect rect;
 +
 +            for (i = 0; i < mts->finger_cnt; i++) {
 +                finger = get_finger_point_from_slot(i);
 +                if (finger != NULL && finger->id != 0) {
 +                    rect.x = finger->origin_x - finger_point_size_half;
 +                    rect.y = finger->origin_y - finger_point_size_half;
 +                    rect.w = rect.h = mts->finger_point_size;
 +
 +                    SDL_BlitSurface(
 +                        (SDL_Surface *)mts->finger_point_surface,
 +                        NULL, surface_screen, &rect);
 +                }
 +            }
 +        } /* end of draw multi-touch */
 +    }
 +
 +    SDL_UpdateRect(surface_screen, 0, 0, 0, 0);
 +}
 +
 +
 +#ifdef SDL_THREAD
 +static void *run_qemu_update(void *arg)
 +{
 +    while(1) {
 +        pthread_mutex_lock(&sdl_mutex);
 +
 +        pthread_cond_wait(&sdl_cond, &sdl_mutex);
 +
 +        qemu_update();
 +
 +        pthread_mutex_unlock(&sdl_mutex);
 +    }
 +
 +    return NULL;
 +}
 +#endif
 +
 +static void maru_sdl_resize_bh(void *opaque)
 +{
 +    int surface_width = 0, surface_height = 0;
 +    int display_width = 0, display_height = 0;
 +    int temp = 0;
 +
 +    INFO("Set up a video mode with the specified width, "
 +         "height and bits-per-pixel\n");
 +
 +    sdl_alteration = 1;
 +    sdl_skip_update = 0;
 +
 +#ifdef SDL_THREAD
 +    pthread_mutex_lock(&sdl_mutex);
 +#endif
 +
 +    /* get current setting information and calculate screen size */
 +    display_width = get_emul_resolution_width();
 +    display_height = get_emul_resolution_height();
 +    current_scale_factor = get_emul_win_scale();
 +
 +    short rotaton_type = get_emul_rotation();
 +    if (rotaton_type == ROTATION_PORTRAIT) {
 +        current_screen_degree = 0.0;
 +    } else if (rotaton_type == ROTATION_LANDSCAPE) {
 +        current_screen_degree = 90.0;
 +        temp = display_width;
 +        display_width = display_height;
 +        display_height = temp;
 +    } else if (rotaton_type == ROTATION_REVERSE_PORTRAIT) {
 +        current_screen_degree = 180.0;
 +    } else if (rotaton_type == ROTATION_REVERSE_LANDSCAPE) {
 +        current_screen_degree = 270.0;
 +        temp = display_width;
 +        display_width = display_height;
 +        display_height = temp;
 +    }
 +
 +    surface_width = display_width * current_scale_factor;
 +    surface_height = display_height * current_scale_factor;
 +
 +    surface_screen = SDL_SetVideoMode(
 +        surface_width, surface_height,
 +        get_emul_sdl_bpp(), SDL_FLAGS);
 +
 +    INFO("SDL_SetVideoMode\n");
 +
 +    if (surface_screen == NULL) {
 +        ERR("Could not open SDL display (%dx%dx%d) : %s\n",
 +            surface_width, surface_height,
 +            get_emul_sdl_bpp(), SDL_GetError());
 +
 +#ifdef SDL_THREAD
 +        pthread_mutex_unlock(&sdl_mutex);
 +#endif
 +
 +        return;
 +    }
 +
 +    /* create buffer for image processing */
 +    SDL_FreeSurface(scaled_screen);
 +    scaled_screen = SDL_CreateRGBSurface(SDL_SWSURFACE,
 +        surface_width, surface_height,
 +        get_emul_sdl_bpp(),
 +        surface_qemu->format->Rmask,
 +        surface_qemu->format->Gmask,
 +        surface_qemu->format->Bmask,
 +        surface_qemu->format->Amask);
 +
 +    SDL_FreeSurface(rotated_screen);
 +    rotated_screen = SDL_CreateRGBSurface(SDL_SWSURFACE,
 +        display_width, display_height,
 +        get_emul_sdl_bpp(),
 +        surface_qemu->format->Rmask,
 +        surface_qemu->format->Gmask,
 +        surface_qemu->format->Bmask,
 +        surface_qemu->format->Amask);
 +
 +    /* rearrange multi-touch finger points */
 +    if (get_emul_multi_touch_state()->multitouch_enable == 1 ||
 +            get_emul_multi_touch_state()->multitouch_enable == 2) {
 +        rearrange_finger_points(get_emul_resolution_width(), get_emul_resolution_height(),
 +            current_scale_factor, rotaton_type);
 +    }
 +
 +#ifdef SDL_THREAD
 +    pthread_mutex_unlock(&sdl_mutex);
 +#endif
 +}
 +
 +static void maru_sdl_init_bh(void *opaque)
 +{
 +    SDL_SysWMinfo info;
 +
 +    INFO("SDL_Init\n");
 +
 +    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
 +        ERR("unable to init SDL: %s\n", SDL_GetError());
 +        // TODO:
 +    }
 +
 +#ifndef _WIN32
 +    SDL_VERSION(&info.version);
 +    SDL_GetWMInfo(&info);
 +#endif
 +
 +    qemu_bh_schedule(sdl_resize_bh);
 +
 +#ifdef SDL_THREAD
 +    if (sdl_thread_initialized == 0) {
 +        sdl_thread_initialized = 1;
 +
 +        INFO("sdl update thread create\n");
 +
 +        pthread_t thread_id;
 +        if (pthread_create(
 +            &thread_id, NULL, run_qemu_update, NULL) != 0) {
 +            ERR("pthread_create fail\n");
 +            return;
 +        }
 +    }
 +#endif
 +}
 +
 +void maruskin_sdl_init(uint64 swt_handle,
 +    unsigned int display_width, unsigned int display_height,
 +    bool blank_guide)
 +{
 +    gchar SDL_windowhack[32] = { 0, };
 +    long window_id = swt_handle;
 +    blank_guide_enable = blank_guide;
 +
 +    INFO("maru sdl init\n");
 +
 +    sdl_init_bh = qemu_bh_new(maru_sdl_init_bh, NULL);
 +    sdl_resize_bh = qemu_bh_new(maru_sdl_resize_bh, NULL);
 +
 +    sprintf(SDL_windowhack, "%ld", window_id);
 +    g_setenv("SDL_WINDOWID", SDL_windowhack, 1);
 +
 +    INFO("register SDL environment variable. "
 +        "(SDL_WINDOWID = %s)\n", SDL_windowhack);
 +
 +    set_emul_resolution(display_width, display_height);
 +    set_emul_sdl_bpp(SDL_BPP);
 +    maruskin_sdl_interpolation(false);
 +    init_multi_touch_state();
 +
 +    if (blank_guide_enable == true) {
 +        INFO("blank guide is on\n");
 +    }
 +
 +    qemu_bh_schedule(sdl_init_bh);
 +}
 +
 +void maruskin_sdl_quit(void)
 +{
 +    INFO("maru sdl quit\n");
 +
 +    if (surface_guide != NULL) {
 +        g_free(surface_guide->pixels);
 +        SDL_FreeSurface(surface_guide);
 +    }
 +
 +    /* remove multi-touch finger points */
 +    cleanup_multi_touch_state();
 +
 +    if (sdl_init_bh != NULL) {
 +        qemu_bh_delete(sdl_init_bh);
 +    }
 +    if (sdl_resize_bh != NULL) {
 +        qemu_bh_delete(sdl_resize_bh);
 +    }
 +
 +    sdl_alteration = -1;
 +
 +#ifdef SDL_THREAD
 +    pthread_mutex_lock(&sdl_mutex);
 +#endif
 +
 +    SDL_Quit();
 +
 +#ifdef SDL_THREAD
 +    pthread_mutex_unlock(&sdl_mutex);
 +    pthread_cond_destroy(&sdl_cond);
 +#endif
 +
 +    pthread_mutex_destroy(&sdl_mutex);
 +}
 +
 +void maruskin_sdl_resize(void)
 +{
 +    INFO("maru sdl resize\n");
 +
 +    qemu_bh_schedule(sdl_resize_bh);
 +}
index 88797e2,0000000..b51436c
mode 100644,000000..100644
--- /dev/null
@@@ -1,659 -1,0 +1,659 @@@
-             qdev_free(&usbdisk->qdev);
 +/*
 + * mainloop_evhandle.c
 + *
 + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
 + *
 + * Contact:
 + * Kitae Kim <kt920.kim@samsung.com>
 + * GiWoong Kim <giwoong.kim@samsung.com>
 + * DoHyung Hong
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + */
 +
 +
 +#ifdef _WIN32
 +#include <winsock.h>
 +#define socklen_t     int
 +#else
 +#include <netinet/in.h>
 +#include <sys/ioctl.h>
 +#endif
 +
 +//#include "qobject.h"
 +#include "qemu-common.h"
 +#include "hw/usb.h"
 +#include "hw/irq.h"
 +#include "mloop_event.h"
 +#include "ui/console.h"
 +#include "emul_state.h"
 +#include "debug_ch.h"
 +#include "monitor/monitor.h"
 +#include "hw/pci/pci.h"
 +#include "sysemu/sysemu.h"
 +#include "exec/memory-internal.h"
 +
 +#include "emulator.h"
 +#include "guest_debug.h"
 +#include "skin/maruskin_server.h"
 +#include "hw/maru_virtio_touchscreen.h"
 +#include "hw/maru_virtio_keyboard.h"
 +
 +MULTI_DEBUG_CHANNEL(qemu, mloop_event);
 +
 +struct mloop_evsock {
 +    int sockno;
 +    unsigned short portno;
 +    unsigned char status;
 +};
 +
 +#define MLOOP_EVSOCK_NULL        0
 +#define MLOOP_EVSOCK_CREATED    1
 +#define MLOOP_EVSOCK_NOTBOUND    2
 +#define MLOOP_EVSOCK_BOUND        3
 +#define MLOOP_EVSOCK_CONNECTED    4
 +
 +#define PACKET_LEN 512
 +struct mloop_evpack {
 +    short type;
 +    short size;
 +    char data[PACKET_LEN-4];
 +};
 +
 +#define MLOOP_EVTYPE_USB_ADD    1
 +#define MLOOP_EVTYPE_USB_DEL    2
 +#define MLOOP_EVTYPE_INTR_UP    3
 +#define MLOOP_EVTYPE_INTR_DOWN  4
 +#define MLOOP_EVTYPE_TOUCH      6
 +#define MLOOP_EVTYPE_KEYBOARD   7
 +#define MLOOP_EVTYPE_KBD_ADD    8
 +#define MLOOP_EVTYPE_KBD_DEL    9
 +#define MLOOP_EVTYPE_RAMDUMP    10
 +#define MLOOP_EVTYPE_SDCARD_ATTACH  11
 +#define MLOOP_EVTYPE_SDCARD_DETACH  12
 +
 +
 +static struct mloop_evsock mloop = {-1, 0, 0};
 +
 +static int mloop_evsock_create(struct mloop_evsock *ev)
 +{
 +    struct sockaddr sa;
 +    socklen_t sa_size;
 +    int ret;
 +    unsigned long nonblock = 1;
 +
 +    if (ev == NULL) {
 +        ERR("null pointer\n");
 +        return -1;
 +    }
 +
 +    ev->sockno = socket(AF_INET, SOCK_DGRAM, 0);
 +    if ( ev->sockno == -1 ) {
 +        ERR("socket() failed\n");
 +        return -1;
 +    }
 +
 +#ifdef _WIN32
 +    ioctlsocket(ev->sockno, FIONBIO, &nonblock );
 +#else
 +    ioctl(ev->sockno, FIONBIO, &nonblock);
 +#endif // _WIN32
 +
 +    nonblock = 1 ;
 +    setsockopt( ev->sockno, SOL_SOCKET, SO_REUSEADDR, (char *)&nonblock, sizeof(nonblock) ) ;
 +
 +    memset(&sa, '\0', sizeof(sa));
 +    ((struct sockaddr_in *) &sa)->sin_family = AF_INET;
 +    memcpy(&((struct sockaddr_in *) &sa)->sin_addr, "\177\000\000\001", 4); // 127.0.0.1
 +    ((struct sockaddr_in *) &sa)->sin_port = htons(ev->portno);
 +    sa_size = sizeof(struct sockaddr_in);
 +
 +    ret = bind(ev->sockno, &sa, sa_size);
 +    if (ret) {
 +        ERR("bind() failed\n");
 +#ifdef _WIN32
 +        closesocket(ev->sockno);
 +#else
 +        close(ev->sockno);
 +#endif
 +        ev->sockno = -1;
 +        ev->status = 0;
 +        return ret;
 +    }
 +
 +    if (ev->portno == 0) {
 +        memset(&sa, '\0', sizeof(sa));
 +        getsockname(ev->sockno, (struct sockaddr *) &sa, &sa_size);
 +        ev->portno = ntohs(((struct sockaddr_in *) &sa)->sin_port);
 +    }
 +
 +    ret = connect(ev->sockno, (struct sockaddr *) &sa, sa_size);
 +    if (ret) {
 +        ERR("connect() failed\n");
 +#ifdef _WIN32
 +        closesocket(ev->sockno);
 +#else
 +        close(ev->sockno);
 +#endif
 +        ev->sockno = -1;
 +        ev->status = 0;
 +        return ret;
 +    }
 +
 +    ev->status = MLOOP_EVSOCK_CONNECTED;
 +    return 0;
 +}
 +
 +static void mloop_evsock_remove(struct mloop_evsock *ev)
 +{
 +    if (!ev) {
 +        return ;
 +    }
 +
 +    if (ev->sockno > 0) {
 +#ifdef _WIN32
 +        shutdown(ev->sockno, SD_BOTH);
 +        closesocket(ev->sockno);
 +#else
 +        shutdown(ev->sockno, SHUT_RDWR);
 +        close(ev->sockno);
 +#endif
 +        ev->sockno = -1;
 +        ev->status = 0;
 +    }
 +}
 +
 +static int mloop_evsock_send(struct mloop_evsock *ev, struct mloop_evpack *p)
 +{
 +    int ret;
 +
 +    if (ev == NULL || ev->sockno == -1) {
 +        ERR("invalid mloop_evsock\n");
 +        return -1;
 +    }
 +
 +    if (p == NULL || p->size <= 0) {
 +        ERR("invalid mloop_evpack\n");
 +        return -1;
 +    }
 +
 +    do {
 +        ret = send(ev->sockno, p, p->size, 0);
 +#ifdef _WIN32
 +    } while (ret == -1 && (WSAGetLastError() == WSAEWOULDBLOCK));
 +#else
 +    } while (ret == -1 && (errno == EWOULDBLOCK || errno == EINTR));
 +#endif // _WIN32
 +
 +    return ret;
 +}
 +
 +static USBDevice *usbkbd = NULL;
 +static USBDevice *usbdisk = NULL;
 +#ifdef TARGET_I386
 +static PCIDevice *hostkbd = NULL;
 +static PCIDevice *virtio_sdcard = NULL;
 +#endif
 +
 +static void mloop_evhandle_usb_add(char *name)
 +{
 +    if (name == NULL) {
 +        ERR("Packet data for usb device is NULL\n");
 +        return;
 +    }
 +
 +    if (strcmp(name, "keyboard") == 0) {
 +        if (usbkbd == NULL) {
 +            usbkbd = usbdevice_create(name);
 +        } else if (usbkbd->attached == 0) {
 +            usb_device_attach(usbkbd);
 +        }
 +    } else if (strncmp(name, "disk:", 5) == 0) {
 +        if (usbdisk == NULL) {
 +            usbdisk = usbdevice_create(name);
 +        }
 +    } else {
 +        WARN("There is no usb-device for %s.\n", name);
 +     }
 +}
 +
 +static void mloop_evhandle_usb_del(char *name)
 +{
 +    if (name == NULL) {
 +        ERR("Packet data for usb device is NULL\n");
 +        return;
 +    }
 +
 +    if (strcmp(name, "keyboard") == 0) {
 +        if (usbkbd && usbkbd->attached != 0) {
 +            usb_device_detach(usbkbd);
 +        }
 +    } else if (strncmp(name, "disk:", 5) == 0) {
 +        if (usbdisk) {
++//            qdev_free(&usbdisk->qdev);
 +        }
 +    } else {
 +        WARN("There is no usb-device for %s.\n", name);
 +    }
 +}
 +
 +static void mloop_evhandle_intr_up(long data)
 +{
 +    if (data == 0) {
 +        return;
 +    }
 +
 +    qemu_irq_raise((qemu_irq)data);
 +}
 +
 +static void mloop_evhandle_intr_down(long data)
 +{
 +    if (data == 0) {
 +        return;
 +    }
 +
 +    qemu_irq_lower((qemu_irq)data);
 +}
 +
 +static void mloop_evhandle_touch(struct mloop_evpack* pack)
 +{
 +    maru_virtio_touchscreen_notify();
 +}
 +
 +static void mloop_evhandle_keyboard(long data)
 +{
 +    virtio_keyboard_notify((void*)data);
 +}
 +
 +#ifdef TARGET_I386
 +static void mloop_evhandle_kbd_add(char *name)
 +{
 +    QDict *qdict;
 +
 +    TRACE("try to add a keyboard device.\n");
 +
 +    if (name == NULL) {
 +        ERR("packet data is NULL.\n");
 +        return;
 +    }
 +
 +    if (hostkbd) {
 +        INFO("virtio-keyboard has already been added.\n");
 +        return;
 +    }
 +
 +    qdict = qdict_new();
 +    qdict_put(qdict, "pci_addr", qstring_from_str("auto"));
 +    qdict_put(qdict, "type", qstring_from_str(name));
 +
 +    hostkbd = do_pci_device_hot_add(cur_mon, qdict);
 +    if (hostkbd) {
 +        TRACE("virtio-keyboard device: root_bus_path %s, bus %d, slot %d, function %d\n",
 +                pci_root_bus_path(hostkbd), pci_bus_num(hostkbd->bus),
 +                PCI_SLOT(hostkbd->devfn), PCI_FUNC(hostkbd->devfn));
 +    } else {
 +        ERR("failed to hot_add keyboard device.\n");
 +    }
 +
 +    QDECREF(qdict);
 +}
 +
 +static void mloop_evhandle_kbd_del(void)
 +{
 +    QDict *qdict;
 +    int slot = 0;
 +    char slotbuf[4] = {0,};
 +
 +    TRACE("try to remove a keyboard device.\n");
 +
 +    if (!hostkbd) {
 +        ERR("Failed to remove a keyboard device "
 +            "because the device has not been created yet.\n");
 +        return;
 +    }
 +
 +    slot = PCI_SLOT(hostkbd->devfn);
 +    snprintf(slotbuf, sizeof(slotbuf), "%x", slot);
 +    TRACE("virtio-keyboard slot %s.\n", slotbuf);
 +
 +    qdict = qdict_new();
 +    qdict_put(qdict, "pci_addr", qstring_from_str(slotbuf));
 +
 +    do_pci_device_hot_remove(cur_mon, qdict);
 +    INFO("hot_remove keyboard.\n");
 +
 +    hostkbd = NULL;
 +
 +    QDECREF(qdict);
 +}
 +
 +static void mloop_evhandle_sdcard_attach(char *name)
 +{
 +    char opts[PATH_MAX];
 +
 +    INFO("try to attach sdcard.\n");
 +
 +    if (name == NULL) {
 +        ERR("Packet data is NULL.\n");
 +        return;
 +    }
 +
 +    if (virtio_sdcard) {
 +        ERR("sdcard is already attached.\n");
 +        return;
 +    }
 +
 +    QDict *qdict = qdict_new();
 +
 +    qdict_put(qdict, "pci_addr", qstring_from_str("auto"));
 +    qdict_put(qdict, "type", qstring_from_str("storage"));
 +    snprintf(opts, sizeof(opts), "file=%s,if=virtio", name);
 +    qdict_put(qdict, "opts", qstring_from_str(opts));
 +
 +    virtio_sdcard = do_pci_device_hot_add(cur_mon, qdict);
 +    if (virtio_sdcard) {
 +        INFO("hot add virtio storage device with [%s]\n", opts);
 +        INFO("virtio-sdcard device: root_bus_path %s, bus %d, slot %d, function %d\n",
 +            pci_root_bus_path(virtio_sdcard), pci_bus_num(virtio_sdcard->bus),
 +            PCI_SLOT(virtio_sdcard->devfn), PCI_FUNC(virtio_sdcard->devfn));
 +    } else {
 +        ERR("failed to create a sdcard device.\n");
 +    }
 +
 +    QDECREF(qdict);
 +}
 +
 +static void mloop_evhandle_sdcard_detach(void)
 +{
 +    INFO("try to detach sdcard.\n");
 +
 +    if (!virtio_sdcard) {
 +        ERR("sdcard is not attached yet.\n");
 +        return;
 +    }
 +
 +    QDict *qdict = qdict_new();
 +    int slot = 0;
 +    char slotbuf[4] = {0,};
 +
 +    slot = PCI_SLOT(virtio_sdcard->devfn);
 +    snprintf(slotbuf, sizeof(slotbuf), "%x", slot);
 +    INFO("virtio-sdcard slot [%d].\n", slot);
 +    qdict_put(qdict, "pci_addr", qstring_from_str(slotbuf));
 +
 +    do_pci_device_hot_remove(cur_mon, qdict);
 +
 +    virtio_sdcard = NULL;
 +
 +    INFO("hot remove virtio storage device.\n");
 +
 +    QDECREF(qdict);
 +}
 +
 +int mloop_evcmd_get_hostkbd_status(void)
 +{
 +    return hostkbd ? 1 : 0;
 +}
 +#endif
 +
 +static void mloop_evhandle_ramdump(struct mloop_evpack* pack)
 +{
 +#define MAX_PATH 256
 +    INFO("dumping...\n");
 +
 +#if defined(CONFIG_LINUX) && !defined(TARGET_ARM) /* FIXME: Handle ARM ram as list */
 +    MemoryRegion* mr = get_ram_memory();
 +    size_t size = mr->size.lo;
 +    char dump_fullpath[MAX_PATH];
 +    char dump_filename[MAX_PATH];
 +
 +    char* dump_path = g_path_get_dirname(get_log_path());
 +
 +    sprintf(dump_filename, "0x%08x%s0x%08x%s", (unsigned int)mr->ram_addr, "-",
 +        (unsigned int)(mr->ram_addr + size), "_RAM.dump");
 +    sprintf(dump_fullpath, "%s/%s", dump_path, dump_filename);
 +    free(dump_path);
 +
 +    FILE *dump_file = fopen(dump_fullpath, "w+");
 +    if(!dump_file) {
 +        fprintf(stderr, "Dump file create failed [%s]\n", dump_fullpath);
 +
 +        return;
 +    }
 +
 +    size_t written;
 +    written = fwrite(qemu_get_ram_ptr(mr->ram_addr), sizeof(char), size, dump_file);
 +    fprintf(stdout, "Dump file written [%08x][%zu bytes]\n", (unsigned int)mr->ram_addr, written);
 +    if(written != size) {
 +        fprintf(stderr, "Dump file size error [%zu, %zu, %d]\n", written, size, errno);
 +    }
 +
 +    fprintf(stdout, "Dump file create success [%s, %zu bytes]\n", dump_fullpath, size);
 +
 +    fclose(dump_file);
 +#endif
 +
 +    /* notify to skin process */
 +    notify_ramdump_completed();
 +}
 +
 +static void mloop_evcb_recv(struct mloop_evsock *ev)
 +{
 +    struct mloop_evpack pack;
 +    int ret;
 +
 +    do {
 +        ret = recv(ev->sockno, (void *)&pack, sizeof(pack), 0);
 +#ifdef _WIN32
 +    } while (ret == -1 && WSAGetLastError() == WSAEINTR);
 +#else
 +    } while (ret == -1 && errno == EINTR);
 +#endif // _WIN32
 +
 +    if (ret == -1) {
 +        return;
 +    }
 +
 +    if (ret == 0) {
 +        return;
 +    }
 +
 +    switch (pack.type) {
 +    case MLOOP_EVTYPE_USB_ADD:
 +        mloop_evhandle_usb_add(pack.data);
 +        break;
 +    case MLOOP_EVTYPE_USB_DEL:
 +        mloop_evhandle_usb_del(pack.data);
 +        break;
 +    case MLOOP_EVTYPE_INTR_UP:
 +        mloop_evhandle_intr_up(*(long*)&pack.data[0]);
 +        break;
 +    case MLOOP_EVTYPE_INTR_DOWN:
 +        mloop_evhandle_intr_down(*(long*)&pack.data[0]);
 +        break;
 +    case MLOOP_EVTYPE_TOUCH:
 +        mloop_evhandle_touch(&pack);
 +        break;
 +    case MLOOP_EVTYPE_KEYBOARD:
 +        mloop_evhandle_keyboard(*(uint64_t*)&pack.data[0]);
 +        break;
 +#ifdef TARGET_I386
 +    case MLOOP_EVTYPE_KBD_ADD:
 +        mloop_evhandle_kbd_add(pack.data);
 +        break;
 +    case MLOOP_EVTYPE_KBD_DEL:
 +        mloop_evhandle_kbd_del();
 +        break;
 +#endif
 +    case MLOOP_EVTYPE_RAMDUMP:
 +        mloop_evhandle_ramdump(&pack);
 +        break;
 +#ifdef TARGET_I386
 +    case MLOOP_EVTYPE_SDCARD_ATTACH:
 +        mloop_evhandle_sdcard_attach(pack.data);
 +        break;
 +    case MLOOP_EVTYPE_SDCARD_DETACH:
 +        mloop_evhandle_sdcard_detach();
 +        break;
 +#endif
 +    default:
 +        break;
 +    }
 +}
 +
 +void mloop_ev_init(void)
 +{
 +    int ret = mloop_evsock_create(&mloop);
 +    if (ret == 0) {
 +        qemu_set_fd_handler(mloop.sockno, (IOHandler *)mloop_evcb_recv, NULL, &mloop);
 +    }
 +}
 +
 +void mloop_ev_stop(void)
 +{
 +    qemu_set_fd_handler(mloop.sockno, NULL, NULL, NULL);
 +    mloop_evsock_remove(&mloop);
 +}
 +
 +void mloop_evcmd_raise_intr(void *irq)
 +{
 +    struct mloop_evpack pack;
 +    memset((void*)&pack, 0, sizeof(struct mloop_evpack));
 +    pack.type = MLOOP_EVTYPE_INTR_UP;
 +    pack.size = 8;
 +    *(long*)&pack.data[0] = (long)irq;
 +    mloop_evsock_send(&mloop, &pack);
 +}
 +
 +void mloop_evcmd_lower_intr(void *irq)
 +{
 +    struct mloop_evpack pack;
 +    memset((void*)&pack, 0, sizeof(struct mloop_evpack));
 +    pack.type = MLOOP_EVTYPE_INTR_DOWN;
 +    pack.size = 8;
 +    *(long*)&pack.data[0] = (long)irq;
 +    mloop_evsock_send(&mloop, &pack);
 +}
 +
 +void mloop_evcmd_usbkbd(int on)
 +{
 +    struct mloop_evpack pack = { MLOOP_EVTYPE_USB_ADD, 13, "keyboard" };
 +    if (on == 0) {
 +        pack.type = MLOOP_EVTYPE_USB_DEL;
 +    }
 +    mloop_evsock_send(&mloop, &pack);
 +}
 +
 +void mloop_evcmd_hostkbd(int on)
 +{
 +    struct mloop_evpack pack
 +        = {MLOOP_EVTYPE_KBD_ADD, 13, "keyboard"};
 +    if (on == 0) {
 +        pack.type = MLOOP_EVTYPE_KBD_DEL;
 +    }
 +    mloop_evsock_send(&mloop, &pack);
 +}
 +
 +void mloop_evcmd_usbdisk(char *img)
 +{
 +    struct mloop_evpack pack;
 +
 +    if (img) {
 +        if (strlen(img) > PACKET_LEN-5) {
 +            ERR("The length of disk image path is greater than "
 +                "lenth of maximum packet.\n");
 +            return;
 +        }
 +
 +        pack.type = MLOOP_EVTYPE_USB_ADD;
 +        pack.size = 5 + sprintf(pack.data, "disk:%s", img);
 +    } else {
 +        pack.type = MLOOP_EVTYPE_USB_DEL;
 +        pack.size = 5 + sprintf(pack.data, "disk:");
 +    }
 +
 +    mloop_evsock_send(&mloop, &pack);
 +}
 +
 +void mloop_evcmd_sdcard(char *img)
 +{
 +    struct mloop_evpack pack;
 +
 +    if (img) {
 +        if (strlen(img) > PACKET_LEN-5) {
 +            ERR("The length of disk image path is greater than "
 +                "lenth of maximum packet.\n");
 +            return;
 +        }
 +
 +        pack.type = MLOOP_EVTYPE_SDCARD_ATTACH;
 +        pack.size = 5 + sprintf(pack.data, "%s", img);
 +    } else {
 +        pack.type = MLOOP_EVTYPE_SDCARD_DETACH;
 +        pack.size = 5;
 +    }
 +
 +    mloop_evsock_send(&mloop, &pack);
 +}
 +
 +int mloop_evcmd_get_usbkbd_status(void)
 +{
 +    return (usbkbd && usbkbd->attached ? 1 : 0);
 +}
 +
 +void mloop_evcmd_set_usbkbd(void *dev)
 +{
 +    usbkbd = (USBDevice *)dev;
 +}
 +
 +void mloop_evcmd_set_usbdisk(void *dev)
 +{
 +    usbdisk = (USBDevice *)dev;
 +}
 +
 +void mloop_evcmd_touch(void)
 +{
 +    struct mloop_evpack pack;
 +    memset(&pack, 0, sizeof(struct mloop_evpack));
 +
 +    pack.type = MLOOP_EVTYPE_TOUCH;
 +    pack.size = 5;
 +    mloop_evsock_send(&mloop, &pack);
 +}
 +
 +void mloop_evcmd_keyboard(void *data)
 +{
 +    struct mloop_evpack pack;
 +    memset(&pack, 0, sizeof(struct mloop_evpack));
 +
 +    pack.type = MLOOP_EVTYPE_KEYBOARD;
 +    pack.size = 4 + 8;
 +    *((VirtIOKeyboard **)pack.data) = (VirtIOKeyboard *)data;
 +    mloop_evsock_send(&mloop, &pack);
 +}
 +
 +void mloop_evcmd_ramdump(void)
 +{
 +    struct mloop_evpack pack;
 +    memset(&pack, 0, sizeof(struct mloop_evpack));
 +
 +    pack.type = MLOOP_EVTYPE_RAMDUMP;
 +    pack.size = 5;
 +    mloop_evsock_send(&mloop, &pack);
 +}
diff --cc ui/input.c
Simple merge
diff --cc ui/sdl.c
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc vl.c
--- 1/vl.c
--- 2/vl.c
+++ b/vl.c
@@@ -4515,12 -4237,8 +4445,12 @@@ int main(int argc, char **argv, char **
  
      qdev_machine_init();
  
 +#ifdef CONFIG_MARU
 +    // Returned variable points different address from input variable.
 +    kernel_cmdline = prepare_maru_devices(kernel_cmdline);
 +#endif
      QEMUMachineInitArgs args = { .ram_size = ram_size,
-                                  .boot_device = boot_order,
+                                  .boot_order = boot_order,
                                   .kernel_filename = kernel_filename,
                                   .kernel_cmdline = kernel_cmdline,
                                   .initrd_filename = initrd_filename,
diff --cc xen-all.c
Simple merge