Merge tag 'v1.2.0' into tizen-arm
authorEvgeny Voevodin <e.voevodin@samsung.com>
Mon, 8 Oct 2012 08:59:35 +0000 (12:59 +0400)
committerEvgeny Voevodin <e.voevodin@samsung.com>
Mon, 8 Oct 2012 09:02:06 +0000 (13:02 +0400)
Tag for 1.2.0

77 files changed:
1  2 
.gitignore
Makefile
Makefile.target
arch_init.c
arch_init.h
audio/audio.c
block/raw-win32.c
blockdev.c
configure
cpu-defs.h
cpu-exec.c
cpus.c
default-configs/arm-softmmu.mak
exec-all.h
exec.c
hw/Makefile.objs
hw/acpi_piix4.c
hw/arm/Makefile.objs
hw/exynos4210.c
hw/exynos4210.h
hw/exynos4210_gic.c
hw/exynos4210_i2s.c
hw/pc.c
hw/pc.h
hw/pc_sysfw.c
hw/pci.c
hw/pci.h
hw/qdev-properties.c
hw/qdev.h
hw/usb/dev-hid.c
hw/usb/dev-storage.c
hw/vga-pci.c
hw/vga_int.h
hw/virtio-balloon.c
hw/virtio-balloon.h
hw/virtio-blk.c
hw/virtio-blk.h
hw/virtio-mmio.c
hw/virtio-net.c
hw/virtio-net.h
hw/virtio-pci-new.c
hw/virtio-pci.c
hw/virtio-pci.h
hw/virtio-serial-bus.c
hw/virtio-serial.h
hw/virtio-transport.c
hw/virtio-transport.h
hw/virtio.c
hw/virtio.h
hw/yagl_device.c
kvm.h
net/tap-win32.c
os-win32.c
oslib-posix.c
qemu-char.c
qemu-options.hx
softmmu_template.h
sysemu.h
target-arm/helper.c
target-arm/op_helper.c
target-i386/translate.c
tcg/tcg.c
tcg/tcg.h
tizen/emulator_configure.sh
tizen/src/Makefile.tizen
tizen/src/Makefile.tizen.arm
tizen/src/Makefile.tizen.i386
tizen/src/hw/maru_arm.h
tizen/src/hw/maru_arm_board.c
tizen/src/hw/maru_arm_soc.c
tizen/src/hw/maru_board.c
tizen/src/hw/maru_pm.c
tizen/src/hw/maru_pm.h
tizen/src/hw/maru_vga.c
tizen/src/hw/maru_vga_int.h
tizen/src/option.h
vl.c

diff --cc .gitignore
Simple merge
diff --cc Makefile
Simple merge
diff --cc Makefile.target
index 03d1bfe,7892a8d..b4b0acd
mode 100755,100644..100755
@@@ -202,356 -138,39 +138,177 @@@ QEMU_CFLAGS += $(VNC_JPEG_CFLAGS
  QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
  
  # xen support
- obj-$(CONFIG_XEN) += xen-all.o xen_machine_pv.o xen_domainbuild.o xen-mapcache.o
+ obj-$(CONFIG_XEN) += xen-all.o xen-mapcache.o
  obj-$(CONFIG_NO_XEN) += xen-stub.o
  
- obj-i386-$(CONFIG_XEN) += xen_platform.o xen_apic.o
 +# HAX support
 +obj-$(CONFIG_HAX) += hax-all.o hax-windows.o
 +obj-$(CONFIG_NO_HAX) += hax-stub.o
 +ifdef CONFIG_DARWIN
 +obj-$(CONFIG_HAX) += \
 +        hax-all.o       \
 +        hax-darwin.o
 +endif
 +
- # Inter-VM PCI shared memory
- CONFIG_IVSHMEM =
- ifeq ($(CONFIG_KVM), y)
-   ifeq ($(CONFIG_PCI), y)
-     CONFIG_IVSHMEM = y
-   endif
- endif
- obj-$(CONFIG_IVSHMEM) += ivshmem.o
- # Generic hotplugging
- obj-y += device-hotplug.o
  # Hardware support
- obj-i386-y += mc146818rtc.o pc.o
- obj-i386-y += apic_common.o apic.o kvmvapic.o
- obj-i386-y += sga.o ioapic_common.o ioapic.o piix_pci.o
- obj-i386-y += vmport.o
- obj-i386-y += pci-hotplug.o smbios.o wdt_ib700.o
- obj-i386-y += debugcon.o multiboot.o
- obj-i386-y += pc_piix.o
- obj-i386-y += pc_sysfw.o
- obj-i386-$(CONFIG_KVM) += kvm/clock.o kvm/apic.o kvm/i8259.o kvm/ioapic.o kvm/i8254.o
- obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
- # shared objects
- obj-ppc-y = ppc.o ppc_booke.o
- # PREP target
- obj-ppc-y += mc146818rtc.o
- obj-ppc-y += ppc_prep.o
- # OldWorld PowerMac
- obj-ppc-y += ppc_oldworld.o
- # NewWorld PowerMac
- obj-ppc-y += ppc_newworld.o
- # IBM pSeries (sPAPR)
- obj-ppc-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
- obj-ppc-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
- obj-ppc-$(CONFIG_PSERIES) += spapr_pci.o device-hotplug.o pci-hotplug.o
- # PowerPC 4xx boards
- obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
- obj-ppc-y += ppc440_bamboo.o
- # PowerPC E500 boards
- obj-ppc-y += ppce500_mpc8544ds.o mpc8544_guts.o ppce500_spin.o
- # PowerPC 440 Xilinx ML507 reference board.
- obj-ppc-y += virtex_ml507.o
- obj-ppc-$(CONFIG_KVM) += kvm_ppc.o
- obj-ppc-$(CONFIG_FDT) += device_tree.o
- # PowerPC OpenPIC
- obj-ppc-y += openpic.o
- # Xilinx PPC peripherals
- obj-ppc-y += xilinx_intc.o
- obj-ppc-y += xilinx_timer.o
- obj-ppc-y += xilinx_uartlite.o
- obj-ppc-y += xilinx_ethlite.o
- # LM32 boards
- obj-lm32-y += lm32_boards.o
- obj-lm32-y += milkymist.o
- # LM32 peripherals
- obj-lm32-y += lm32_pic.o
- obj-lm32-y += lm32_juart.o
- obj-lm32-y += lm32_timer.o
- obj-lm32-y += lm32_uart.o
- obj-lm32-y += lm32_sys.o
- obj-lm32-y += milkymist-ac97.o
- obj-lm32-y += milkymist-hpdmc.o
- obj-lm32-y += milkymist-memcard.o
- obj-lm32-y += milkymist-minimac2.o
- obj-lm32-y += milkymist-pfpu.o
- obj-lm32-y += milkymist-softusb.o
- obj-lm32-y += milkymist-sysctl.o
- obj-lm32-$(CONFIG_OPENGL) += milkymist-tmu2.o
- obj-lm32-y += milkymist-uart.o
- obj-lm32-y += milkymist-vgafb.o
- obj-lm32-y += framebuffer.o
- obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
- obj-mips-y += mips_addr.o mips_timer.o mips_int.o
- obj-mips-y += gt64xxx.o mc146818rtc.o
- obj-mips-$(CONFIG_FULONG) += bonito.o vt82c686.o mips_fulong2e.o
- obj-microblaze-y = petalogix_s3adsp1800_mmu.o
- obj-microblaze-y += petalogix_ml605_mmu.o
- obj-microblaze-y += microblaze_boot.o
- obj-microblaze-y += microblaze_pic_cpu.o
- obj-microblaze-y += xilinx_intc.o
- obj-microblaze-y += xilinx_timer.o
- obj-microblaze-y += xilinx_uartlite.o
- obj-microblaze-y += xilinx_ethlite.o
- obj-microblaze-y += xilinx_axidma.o
- obj-microblaze-y += xilinx_axienet.o
- obj-microblaze-$(CONFIG_FDT) += device_tree.o
- # Boards
- obj-cris-y = cris_pic_cpu.o
- obj-cris-y += cris-boot.o
- obj-cris-y += axis_dev88.o
- # IO blocks
- obj-cris-y += etraxfs_dma.o
- obj-cris-y += etraxfs_pic.o
- obj-cris-y += etraxfs_eth.o
- obj-cris-y += etraxfs_timer.o
- obj-cris-y += etraxfs_ser.o
  ifeq ($(TARGET_ARCH), sparc64)
- obj-sparc-y = sun4u.o apb_pci.o
- obj-sparc-y += mc146818rtc.o
+ obj-y += hw/sparc64/
  else
- obj-sparc-y = sun4m.o lance.o tcx.o sun4m_iommu.o slavio_intctl.o
- obj-sparc-y += slavio_timer.o slavio_misc.o sparc32_dma.o
- obj-sparc-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o leon3.o
- # GRLIB
- obj-sparc-y += grlib_gptimer.o grlib_irqmp.o grlib_apbuart.o
+ obj-y += hw/$(TARGET_BASE_ARCH)/
  endif
  
- obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o
- obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
- obj-arm-y += versatile_pci.o
- obj-arm-y += versatile_i2c.o
- obj-arm-y += cadence_uart.o
- obj-arm-y += cadence_ttc.o
- obj-arm-y += cadence_gem.o
- obj-arm-y += xilinx_zynq.o zynq_slcr.o
- obj-arm-y += arm_gic.o
- obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
- obj-arm-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o
- obj-arm-y += exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o
- obj-arm-y += exynos4210_pmu.o exynos4210_mct.o exynos4210_fimd.o
- obj-arm-y += exynos4210_rtc.o exynos4210_cmu.o exynos4210_g3d.o
- obj-arm-y += exynos4210_i2c.o exynos4210_i2s.o exynos4210_audio.o
- obj-arm-y += ac97.o
- obj-arm-y += arm_l2x0.o
- obj-arm-y += arm_mptimer.o a15mpcore.o
- obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
- obj-arm-y += highbank.o
- obj-arm-y += pl061.o
- obj-arm-y += xgmac.o
- obj-arm-y += arm-semi.o
- obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
- obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
- obj-arm-y += gumstix.o
- obj-arm-y += zaurus.o ide/microdrive.o spitz.o tosa.o tc6393xb.o
- obj-arm-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-arm-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-arm-y += omap_sx1.o palm.o tsc210x.o
- obj-arm-y += nseries.o blizzard.o onenand.o cbus.o tusb6010.o usb/hcd-musb.o
- obj-arm-y += mst_fpga.o mainstone.o
- obj-arm-y += z2.o
- obj-arm-y += musicpal.o bitbang_i2c.o marvell_88w8618_audio.o
- obj-arm-y += framebuffer.o
- obj-arm-y += vexpress.o
- obj-arm-y += strongarm.o
- obj-arm-y += collie.o
- obj-arm-y += pl041.o lm4549.o
- obj-arm-$(CONFIG_FDT) += device_tree.o
- obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
- obj-sh4-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o
- obj-sh4-y += ide/mmio.o
- obj-m68k-y = an5206.o mcf5206.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
- obj-m68k-y += m68k-semi.o dummy_m68k.o
- obj-s390x-y = s390-virtio-bus.o s390-virtio.o
- obj-alpha-y = mc146818rtc.o
- obj-alpha-y += alpha_pci.o alpha_dp264.o alpha_typhoon.o
- obj-xtensa-y += xtensa_pic.o
- obj-xtensa-y += xtensa_sim.o
- obj-xtensa-y += xtensa_lx60.o
- obj-xtensa-y += xtensa-semi.o
- obj-xtensa-y += core-dc232b.o
- obj-xtensa-y += core-dc233c.o
- obj-xtensa-y += core-fsf.o
  main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
  
monitor.o: hmp-commands.h qmp-commands-old.h
GENERATED_HEADERS += hmp-commands.h qmp-commands-old.h
  
- $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS)
+ endif # CONFIG_SOFTMMU
  
- obj-y += $(addprefix ../, $(universal-obj-y))
- obj-y += $(addprefix ../, $(common-obj-y))
- obj-y += $(addprefix ../libdis/, $(libdis-y))
- obj-y += $(libobj-y)
- obj-y += $(addprefix $(HWDIR)/, $(hw-obj-y))
- obj-y += $(addprefix ../, $(trace-obj-y))
+ nested-vars += obj-y
  
- obj-$(TARGET_BASE_ARCH)-y += yagl_device.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_log.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_process.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_thread.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_server.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_ref.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_mem.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_mem_egl.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_mem_gl.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_mem_transfer.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_event.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_handle_gen.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_dyn_lib.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_api.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_vector.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_avl.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_range_list.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_egl_driver.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles_driver.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles1_driver.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles2_driver.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_egl_interface.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_client_interface.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_client_context.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_resource.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_resource_list.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_object.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_namespace.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_sharegroup.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_stats.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_compiled_transfer.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_egl_native_config.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_egl_surface_attribs.o
 +# Makefile for TIZEN-maru
 +ifdef CONFIG_MARU
 +include $(SRC_PATH)/tizen/src/Makefile.tizen
 +endif
 +##
 +
 +ifdef CONFIG_BUILD_YAGL
 +
 +# YaGL
 +QEMU_CFLAGS += -I$(SRC_PATH)/hw/yagl_inc
 +
 +$(call set-vpath, $(SRC_PATH)/hw/yagl_apis/egl: \
 +                  $(SRC_PATH)/hw/yagl_apis/gles: \
 +                  $(SRC_PATH)/hw/yagl_apis/gles1: \
 +                  $(SRC_PATH)/hw/yagl_apis/gles2: \
 +                  $(SRC_PATH)/hw/yagl_drivers/egl_glx: \
 +                  $(SRC_PATH)/hw/yagl_drivers/gles_ogl: \
 +                  $(SRC_PATH)/hw/yagl_drivers/gles1_ogl: \
 +                  $(SRC_PATH)/hw/yagl_drivers/gles2_ogl)
 +
- obj-$(TARGET_BASE_ARCH)-y += yagl_egl_api.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_egl_api_ps.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_egl_api_ts.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_egl_calls.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_egl_display.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_egl_config.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_egl_surface.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_egl_context.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_egl_validate.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_host_egl_calls.o
++obj-y += yagl_device.o
++obj-y += yagl_log.o
++obj-y += yagl_process.o
++obj-y += yagl_thread.o
++obj-y += yagl_server.o
++obj-y += yagl_ref.o
++obj-y += yagl_mem.o
++obj-y += yagl_mem_egl.o
++obj-y += yagl_mem_gl.o
++obj-y += yagl_mem_transfer.o
++obj-y += yagl_event.o
++obj-y += yagl_handle_gen.o
++obj-y += yagl_dyn_lib.o
++obj-y += yagl_api.o
++obj-y += yagl_vector.o
++obj-y += yagl_avl.o
++obj-y += yagl_range_list.o
++obj-y += yagl_egl_driver.o
++obj-y += yagl_gles_driver.o
++obj-y += yagl_gles1_driver.o
++obj-y += yagl_gles2_driver.o
++obj-y += yagl_egl_interface.o
++obj-y += yagl_client_interface.o
++obj-y += yagl_client_context.o
++obj-y += yagl_resource.o
++obj-y += yagl_resource_list.o
++obj-y += yagl_object.o
++obj-y += yagl_namespace.o
++obj-y += yagl_sharegroup.o
++obj-y += yagl_stats.o
++obj-y += yagl_compiled_transfer.o
++obj-y += yagl_egl_native_config.o
++obj-y += yagl_egl_surface_attribs.o
 +# EGL api
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles_context.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles_array.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles_buffer.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles_texture.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles_framebuffer.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles_renderbuffer.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles_texture_unit.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles_validate.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_host_gles_calls.o
++obj-y += yagl_egl_api.o
++obj-y += yagl_egl_api_ps.o
++obj-y += yagl_egl_api_ts.o
++obj-y += yagl_egl_calls.o
++obj-y += yagl_egl_display.o
++obj-y += yagl_egl_config.o
++obj-y += yagl_egl_surface.o
++obj-y += yagl_egl_context.o
++obj-y += yagl_egl_validate.o
++obj-y += yagl_host_egl_calls.o
 +# GLES common api
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles1_calls.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_host_gles1_calls.o
++obj-y += yagl_gles_context.o
++obj-y += yagl_gles_array.o
++obj-y += yagl_gles_buffer.o
++obj-y += yagl_gles_texture.o
++obj-y += yagl_gles_framebuffer.o
++obj-y += yagl_gles_renderbuffer.o
++obj-y += yagl_gles_texture_unit.o
++obj-y += yagl_gles_validate.o
++obj-y += yagl_host_gles_calls.o
 +# GLESv1_CM api
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles2_api.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles2_api_ps.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles2_api_ts.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles2_calls.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles2_context.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles2_shader.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles2_program.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles2_validate.o
- obj-$(TARGET_BASE_ARCH)-y += yagl_host_gles2_calls.o
++obj-y += yagl_gles1_calls.o
++obj-y += yagl_host_gles1_calls.o
 +# GLESv2 api
- obj-$(TARGET_BASE_ARCH)-y += yagl_egl_glx.o
++obj-y += yagl_gles2_api.o
++obj-y += yagl_gles2_api_ps.o
++obj-y += yagl_gles2_api_ts.o
++obj-y += yagl_gles2_calls.o
++obj-y += yagl_gles2_context.o
++obj-y += yagl_gles2_shader.o
++obj-y += yagl_gles2_program.o
++obj-y += yagl_gles2_validate.o
++obj-y += yagl_host_gles2_calls.o
 +# EGL GLX driver
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles_ogl.o
++obj-y += yagl_egl_glx.o
 +# GLES OpenGL common driver
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles1_ogl.o
++obj-y += yagl_gles_ogl.o
 +# GLESv1_CM OpenGL driver
- obj-$(TARGET_BASE_ARCH)-y += yagl_gles2_ogl.o
++obj-y += yagl_gles1_ogl.o
 +# GLESv2 OpenGL driver
- endif # CONFIG_SOFTMMU
++obj-y += yagl_gles2_ogl.o
 +
 +endif
 +
 +ifdef CONFIG_BUILD_GLES
 +
 +gles2.o: gles2.c gles2.h
 +gles2_egl.o: gles2_egl.c gles2.h
 +gles2_es11.o: gles2_es11.c gles2.h
 +gles2_es20.o: gles2_es20.c gles2.h
 +gles2_kernel_calls.o: gles2_kernel_calls.c gles2.h gles2_calls.h
 +gles2_egl_calls.o: gles2_egl_calls.c gles2.h gles2_calls.h
 +gles2_es11_calls.o: gles2_es11_calls.c gles2.h gles2_calls.h
 +gles2_es20_calls.o: gles2_es20_calls.c gles2.h gles2_calls.h
 +obj-y += gles2.o gles2_egl.o gles2_es11.o gles2_es20.o
 +obj-y += gles2_kernel_calls.o  gles2_egl_calls.o gles2_es11_calls.o
 +obj-y += gles2_es20_calls.o
 +
 +ifdef QEMU_PROGW
 +GLESLIBS_LINK_LIST:=$(wildcard $(CONFIG_GLES_LIBDIR)/*.dll)
 +else
 +GLESLIBS_LINK_LIST:=$(wildcard $(CONFIG_GLES_LIBDIR)/lib*)
 +endif
 +
 +$(GLESLIBS_LINK_LIST):
 +
 +GLESLIBS_RUNTIME_LIST:=$(addprefix ./,$(notdir $(GLESLIBS_LINK_LIST)))
 +
 +$(GLESLIBS_RUNTIME_LIST): $(GLESLIBS_LINK_LIST)
 +      @cp -dpu -t ./ $(GLESLIBS_LINK_LIST)
 +
 +$(QEMU_PROG): $(GLESLIBS_RUNTIME_LIST)
 +
 +endif # CONFIG_BUILD_GLES
 +
+ # This resolves all nested paths, so it must come last
+ include $(SRC_PATH)/Makefile.objs
  
- ifndef CONFIG_LINUX_USER
- ifndef CONFIG_BSD_USER
- # libcacard needs qemu-thread support, and besides is only needed by devices
- # so not requires with linux-user / bsd-user targets
- obj-$(CONFIG_SMARTCARD_NSS) += $(addprefix ../libcacard/, $(libcacard-y))
- endif # CONFIG_BSD_USER
- endif # CONFIG_LINUX_USER
+ all-obj-y = $(obj-y)
+ all-obj-y += $(addprefix ../, $(universal-obj-y))
  
- obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o
+ ifdef CONFIG_SOFTMMU
+ all-obj-y += $(addprefix ../, $(common-obj-y))
+ all-obj-y += $(addprefix ../libdis/, $(libdis-y))
+ all-obj-y += $(addprefix $(HWDIR)/, $(hw-obj-y))
+ all-obj-y += $(addprefix ../, $(trace-obj-y))
+ else
+ all-obj-y += $(addprefix ../libuser/, $(user-obj-y))
+ all-obj-y += $(addprefix ../libdis-user/, $(libdis-y))
+ endif #CONFIG_LINUX_USER
  
  ifdef QEMU_PROGW
  # The linker builds a windows executable. Make also a console executable.
diff --cc arch_init.c
@@@ -765,11 -1082,12 +1082,21 @@@ int xen_available(void
  #endif
  }
  
+ TargetInfo *qmp_query_target(Error **errp)
+ {
+     TargetInfo *info = g_malloc0(sizeof(*info));
+     info->arch = TARGET_TYPE;
+     return info;
+ }
++
 +int hax_available(void)
 +{
 +#ifdef CONFIG_HAX
 +    return 1;
 +#else
 +    return 0;
 +#endif
 +}
diff --cc arch_init.h
@@@ -29,5 -33,7 +33,6 @@@ void audio_init(ISABus *isa_bus, PCIBu
  int tcg_available(void);
  int kvm_available(void);
  int xen_available(void);
 -
 +int hax_available(void);
+ CpuDefinitionInfoList GCC_WEAK_DECL *arch_query_cpu_definitions(Error **errp);
 -
  #endif
diff --cc audio/audio.c
Simple merge
Simple merge
diff --cc blockdev.c
Simple merge
diff --cc configure
+++ b/configure
@@@ -144,11 -169,8 +169,10 @@@ xfs="
  
  vhost_net="no"
  kvm="no"
 +hax="no"
  gprof="no"
  debug_tcg="no"
- debug_mon="no"
 +debug_gles="no"
  debug="no"
  strip_opt="yes"
  tcg_interpreter="no"
@@@ -203,11 -218,7 +227,12 @@@ zlib="yes
  guest_agent="yes"
  libiscsi=""
  coroutine=""
+ seccomp=""
 +gl="yes"
 +
 +# for TIZEN-maru 
 +maru="no"
 +#
  
  # parse CC options first
  for opt do
@@@ -872,10 -865,10 +913,14 @@@ for opt d
    ;;
    --disable-guest-agent) guest_agent="no"
    ;;
+   --enable-seccomp) seccomp="yes"
+   ;;
+   --disable-seccomp) seccomp="no"
+   ;;
 +# for TIZEN-maru
 +  --enable-maru) maru="yes"
 +  ;;
 +#
    *) echo "ERROR: unknown option $opt"; show_help="yes"
    ;;
    esac
@@@ -3129,23 -3162,11 +3265,24 @@@ echo "xfsctl support    $xfs
  echo "nss used          $smartcard_nss"
  echo "usb net redir     $usb_redir"
  echo "OpenGL support    $opengl"
 +echo "OpenGLES support  $opengles"
 +if test "$opengles" = "yes"; then
 +  echo "OpenGLES incdir   $glesincdir"
 +  echo "OpenGLES libdir   $gleslibdir"
 +  echo "OpenGLES debug    $debug_gles"
 +fi
 +echo "EFence support    $efence"
 +echo "YaGL support      $yagl"
 +echo "YaGL stats        $yagl_stats"
  echo "libiscsi support  $libiscsi"
  echo "build guest agent $guest_agent"
+ echo "seccomp support   $seccomp"
  echo "coroutine backend $coroutine_backend"
  
 +# for TIZEN-maru
 +echo "TIZEN-maru support $maru"
 +#
 +
  if test "$sdl_too_old" = "yes"; then
  echo "-> Your SDL version is too old - please upgrade to have SDL support"
  fi
@@@ -3884,40 -3884,10 +4039,44 @@@ case "$target_arch2" i
        fi
      fi
  esac
+ case "$target_arch2" in
+   i386|x86_64)
+     echo "CONFIG_HAVE_GET_MEMORY_MAPPING=y" >> $config_target_mak
+ esac
 +if test "$hax" = "yes" ; then
 +  if test "$target_softmmu" = "yes" ; then
 +    case "$target_arch2" in
 +    i386|x86_64)
 +      echo "CONFIG_HAX=y" >> $config_target_mak
 +    ;;
 +    *)
 +      echo "CONFIG_NO_HAX=y" >> $config_target_mak
 +    ;;
 +    esac
 +  else
 +    echo "CONFIG_NO_HAX=y" >> $config_target_mak
 +  fi
 +fi
 +if test "$ldst_optimization" = "yes" ; then
 +  if test "$target_arch2" = "i386" -o "$target_arch2" = "x86_64"; then
 +    echo "CONFIG_QEMU_LDST_OPTIMIZATION=y" >> $config_target_mak
 +  fi
 +fi
 +if test "$gl" = "yes" ; then
 +  case "$target_arch2" in
 +  i386|x86_64)
 +    echo "CONFIG_GL=y" >> $config_target_mak
 +    if test "$mingw32" = "yes" ; then
 +      echo "LIBS+=-lopengl32 -lglu32" >> $config_target_mak
 +    else
 +      echo "LIBS+=-lGLU -ldl" >> $config_target_mak
 +    fi
 +  ;;
 +  *)
 +    echo "CONFIG_NO_GL=y" >> $config_target_mak
 +  ;;
 +  esac
 +fi
  if test "$target_arch2" = "ppc64" -a "$fdt" = "yes"; then
    echo "CONFIG_PSERIES=y" >> $config_target_mak
  fi
diff --cc cpu-defs.h
Simple merge
diff --cc cpu-exec.c
@@@ -183,26 -179,11 +180,29 @@@ static void cpu_handle_debug_exception(
  
  volatile sig_atomic_t exit_request;
  
 +/*
 + * QEMU emulate can happens because of MMIO or emulation mode, i.e. non-PG mode,
 + * when it's because of MMIO, the MMIO, the interrupt should not be emulated,
 + * because MMIO is emulated for only one instruction now and then back to
 + * HAX kernel
 + */
 +int need_handle_intr_request(CPUArchState *env)
 +{
 +#ifdef CONFIG_HAX
 +    if (!hax_enabled() || hax_vcpu_emulation_mode(env))
 +        return env->interrupt_request;
 +    return 0;
 +#else
 +    return env->interrupt_request;
 +#endif
 +}
 +
 +
  int cpu_exec(CPUArchState *env)
  {
+ #ifdef TARGET_PPC
+     CPUState *cpu = ENV_GET_CPU(env);
+ #endif
      int ret, interrupt_request;
      TranslationBlock *tb;
      uint8_t *tc_ptr;
diff --cc cpus.c
--- 1/cpus.c
--- 2/cpus.c
+++ b/cpus.c
  
  static CPUArchState *next_cpu;
  
 -        kvm_async_interrupts_enabled()) {
+ static bool cpu_thread_is_idle(CPUArchState *env)
+ {
+     if (env->stop || env->queued_work_first) {
+         return false;
+     }
+     if (env->stopped || !runstate_is_running()) {
+         return true;
+     }
+     if (!env->halted || qemu_cpu_has_work(env) ||
++        kvm_async_interrupts_enabled() || hax_enabled()) {
+         return false;
+     }
+     return true;
+ }
+ static bool all_cpu_threads_idle(void)
+ {
+     CPUArchState *env;
+     for (env = first_cpu; env != NULL; env = env->next_cpu) {
+         if (!cpu_thread_is_idle(env)) {
+             return false;
+         }
+     }
+     return true;
+ }
  /***********************************************************/
  /* guest cycle counter */
  
@@@ -976,14 -985,11 +986,15 @@@ void resume_all_vcpus(void
  static void qemu_tcg_init_vcpu(void *_env)
  {
      CPUArchState *env = _env;
+     CPUState *cpu = ENV_GET_CPU(env);
  
 +#ifdef        CONFIG_HAX
 +      if (hax_enabled())
 +              hax_init_vcpu(env);
 +#endif
      /* share a single thread for all cpus with TCG */
      if (!tcg_cpu_thread) {
-         env->thread = g_malloc0(sizeof(QemuThread));
+         cpu->thread = g_malloc0(sizeof(QemuThread));
          env->halt_cond = g_malloc0(sizeof(QemuCond));
          qemu_cond_init(env->halt_cond);
          tcg_halt_cond = env->halt_cond;
@@@ -28,3 -27,21 +28,23 @@@ CONFIG_SMC91C111=
  CONFIG_DS1338=y
  CONFIG_PFLASH_CFI01=y
  CONFIG_PFLASH_CFI02=y
+ CONFIG_ARM_TIMER=y
+ CONFIG_PL011=y
+ CONFIG_PL022=y
+ CONFIG_PL031=y
+ CONFIG_PL041=y
+ CONFIG_PL050=y
+ CONFIG_PL061=y
+ CONFIG_PL080=y
+ CONFIG_PL110=y
+ CONFIG_PL181=y
+ CONFIG_PL190=y
+ CONFIG_PL310=y
+ CONFIG_CADENCE=y
+ CONFIG_XGMAC=y
+ CONFIG_VERSATILE_PCI=y
+ CONFIG_VERSATILE_I2C=y
++
++CONFIG_SOUND=y
diff --cc exec-all.h
Simple merge
diff --cc exec.c
--- 1/exec.c
--- 2/exec.c
+++ b/exec.c
@@@ -2645,43 -2551,14 +2552,31 @@@ ram_addr_t qemu_ram_alloc_from_ptr(ram_
              exit(1);
  #endif
          } else {
- #if defined(TARGET_S390X) && defined(CONFIG_KVM)
-             /* S390 KVM requires the topmost vma of the RAM to be smaller than
-                an system defined value, which is at least 256GB. Larger systems
-                have larger values. We put the guest between the end of data
-                segment (system break) and this value. We use 32GB as a base to
-                have enough room for the system break to grow. */
-             new_block->host = mmap((void*)0x800000000, size,
-                                    PROT_EXEC|PROT_READ|PROT_WRITE,
-                                    MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
-             if (new_block->host == MAP_FAILED) {
-                 fprintf(stderr, "Allocating RAM failed\n");
-                 abort();
-             }
- #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_vmalloc(size);
              } else {
                  new_block->host = qemu_vmalloc(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
              }
- #endif
              qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE);
          }
      }
index 0000000,6dfebd2..2eb520f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,204 +1,208 @@@
+ hw-obj-y = usb/ ide/
+ hw-obj-y += loader.o
+ hw-obj-$(CONFIG_VIRTIO) += virtio-console.o
+ hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
++hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci-new.o
++hw-obj-$(CONFIG_VIRTIO) += virtio-transport.o
++hw-obj-$(CONFIG_VIRTIO) += virtio-mmio.o
+ hw-obj-y += fw_cfg.o
+ hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o pci_bridge_dev.o
+ hw-obj-$(CONFIG_PCI) += msix.o msi.o
+ hw-obj-$(CONFIG_PCI) += shpc.o
+ hw-obj-$(CONFIG_PCI) += slotid_cap.o
+ hw-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o
+ hw-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o
+ hw-obj-y += watchdog.o
+ hw-obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
+ hw-obj-$(CONFIG_ECC) += ecc.o
+ hw-obj-$(CONFIG_NAND) += nand.o
+ hw-obj-$(CONFIG_PFLASH_CFI01) += pflash_cfi01.o
+ hw-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
+ hw-obj-$(CONFIG_M48T59) += m48t59.o
+ hw-obj-$(CONFIG_ESCC) += escc.o
+ hw-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
+ hw-obj-$(CONFIG_SERIAL) += serial.o
+ hw-obj-$(CONFIG_PARALLEL) += parallel.o
+ hw-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
+ hw-obj-$(CONFIG_PCSPK) += pcspk.o
+ hw-obj-$(CONFIG_PCKBD) += pckbd.o
+ hw-obj-$(CONFIG_FDC) += fdc.o
+ hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
+ hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
+ hw-obj-$(CONFIG_DMA) += dma.o
+ hw-obj-$(CONFIG_I82374) += i82374.o
+ hw-obj-$(CONFIG_HPET) += hpet.o
+ hw-obj-$(CONFIG_APPLESMC) += applesmc.o
+ hw-obj-$(CONFIG_SMARTCARD) += ccid-card-passthru.o
+ hw-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
+ hw-obj-$(CONFIG_I8259) += i8259_common.o i8259.o
+ # PPC devices
+ hw-obj-$(CONFIG_PREP_PCI) += prep_pci.o
+ hw-obj-$(CONFIG_I82378) += i82378.o
+ # Mac shared devices
+ hw-obj-$(CONFIG_MACIO) += macio.o
+ hw-obj-$(CONFIG_CUDA) += cuda.o
+ hw-obj-$(CONFIG_ADB) += adb.o
+ hw-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o
+ hw-obj-$(CONFIG_MAC_DBDMA) += mac_dbdma.o
+ # OldWorld PowerMac
+ hw-obj-$(CONFIG_HEATHROW_PIC) += heathrow_pic.o
+ hw-obj-$(CONFIG_GRACKLE_PCI) += grackle_pci.o
+ # NewWorld PowerMac
+ hw-obj-$(CONFIG_UNIN_PCI) += unin_pci.o
+ hw-obj-$(CONFIG_DEC_PCI) += dec_pci.o
+ # PowerPC E500 boards
+ hw-obj-$(CONFIG_PPCE500_PCI) += ppce500_pci.o
+ # MIPS devices
+ hw-obj-$(CONFIG_PIIX4) += piix4.o
+ hw-obj-$(CONFIG_G364FB) += g364fb.o
+ hw-obj-$(CONFIG_JAZZ_LED) += jazz_led.o
+ # Xilinx devices
+ hw-obj-$(CONFIG_XILINX) += xilinx_intc.o
+ hw-obj-$(CONFIG_XILINX) += xilinx_timer.o
+ hw-obj-$(CONFIG_XILINX) += xilinx_uartlite.o
+ hw-obj-$(CONFIG_XILINX_AXI) += xilinx_axidma.o
+ hw-obj-$(CONFIG_XILINX_AXI) += xilinx_axienet.o
+ hw-obj-$(CONFIG_XILINX_AXI) += stream.o
+ # PKUnity SoC devices
+ hw-obj-$(CONFIG_PUV3) += puv3_intc.o
+ hw-obj-$(CONFIG_PUV3) += puv3_ost.o
+ hw-obj-$(CONFIG_PUV3) += puv3_gpio.o
+ hw-obj-$(CONFIG_PUV3) += puv3_pm.o
+ hw-obj-$(CONFIG_PUV3) += puv3_dma.o
+ # ARM devices
+ hw-obj-$(CONFIG_ARM_TIMER) += arm_timer.o
+ hw-obj-$(CONFIG_PL011) += pl011.o
+ hw-obj-$(CONFIG_PL022) += pl022.o
+ hw-obj-$(CONFIG_PL031) += pl031.o
+ hw-obj-$(CONFIG_PL041) += pl041.o lm4549.o
+ hw-obj-$(CONFIG_PL050) += pl050.o
+ hw-obj-$(CONFIG_PL061) += pl061.o
+ hw-obj-$(CONFIG_PL080) += pl080.o
+ hw-obj-$(CONFIG_PL110) += pl110.o
+ hw-obj-$(CONFIG_PL181) += pl181.o
+ hw-obj-$(CONFIG_PL190) += pl190.o
+ hw-obj-$(CONFIG_PL310) += arm_l2x0.o
+ hw-obj-$(CONFIG_VERSATILE_PCI) += versatile_pci.o
+ hw-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o
+ hw-obj-$(CONFIG_CADENCE) += cadence_uart.o
+ hw-obj-$(CONFIG_CADENCE) += cadence_ttc.o
+ hw-obj-$(CONFIG_CADENCE) += cadence_gem.o
+ hw-obj-$(CONFIG_XGMAC) += xgmac.o
+ # PCI watchdog devices
+ hw-obj-$(CONFIG_PCI) += wdt_i6300esb.o
+ hw-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o
+ # PCI network cards
+ hw-obj-$(CONFIG_NE2000_PCI) += ne2000.o
+ hw-obj-$(CONFIG_EEPRO100_PCI) += eepro100.o
+ hw-obj-$(CONFIG_PCNET_PCI) += pcnet-pci.o
+ hw-obj-$(CONFIG_PCNET_COMMON) += pcnet.o
+ hw-obj-$(CONFIG_E1000_PCI) += e1000.o
+ hw-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o
+ hw-obj-$(CONFIG_SMC91C111) += smc91c111.o
+ hw-obj-$(CONFIG_LAN9118) += lan9118.o
+ hw-obj-$(CONFIG_NE2000_ISA) += ne2000-isa.o
+ hw-obj-$(CONFIG_OPENCORES_ETH) += opencores_eth.o
+ # SCSI layer
+ hw-obj-$(CONFIG_LSI_SCSI_PCI) += lsi53c895a.o
+ hw-obj-$(CONFIG_MEGASAS_SCSI_PCI) += megasas.o
+ hw-obj-$(CONFIG_ESP) += esp.o
+ hw-obj-$(CONFIG_ESP_PCI) += esp-pci.o
+ hw-obj-y += sysbus.o isa-bus.o
+ hw-obj-y += qdev-addr.o
+ # VGA
+ hw-obj-$(CONFIG_VGA_PCI) += vga-pci.o
+ hw-obj-$(CONFIG_VGA_ISA) += vga-isa.o
+ hw-obj-$(CONFIG_VGA_ISA_MM) += vga-isa-mm.o
+ hw-obj-$(CONFIG_VMWARE_VGA) += vmware_vga.o
+ hw-obj-$(CONFIG_VMMOUSE) += vmmouse.o
+ hw-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o
+ hw-obj-$(CONFIG_RC4030) += rc4030.o
+ hw-obj-$(CONFIG_DP8393X) += dp8393x.o
+ hw-obj-$(CONFIG_DS1225Y) += ds1225y.o
+ hw-obj-$(CONFIG_MIPSNET) += mipsnet.o
+ hw-obj-y += null-machine.o
+ # Sound
+ sound-obj-y =
+ sound-obj-$(CONFIG_SB16) += sb16.o
+ sound-obj-$(CONFIG_ES1370) += es1370.o
+ sound-obj-$(CONFIG_AC97) += ac97.o
+ sound-obj-$(CONFIG_ADLIB) += fmopl.o adlib.o
+ sound-obj-$(CONFIG_GUS) += gus.o gusemu_hal.o gusemu_mixer.o
+ sound-obj-$(CONFIG_CS4231A) += cs4231a.o
+ sound-obj-$(CONFIG_HDA) += intel-hda.o hda-audio.o
+ $(obj)/adlib.o $(obj)/fmopl.o: QEMU_CFLAGS += -DBUILD_Y8950=0
+ hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
+ hw-obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/
+ common-obj-y += usb/
+ common-obj-y += irq.o
+ common-obj-$(CONFIG_PTIMER) += ptimer.o
+ common-obj-$(CONFIG_MAX7310) += max7310.o
+ common-obj-$(CONFIG_WM8750) += wm8750.o
++common-obj-$(CONFIG_WM8994) += wm8994.o
+ common-obj-$(CONFIG_TWL92230) += twl92230.o
+ common-obj-$(CONFIG_TSC2005) += tsc2005.o
+ common-obj-$(CONFIG_LM832X) += lm832x.o
+ common-obj-$(CONFIG_TMP105) += tmp105.o
+ common-obj-$(CONFIG_STELLARIS_INPUT) += stellaris_input.o
+ common-obj-$(CONFIG_SSD0303) += ssd0303.o
+ common-obj-$(CONFIG_SSD0323) += ssd0323.o
+ common-obj-$(CONFIG_ADS7846) += ads7846.o
+ common-obj-$(CONFIG_MAX111X) += max111x.o
+ common-obj-$(CONFIG_DS1338) += ds1338.o
+ common-obj-y += i2c.o smbus.o smbus_eeprom.o
+ common-obj-y += eeprom93xx.o
+ common-obj-y += scsi-disk.o cdrom.o hd-geometry.o block-common.o
+ common-obj-y += scsi-generic.o scsi-bus.o
+ common-obj-y += hid.o
+ common-obj-$(CONFIG_SSI) += ssi.o
+ common-obj-$(CONFIG_SSI_SD) += ssi-sd.o
+ common-obj-$(CONFIG_SD) += sd.o
+ common-obj-y += bt.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o
+ common-obj-y += bt-hci-csr.o
+ common-obj-y += msmouse.o ps2.o
+ common-obj-y += qdev.o qdev-properties.o qdev-monitor.o
+ common-obj-$(CONFIG_BRLAPI) += baum.o
+ # xen backend driver support
+ common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
+ common-obj-$(CONFIG_XEN_BACKEND) += xen_console.o xenfb.o xen_disk.o xen_nic.o
+ # Per-target files
+ # virtio has to be here due to weird dependency between PCI and virtio-net.
+ # need to fix this properly
+ obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o
+ obj-$(CONFIG_VIRTIO) += virtio-serial-bus.o virtio-scsi.o
+ obj-$(CONFIG_SOFTMMU) += vhost_net.o
+ obj-$(CONFIG_VHOST_NET) += vhost.o
+ obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/
+ obj-$(CONFIG_NO_PCI) += pci-stub.o
+ obj-$(CONFIG_VGA) += vga.o
+ obj-$(CONFIG_SOFTMMU) += device-hotplug.o
+ obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
+ # Inter-VM PCI shared memory
+ ifeq ($(CONFIG_PCI), y)
+ obj-$(CONFIG_KVM) += ivshmem.o
+ endif
diff --cc hw/acpi_piix4.c
Simple merge
index 0000000,2b39fb3..70895c5
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,34 +1,36 @@@
+ obj-y = integratorcp.o versatilepb.o arm_pic.o
+ obj-y += arm_boot.o
+ obj-y += xilinx_zynq.o zynq_slcr.o
+ obj-y += arm_gic.o arm_gic_common.o
+ obj-y += realview_gic.o realview.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.o stellaris_enet.o
+ obj-y += highbank.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 += gumstix.o
+ obj-y += zaurus.o ide/microdrive.o spitz.o tosa.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 += omap_sx1.o palm.o tsc210x.o
+ obj-y += nseries.o blizzard.o onenand.o cbus.o tusb6010.o usb/hcd-musb.o
+ obj-y += mst_fpga.o mainstone.o
+ obj-y += z2.o
+ obj-y += musicpal.o bitbang_i2c.o marvell_88w8618_audio.o
+ obj-y += framebuffer.o
+ obj-y += vexpress.o
+ obj-y += strongarm.o
+ obj-y += collie.o
+ obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
+ obj-y += kzm.o
+ obj-$(CONFIG_FDT) += ../device_tree.o
+ obj-y := $(addprefix ../,$(obj-y))
diff --cc hw/exynos4210.c
@@@ -26,6 -26,6 +26,7 @@@
  #include "sysbus.h"
  #include "arm-misc.h"
  #include "loader.h"
++#include "virtio-transport.h"
  #include "exynos4210.h"
  
  #define EXYNOS4210_CHIPID_ADDR         0x10000000
  /* Display controllers (FIMD) */
  #define EXYNOS4210_FIMD0_BASE_ADDR          0x11C00000
  
++/* VirtIO MMIO */
++#define EXYNOS4210_VIRTIO_MMIO0_BASE_ADDR   0x10AD0000
++#define EXYNOS4210_VIRTIO_MMIO1_BASE_ADDR   0x10AC0000
++
  static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
                                      0x09, 0x00, 0x00, 0x00 };
  
@@@ -296,5 -334,5 +339,13 @@@ Exynos4210State *exynos4210_init(Memory
              s->irq_table[exynos4210_get_irq(11, 2)],
              NULL);
  
++    sysbus_create_simple(VIRTIO_MMIO,
++                         EXYNOS4210_VIRTIO_MMIO0_BASE_ADDR,
++                         s->irq_table[exynos4210_get_irq(37, 3)]);
++
++    sysbus_create_simple(VIRTIO_MMIO,
++                         EXYNOS4210_VIRTIO_MMIO1_BASE_ADDR,
++                         s->irq_table[exynos4210_get_irq(37, 2)]);
++
      return s;
  }
diff --cc hw/exynos4210.h
@@@ -102,13 -97,10 +104,13 @@@ typedef struct Exynos4210State 
      MemoryRegion dram1_mem;
      MemoryRegion boot_secondary;
      MemoryRegion bootreg_mem;
 +    MemoryRegion audss_intmem;
      i2c_bus *i2c_if[EXYNOS4210_I2C_NUMBER];
 +    BusState *i2s_bus[3];
 +    SysBusDevice *vpci_bus;
  } Exynos4210State;
  
- void exynos4210_write_secondary(CPUARMState *env,
+ void exynos4210_write_secondary(ARMCPU *cpu,
          const struct arm_boot_info *info);
  
  Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
@@@ -134,54 -126,8 +136,53 @@@ void exynos4210_combiner_get_gpioin(Exy
          int ext);
  
  /*
 + * Interface for exynos4210 Clock Management Units (CMUs)
 + */
 +typedef enum {
 +    UNSPECIFIED_CMU = -1,
 +    EXYNOS4210_CMU_LEFTBUS,
 +    EXYNOS4210_CMU_RIGHTBUS,
 +    EXYNOS4210_CMU_TOP,
 +    EXYNOS4210_CMU_DMC,
 +    EXYNOS4210_CMU_CPU,
 +    EXYNOS4210_CMU_NUMBER
 +} Exynos4210Cmu;
 +
 +typedef enum {
 +    UNSPECIFIED_CLOCK,
 +    EXYNOS4210_XXTI,
 +    EXYNOS4210_XUSBXTI,
 +//    EXYNOS4210_USB_PHY,
 +//    EXYNOS4210_USB_HOST_PHY,
 +//    EXYNOS4210_HDMI_PHY,
 +    EXYNOS4210_APLL,
 +    EXYNOS4210_MPLL,
 +    EXYNOS4210_SCLK_HDMI24M,
 +    EXYNOS4210_SCLK_USBPHY0,
 +    EXYNOS4210_SCLK_USBPHY1,
 +    EXYNOS4210_SCLK_HDMIPHY,
 +    EXYNOS4210_SCLK_APLL,
 +    EXYNOS4210_SCLK_MPLL,
 +    EXYNOS4210_ACLK_100,
 +    EXYNOS4210_SCLK_UART0,
 +    EXYNOS4210_SCLK_UART1,
 +    EXYNOS4210_SCLK_UART2,
 +    EXYNOS4210_SCLK_UART3,
 +    EXYNOS4210_SCLK_UART4,
 +    EXYNOS4210_CLOCKS_NUMBER
 +} Exynos4210Clock;
 +
 +typedef void ClockChangeHandler(void *opaque);
 +
 +DeviceState *exynos4210_cmu_create(target_phys_addr_t addr, Exynos4210Cmu cmu);
 +uint64_t exynos4210_cmu_get_rate(Exynos4210Clock clock_id);
 +void exynos4210_register_clock_handler(ClockChangeHandler *func,
 +                                       Exynos4210Clock clock_id,
 +                                       void *opaque);
 +
 +/*
   * exynos4210 UART
   */
  DeviceState *exynos4210_uart_create(target_phys_addr_t addr,
                                      int fifo_size,
                                      int channel,
Simple merge
index 236cc57,0000000..705643f
mode 100644,000000..100644
--- /dev/null
@@@ -1,577 -1,0 +1,592 @@@
-     DeviceState *dev = QTAILQ_FIRST(&bus->qbus.children);
 +/*
 + * Samsung exynos4210 I2S driver
 + *
 + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
 + *  Vorobiov Stanislav <s.vorobiov@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, see <http://www.gnu.org/licenses/>.
 + *
 + */
 +
 +#include "exynos4210_i2s.h"
 +#include "exec-memory.h"
 +
 +/* #define DEBUG_I2S */
 +
 +#ifdef DEBUG_I2S
 +#define DPRINTF(fmt, ...) \
 +    do { \
 +        fprintf(stdout, "I2S: [%s:%d] " fmt, __func__, __LINE__, \
 +            ## __VA_ARGS__); \
 +    } while (0)
 +#else
 +#define DPRINTF(fmt, ...) do {} while (0)
 +#endif
 +
 +/* Registers */
 +#define IISCON       0x00
 +#define IISMOD       0x04
 +#define IISFIC       0x08
 +#define IISPSR       0x0C
 +#define IISTXD       0x10
 +#define IISRXD       0x14
 +#define IISFICS      0x18
 +#define IISTXDS      0x1C
 +#define IISAHB       0x20
 +#define IISSTR0      0x24
 +#define IISSIZE      0x28
 +#define IISTRNCNT    0x2C
 +#define IISLVL0ADDR  0x30
 +#define IISLVL1ADDR  0x34
 +#define IISLVL2ADDR  0x38
 +#define IISLVL3ADDR  0x3C
 +#define IISSTR1      0x40
 +
 +#define I2S_REGS_MEM_SIZE 0x44
 +#define I2S_REGS_NUM (I2S_REGS_MEM_SIZE >> 2)
 +
 +#define I_(reg) (reg / sizeof(uint32_t))
 +
 +/* Interface Control Register */
 +#define IISCON_I2SACTIVE    (1 << 0)
 +#define IISCON_RXDMACTIVE   (1 << 1)
 +#define IISCON_TXDMACTIVE   (1 << 2)
 +#define IISCON_RXCHPAUSE    (1 << 3)
 +#define IISCON_TXCHPAUSE    (1 << 4)
 +#define IISCON_RXDMAPAUSE   (1 << 5)
 +#define IISCON_TXDMAPAUSE   (1 << 6)
 +#define IISCON_FRXFULL      (1 << 7)
 +#define IISCON_FTX0FULL     (1 << 8)
 +#define IISCON_FRXEMPT      (1 << 9)
 +#define IISCON_FTX0EMPT     (1 << 10)
 +#define IISCON_LRI          (1 << 11)
 +#define IISCON_FTX1FULL     (1 << 12)
 +#define IISCON_FTX2FULL     (1 << 13)
 +#define IISCON_FTX1EMPT     (1 << 14)
 +#define IISCON_FTX2EMPT     (1 << 15)
 +#define IISCON_FTXURINTEN   (1 << 16)
 +#define IISCON_FTXURSTATUS  (1 << 17)
 +#define IISCON_TXSDMACTIVE  (1 << 18)
 +#define IISCON_TXSDMAPAUSE  (1 << 20)
 +#define IISCON_FTXSFULL     (1 << 21)
 +#define IISCON_FTXSEMPT     (1 << 22)
 +#define IISCON_FTXSURINTEN  (1 << 23)
 +#define IISCON_FTXSURSTATUS (1 << 24)
 +#define IISCON_FRXOFINTEN   (1 << 25)
 +#define IISCON_FRXOFSTATUS  (1 << 26)
 +#define IISCON_SW_RST       (1 << 31)
 +
 +#define IISCON_WRITE_MASK   (0x8295007F)
 +
 +/* AHB DMA Control Register */
 +#define IISAHB_WRITE_MASK     0xFF0000FB
 +#define IISAHB_LVL3EN         (1 << 27)
 +#define IISAHB_LVL2EN         (1 << 26)
 +#define IISAHB_LVL1EN         (1 << 25)
 +#define IISAHB_LVL0EN         (1 << 24)
 +#define IISAHB_LVL3INT        (1 << 23)
 +#define IISAHB_LVL2INT        (1 << 22)
 +#define IISAHB_LVL1INT        (1 << 21)
 +#define IISAHB_LVL0INT        (1 << 20)
 +#define IISAHB_LVL3CLR        (1 << 19)
 +#define IISAHB_LVL2CLR        (1 << 18)
 +#define IISAHB_LVL1CLR        (1 << 17)
 +#define IISAHB_LVL0CLR        (1 << 16)
 +#define IISAHB_DMA_STRADDRRST (1 << 7)
 +#define IISAHB_DMA_STRADDRTOG (1 << 6)
 +#define IISAHB_DMARLD         (1 << 5)
 +#define IISAHB_INTMASK        (1 << 3)
 +#define IISAHB_DMAINT         (1 << 2)
 +#define IISAHB_DMACLR         (1 << 1)
 +#define IISAHB_DMAEN          (1 << 0)
 +
 +/* AHB DMA Size Register */
 +#define IISSIZE_TRNS_SIZE_OFFSET  16
 +#define IISSIZE_TRNS_SIZE_MASK    0xFFFF
 +
 +/* AHB DMA Transfer Count Register */
 +#define IISTRNCNT_OFFSET 0
 +#define IISTRNCNT_MASK   0xFFFFFF
 +
 +typedef struct {
 +    const char *name;
 +    target_phys_addr_t offset;
 +    uint32_t reset_value;
 +} Exynos4210I2SReg;
 +
 +static Exynos4210I2SReg exynos4210_i2s_regs[I2S_REGS_NUM] = {
 +    {"IISCON",         IISCON,         0x00000000},
 +    {"IISMOD",         IISMOD,         0x00000000},
 +    {"IISFIC",         IISFIC,         0x00000000},
 +    {"IISPSR",         IISPSR,         0x00000000},
 +    {"IISTXD",         IISTXD,         0x00000000},
 +    {"IISRXD",         IISRXD,         0x00000000},
 +    {"IISFICS",        IISFICS,        0x00000000},
 +    {"IISTXDS",        IISTXDS,        0x00000000},
 +    {"IISAHB",         IISAHB,         0x00000000},
 +    {"IISSTR0",        IISSTR0,        0x00000000},
 +    {"IISSIZE",        IISSIZE,        0x7FFF0000},
 +    {"IISTRNCNT",      IISTRNCNT,      0x00000000},
 +    {"IISLVL0ADDR",    IISLVL0ADDR,    0x00000000},
 +    {"IISLVL1ADDR",    IISLVL1ADDR,    0x00000000},
 +    {"IISLVL2ADDR",    IISLVL2ADDR,    0x00000000},
 +    {"IISLVL3ADDR",    IISLVL3ADDR,    0x00000000},
 +    {"IISSTR1",        IISSTR1,        0x00000000},
 +};
 +
 +static struct {
 +    uint32_t ahb_en_bit;
 +    uint32_t ahb_int_bit;
 +    uint32_t ahb_clr_bit;
 +    int reg_offset;
 +} lvl_regs[] = {
 +    { IISAHB_LVL3EN, IISAHB_LVL3INT, IISAHB_LVL3CLR, IISLVL3ADDR },
 +    { IISAHB_LVL2EN, IISAHB_LVL2INT, IISAHB_LVL2CLR, IISLVL2ADDR },
 +    { IISAHB_LVL1EN, IISAHB_LVL1INT, IISAHB_LVL1CLR, IISLVL1ADDR },
 +    { IISAHB_LVL0EN, IISAHB_LVL0INT, IISAHB_LVL0CLR, IISLVL0ADDR },
 +};
 +
++#define TYPE_EXYNOS4210_I2S_BUS "exynos4210-i2s"
++
 +typedef struct {
 +    BusState qbus;
 +
 +    MemoryRegion iomem;
 +    qemu_irq irq;
 +    uint32_t reg[I2S_REGS_NUM];
 +} Exynos4210I2SBus;
 +
 +static Exynos4210I2SSlave *get_slave(Exynos4210I2SBus *bus)
 +{
-     if (dev) {
-         return EXYNOS4210_I2S_SLAVE_FROM_QDEV(dev);
++    BusChild *kid = QTAILQ_FIRST(&bus->qbus.children);
++    DeviceState *dev;
 +
- static struct BusInfo exynos4210_i2s_bus_info = {
-     .name = "Exynos4210.I2S",
-     .size = sizeof(Exynos4210I2SBus),
-     .reset = exynos4210_i2s_bus_reset
++    if (kid) {
++        dev = kid->child;
++        if (dev) {
++            return EXYNOS4210_I2S_SLAVE_FROM_QDEV(dev);
++        }
 +    }
 +
 +    return NULL;
 +}
 +
 +static void reset_internal(BusState *qbus, bool reset_slave)
 +{
 +    Exynos4210I2SBus *bus = DO_UPCAST(Exynos4210I2SBus, qbus, qbus);
 +    Exynos4210I2SSlave *s;
 +    int i;
 +
 +    DPRINTF("enter\n");
 +
 +    qemu_irq_lower(bus->irq);
 +
 +    for (i = 0; i < ARRAY_SIZE(exynos4210_i2s_regs); i++) {
 +        bus->reg[i] = exynos4210_i2s_regs[i].reset_value;
 +    }
 +
 +    if (reset_slave) {
 +        s = get_slave(bus);
 +
 +        if (s != NULL) {
 +            device_reset(&s->qdev);
 +        }
 +    }
 +}
 +
 +static uint32_t get_dma_size_words(Exynos4210I2SBus *bus)
 +{
 +    return (bus->reg[I_(IISSIZE)] >> IISSIZE_TRNS_SIZE_OFFSET) &
 +            IISSIZE_TRNS_SIZE_MASK;
 +}
 +
 +static uint32_t get_dma_trncnt_words(Exynos4210I2SBus *bus)
 +{
 +    return (bus->reg[I_(IISTRNCNT)] >> IISTRNCNT_OFFSET) &
 +            IISTRNCNT_MASK;
 +}
 +
 +static void set_dma_trncnt_words(Exynos4210I2SBus *bus, uint32_t trncnt_words)
 +{
 +    bus->reg[I_(IISTRNCNT)] &= ~(IISTRNCNT_MASK << IISTRNCNT_OFFSET);
 +    bus->reg[I_(IISTRNCNT)] |=
 +        ((trncnt_words & IISTRNCNT_MASK) << IISTRNCNT_OFFSET);
 +}
 +
 +static int exynos4210_i2s_bus_reset(BusState *qbus);
 +
-                     qbus_create(&exynos4210_i2s_bus_info, NULL, name));
++static void exynos4210_i2s_bus_class_init(ObjectClass *klass, void *data)
++{
++    BusClass *k = BUS_CLASS(klass);
++
++    k->reset    = exynos4210_i2s_bus_reset;
++}
++
++static struct TypeInfo exynos4210_i2s_bus_info = {
++    .name          = TYPE_EXYNOS4210_I2S_BUS,
++    .parent        = TYPE_BUS,
++    .instance_size = sizeof(Exynos4210I2SBus),
++    .class_init    = exynos4210_i2s_bus_class_init,
 +};
 +
 +static const VMStateDescription vmstate_exynos4210_i2s_bus = {
 +    .name = "exynos4210.i2s_bus",
 +    .version_id = 1,
 +    .minimum_version_id = 1,
 +    .minimum_version_id_old = 1,
 +    .fields      = (VMStateField[]) {
 +        VMSTATE_UINT32_ARRAY(reg, Exynos4210I2SBus,
 +                                  I2S_REGS_NUM),
 +        VMSTATE_END_OF_LIST()
 +    }
 +};
 +
 +#ifdef DEBUG_I2S
 +static const char *exynos4210_i2s_regname(Exynos4210I2SBus *bus,
 +                                          target_phys_addr_t offset)
 +{
 +    int i;
 +
 +    for (i = 0; i < ARRAY_SIZE(exynos4210_i2s_regs); i++) {
 +        if (offset == exynos4210_i2s_regs[i].offset) {
 +            return exynos4210_i2s_regs[i].name;
 +        }
 +    }
 +
 +    return NULL;
 +}
 +#endif
 +
 +static void exynos4210_i2s_bus_write(void *opaque,
 +                                     target_phys_addr_t offset,
 +                                     uint64_t value,
 +                                     unsigned size)
 +{
 +    Exynos4210I2SBus *bus = opaque;
 +    Exynos4210I2SSlave *s;
 +    Exynos4210I2SSlaveClass *sc;
 +    int i;
 +
 +    s = get_slave(bus);
 +
 +    assert(s != NULL);
 +
 +    if (s == NULL) {
 +        hw_error("Exynos I2S cannot operate without a slave\n");
 +    }
 +
 +    sc = EXYNOS4210_I2S_SLAVE_GET_CLASS(s);
 +
 +    switch (offset) {
 +    case IISCON:
 +        if (!(value & IISCON_SW_RST) &&
 +             (bus->reg[I_(IISCON)] & IISCON_SW_RST)) {
 +            reset_internal(&bus->qbus, 1);
 +        }
 +
 +        bus->reg[I_(offset)] = (bus->reg[I_(offset)] & ~IISCON_WRITE_MASK) |
 +                               (value & IISCON_WRITE_MASK);
 +
 +        DPRINTF("0x%.8X -> %s\n",
 +                bus->reg[I_(offset)],
 +                exynos4210_i2s_regname(bus, offset));
 +
 +        break;
 +    case IISAHB:
 +        if (((value & IISAHB_DMAEN) != 0) && ((value & IISAHB_DMARLD) == 0)) {
 +            hw_error("Non auto-reload DMA is not supported\n");
 +        }
 +
 +        if (((value & IISAHB_DMAEN) != 0) && ((value & IISAHB_INTMASK) == 0)) {
 +            hw_error("Non buffer level DMA interrupt is not supported\n");
 +        }
 +
 +        if (((value & IISAHB_DMAEN) != 0) &&
 +            ((value & IISAHB_DMA_STRADDRTOG) != 0)) {
 +            hw_error("DMA start address toggle is not supported\n");
 +        }
 +
 +        for (i = 0; i < ARRAY_SIZE(lvl_regs); ++i) {
 +            if ((value & lvl_regs[i].ahb_clr_bit) &&
 +                (bus->reg[I_(IISAHB)] & lvl_regs[i].ahb_int_bit)) {
 +                qemu_irq_lower(bus->irq);
 +                bus->reg[I_(IISAHB)] &= ~lvl_regs[i].ahb_int_bit;
 +            }
 +        }
 +
 +        if ((value & IISAHB_DMACLR) &&
 +            (bus->reg[I_(IISAHB)] & IISAHB_DMAINT)) {
 +            qemu_irq_lower(bus->irq);
 +            bus->reg[I_(IISAHB)] &= ~IISAHB_DMAINT;
 +        }
 +
 +        if ((value & IISAHB_DMAEN) !=
 +            (bus->reg[I_(IISAHB)] & IISAHB_DMAEN)) {
 +            if ((value & IISAHB_DMAEN) == 0) {
 +                qemu_irq_lower(bus->irq);
 +            }
 +            if (sc->dma_enable) {
 +                sc->dma_enable(s, ((value & IISAHB_DMAEN) != 0));
 +            }
 +        }
 +
 +        bus->reg[I_(offset)] = (bus->reg[I_(offset)] & ~IISAHB_WRITE_MASK) |
 +                               (value & IISAHB_WRITE_MASK);
 +
 +        DPRINTF("0x%.8X -> %s\n",
 +                bus->reg[I_(offset)],
 +                exynos4210_i2s_regname(bus, offset));
 +
 +        break;
 +    case IISTRNCNT:
 +        hw_error("Cannot write IISTRNCNT\n");
 +        break;
 +    case IISSIZE:
 +        if (value == 0) {
 +            hw_error("IISSIZE cannot be 0\n");
 +        }
 +
 +        bus->reg[I_(offset)] = value;
 +
 +        if (get_dma_size_words(bus) <= get_dma_trncnt_words(bus)) {
 +            set_dma_trncnt_words(bus, 0);
 +        }
 +
 +        DPRINTF("0x%.8X -> %s\n",
 +                bus->reg[I_(offset)],
 +                exynos4210_i2s_regname(bus, offset));
 +
 +        break;
 +    case IISLVL0ADDR:
 +    case IISLVL1ADDR:
 +    case IISLVL2ADDR:
 +    case IISLVL3ADDR:
 +    case IISTXD:
 +    case IISMOD:
 +    case IISFIC:
 +    case IISPSR:
 +    case IISTXDS:
 +    case IISFICS:
 +    case IISSTR0:
 +    case IISSTR1:
 +        bus->reg[I_(offset)] = value;
 +
 +        DPRINTF("0x%.8X -> %s\n",
 +                bus->reg[I_(offset)],
 +                exynos4210_i2s_regname(bus, offset));
 +
 +        break;
 +    default:
 +        hw_error("Bad offset: 0x%X\n", (int)offset);
 +    }
 +}
 +
 +static uint64_t exynos4210_i2s_bus_read(void *opaque,
 +                                        target_phys_addr_t offset,
 +                                        unsigned size)
 +{
 +    Exynos4210I2SBus *bus = opaque;
 +
 +    if (offset > (I2S_REGS_MEM_SIZE - sizeof(uint32_t))) {
 +        hw_error("Bad offset: 0x%X\n", (int)offset);
 +        return 0;
 +    }
 +
 +    DPRINTF("%s -> 0x%.8X\n",
 +            exynos4210_i2s_regname(bus, offset),
 +            bus->reg[I_(offset)]);
 +
 +    return bus->reg[I_(offset)];
 +}
 +
 +static int exynos4210_i2s_bus_reset(BusState *qbus)
 +{
 +    reset_internal(qbus, 0);
 +
 +    return 0;
 +}
 +
 +static const MemoryRegionOps exynos4210_i2s_bus_ops = {
 +    .read = exynos4210_i2s_bus_read,
 +    .write = exynos4210_i2s_bus_write,
 +    .endianness = DEVICE_NATIVE_ENDIAN,
 +    .valid = {
 +        .max_access_size = 4,
 +        .unaligned = false
 +    },
 +};
 +
 +BusState *exynos4210_i2s_bus_new(const char *name,
 +                                 target_phys_addr_t addr,
 +                                 qemu_irq irq)
 +{
 +    Exynos4210I2SBus *bus;
 +
 +    bus = FROM_QBUS(Exynos4210I2SBus,
-     k->bus_info = &exynos4210_i2s_bus_info;
++                    qbus_create(TYPE_EXYNOS4210_I2S_BUS, NULL, name));
 +    vmstate_register(NULL, -1, &vmstate_exynos4210_i2s_bus, bus);
 +
 +    memory_region_init_io(&bus->iomem,
 +                          &exynos4210_i2s_bus_ops,
 +                          bus,
 +                          "exynos4210.i2s",
 +                          I2S_REGS_MEM_SIZE);
 +
 +    memory_region_add_subregion(get_system_memory(),
 +                                addr,
 +                                &bus->iomem);
 +
 +    bus->irq = irq;
 +
 +    return &bus->qbus;
 +}
 +
 +bool exynos4210_i2s_dma_enabled(BusState *qbus)
 +{
 +    Exynos4210I2SBus *bus = DO_UPCAST(Exynos4210I2SBus, qbus, qbus);
 +
 +    return ((bus->reg[I_(IISAHB)] & IISAHB_DMAEN) != 0);
 +}
 +
 +uint32_t exynos4210_i2s_dma_get_words_available(BusState *qbus)
 +{
 +    Exynos4210I2SBus *bus = DO_UPCAST(Exynos4210I2SBus, qbus, qbus);
 +
 +    return get_dma_size_words(bus);
 +}
 +
 +void exynos4210_i2s_dma_read(BusState *qbus, void *buf, uint32_t num_words)
 +{
 +    Exynos4210I2SBus *bus = DO_UPCAST(Exynos4210I2SBus, qbus, qbus);
 +    target_phys_addr_t addr;
 +    uint32_t size_words, trncnt_words;
 +
 +    assert(num_words <= exynos4210_i2s_dma_get_words_available(qbus));
 +
 +    if (num_words > exynos4210_i2s_dma_get_words_available(qbus)) {
 +        hw_error("Bad DMA read length: %d\n", num_words);
 +    }
 +
 +    size_words = get_dma_size_words(bus);
 +    addr = bus->reg[I_(IISSTR0)];
 +    trncnt_words = get_dma_trncnt_words(bus);
 +
 +    assert(trncnt_words < size_words);
 +
 +    if (num_words > (size_words - trncnt_words)) {
 +        cpu_physical_memory_read(addr +
 +                                 (trncnt_words * EXYNOS4210_I2S_WORD_LEN),
 +            buf,
 +            (size_words - trncnt_words) * EXYNOS4210_I2S_WORD_LEN);
 +        num_words -= (size_words - trncnt_words);
 +        buf += (size_words - trncnt_words) * EXYNOS4210_I2S_WORD_LEN;
 +        trncnt_words = 0;
 +    }
 +
 +    cpu_physical_memory_read(addr + (trncnt_words * EXYNOS4210_I2S_WORD_LEN),
 +                             buf,
 +                             num_words * EXYNOS4210_I2S_WORD_LEN);
 +}
 +
 +void exynos4210_i2s_dma_advance(BusState *qbus, uint32_t num_words)
 +{
 +    Exynos4210I2SBus *bus = DO_UPCAST(Exynos4210I2SBus, qbus, qbus);
 +    uint32_t size_words, trncnt_words;
 +    int i;
 +
 +    assert(num_words <= exynos4210_i2s_dma_get_words_available(qbus));
 +
 +    if (num_words > exynos4210_i2s_dma_get_words_available(qbus)) {
 +        hw_error("Bad DMA read length: %d\n", num_words);
 +    }
 +
 +    size_words = get_dma_size_words(bus);
 +    trncnt_words = get_dma_trncnt_words(bus);
 +
 +    for (i = 0; i < ARRAY_SIZE(lvl_regs); ++i) {
 +        target_phys_addr_t dma_offset;
 +        uint32_t tmp_num_words = num_words, tmp_trncnt_words = trncnt_words;
 +
 +        if ((bus->reg[I_(IISAHB)] & lvl_regs[i].ahb_en_bit) == 0) {
 +            continue;
 +        }
 +
 +        if (bus->reg[I_(lvl_regs[i].reg_offset)] < bus->reg[I_(IISSTR0)]) {
 +            continue;
 +        }
 +
 +        dma_offset = bus->reg[I_(lvl_regs[i].reg_offset)] -
 +                     bus->reg[I_(IISSTR0)];
 +
 +        if (tmp_num_words > (size_words - tmp_trncnt_words)) {
 +            if ((dma_offset >= (tmp_trncnt_words * EXYNOS4210_I2S_WORD_LEN)) &&
 +                (dma_offset < size_words * EXYNOS4210_I2S_WORD_LEN)) {
 +                bus->reg[I_(IISAHB)] |= lvl_regs[i].ahb_int_bit;
 +                qemu_irq_raise(bus->irq);
 +                break;
 +            }
 +
 +            tmp_num_words -= (size_words - tmp_trncnt_words);
 +            tmp_trncnt_words = 0;
 +        }
 +
 +        if ((dma_offset >= (tmp_trncnt_words * EXYNOS4210_I2S_WORD_LEN)) &&
 +            (dma_offset <
 +                (tmp_trncnt_words + tmp_num_words) * EXYNOS4210_I2S_WORD_LEN)) {
 +            bus->reg[I_(IISAHB)] |= lvl_regs[i].ahb_int_bit;
 +            qemu_irq_raise(bus->irq);
 +        }
 +    }
 +
 +    set_dma_trncnt_words(bus, (trncnt_words + num_words) % size_words);
 +}
 +
 +const VMStateDescription vmstate_exynos4210_i2s_slave = {
 +    .name = "Exynos4210I2SSlave",
 +    .version_id = 1,
 +    .minimum_version_id = 1,
 +    .minimum_version_id_old = 1
 +};
 +
 +static int exynos4210_i2s_slave_qdev_init(DeviceState *dev)
 +{
 +    Exynos4210I2SSlave *s = EXYNOS4210_I2S_SLAVE_FROM_QDEV(dev);
 +    Exynos4210I2SSlaveClass *sc = EXYNOS4210_I2S_SLAVE_GET_CLASS(s);
 +
 +    return sc->init ? sc->init(s) : 0;
 +}
 +
 +static void exynos4210_i2s_slave_class_init(ObjectClass *klass, void *data)
 +{
 +    DeviceClass *k = DEVICE_CLASS(klass);
 +    k->init = exynos4210_i2s_slave_qdev_init;
++    k->bus_type = TYPE_EXYNOS4210_I2S_BUS;
 +}
 +
 +static TypeInfo exynos4210_i2s_slave_type_info = {
 +    .name = TYPE_EXYNOS4210_I2S_SLAVE,
 +    .parent = TYPE_DEVICE,
 +    .instance_size = sizeof(Exynos4210I2SSlave),
 +    .abstract = true,
 +    .class_size = sizeof(Exynos4210I2SSlaveClass),
 +    .class_init = exynos4210_i2s_slave_class_init,
 +};
 +
 +static void exynos4210_i2s_slave_register_types(void)
 +{
++    type_register_static(&exynos4210_i2s_bus_info);
 +    type_register_static(&exynos4210_i2s_slave_type_info);
 +}
 +
 +type_init(exynos4210_i2s_slave_register_types)
diff --cc hw/pc.c
+++ b/hw/pc.c
  #include "memory.h"
  #include "exec-memory.h"
  #include "arch_init.h"
+ #include "bitmap.h"
+ #include "vga-pci.h"
  
 +#ifdef CONFIG_MARU
 +#include "../tizen/src/hw/maru_overlay.h"
 +#include "../tizen/src/hw/maru_brightness.h"
 +#include "../tizen/src/maru_err_table.h"
 +#endif
 +
  /* output Bochs bios info messages */
  //#define DEBUG_BIOS
  
diff --cc hw/pc.h
+++ b/hw/pc.h
@@@ -189,12 -189,6 +189,11 @@@ static inline DeviceState *isa_vga_init
      return &dev->qdev;
  }
  
- DeviceState *pci_vga_init(PCIBus *bus);
 +#ifdef CONFIG_MARU
 +DeviceState *pci_maru_vga_init(PCIBus *bus);
 +#endif
 +
 +
  int isa_vga_mm_init(target_phys_addr_t vram_base,
                      target_phys_addr_t ctrl_base, int it_shift,
                      MemoryRegion *address_space);
diff --cc hw/pc_sysfw.c
Simple merge
diff --cc hw/pci.c
+++ b/hw/pci.c
@@@ -66,7 -77,7 +77,6 @@@ static const TypeInfo pci_bus_info = 
  static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
  static void pci_update_mappings(PCIDevice *d);
  static void pci_set_irq(void *opaque, int irq_num, int level);
--static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom);
  static void pci_del_option_rom(PCIDevice *pdev);
  
  static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
@@@ -1668,7 -1733,7 +1732,7 @@@ static void pci_patch_ids(PCIDevice *pd
  }
  
  /* Add an option rom for the device */
--static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
++int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
  {
      int size;
      char *path;
diff --cc hw/pci.h
+++ b/hw/pci.h
@@@ -251,6 -274,6 +276,8 @@@ void pci_register_bar(PCIDevice *pci_de
                        uint8_t attr, MemoryRegion *memory);
  pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num);
  
++int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom);
++
  int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
                         uint8_t offset, uint8_t size);
  
@@@ -2,6 -2,8 +2,9 @@@
  #include "qdev.h"
  #include "qerror.h"
  #include "blockdev.h"
++#include "virtio-transport.h"
+ #include "hw/block-common.h"
+ #include "net/hub.h"
  
  void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
  {
@@@ -528,6 -526,6 +527,34 @@@ PropertyInfo qdev_prop_drive = 
      .release = release_drive,
  };
  
++/* --- virtio transport --- */
++
++static int parse_transport(DeviceState *dev, const char *str, void **ptr)
++{
++    VirtIOTransportLink *trl;
++
++    trl = virtio_find_transport(str);
++
++    if (trl == NULL) {
++        return -ENOENT;
++    }
++
++    *ptr = trl;
++
++    return 0;
++}
++
++static void set_transport(Object *obj, Visitor *v, void *opaque,
++                      const char *name, Error **errp)
++{
++    set_pointer(obj, v, opaque, parse_transport, name, errp);
++}
++
++PropertyInfo qdev_prop_transport = {
++    .name  = "transport",
++    .set   = set_transport,
++};
++
  /* --- character device --- */
  
  static int parse_chr(DeviceState *dev, const char *str, void **ptr)
diff --cc hw/qdev.h
+++ b/hw/qdev.h
@@@ -220,7 -231,8 +231,9 @@@ extern PropertyInfo qdev_prop_chr
  extern PropertyInfo qdev_prop_ptr;
  extern PropertyInfo qdev_prop_macaddr;
  extern PropertyInfo qdev_prop_losttickpolicy;
+ extern PropertyInfo qdev_prop_bios_chs_trans;
  extern PropertyInfo qdev_prop_drive;
++extern PropertyInfo qdev_prop_transport;
  extern PropertyInfo qdev_prop_netdev;
  extern PropertyInfo qdev_prop_vlan;
  extern PropertyInfo qdev_prop_pci_devfn;
@@@ -276,11 -289,11 +290,13 @@@ extern PropertyInfo qdev_prop_pci_host_
  #define DEFINE_PROP_STRING(_n, _s, _f)             \
      DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*)
  #define DEFINE_PROP_NETDEV(_n, _s, _f)             \
-     DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, VLANClientState*)
+     DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, NetClientState*)
  #define DEFINE_PROP_VLAN(_n, _s, _f)             \
-     DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, VLANState*)
+     DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, NetClientState*)
  #define DEFINE_PROP_DRIVE(_n, _s, _f) \
      DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockDriverState *)
++#define DEFINE_PROP_TRANSPORT(_n, _s, _f) \
++    DEFINE_PROP(_n, _s, _f, qdev_prop_transport, VirtIOTransportLink *)
  #define DEFINE_PROP_MACADDR(_n, _s, _f)         \
      DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr)
  #define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \
Simple merge
@@@ -595,8 -599,8 +610,8 @@@ static USBDevice *usb_msd_init(USBBus *
  
      /* parse -usbdevice disk: syntax into drive opts */
      snprintf(id, sizeof(id), "usb%d", nr++);
-     opts = qemu_opts_create(qemu_find_opts("drive"), id, 0);
+     opts = qemu_opts_create(qemu_find_opts("drive"), id, 0, NULL);
 -
 +#ifndef CONFIG_MARU
      p1 = strchr(filename, ':');
      if (p1++) {
          const char *p2;
diff --cc hw/vga-pci.c
@@@ -100,59 -102,6 +106,60 @@@ static TypeInfo vga_info = 
      .class_init    = vga_class_init,
  };
  
-      maru_vga_common_init(s, VGA_RAM_SIZE);
 +#ifdef CONFIG_MARU
 +
 +DeviceState *pci_maru_vga_init(PCIBus *bus)
 +{
 +    return &pci_create_simple(bus, -1, "MARU_VGA")->qdev;
 +}
 +
 +static int maru_pci_vga_initfn(PCIDevice *dev)
 +{
 +     PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
 +     VGACommonState *s = &d->vga;
 +
 +     // vga + console init
++     maru_vga_common_init(s);
 +     vga_init(s, pci_address_space(dev), pci_address_space_io(dev), true);
 +
 +     s->ds = graphic_console_init(s->update, s->invalidate,
 +                                  s->screen_dump, s->text_update, s);
 +
 +     /* XXX: VGA_RAM_SIZE must be a power of two */
 +     pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
 +
 +     if (!dev->rom_bar) {
 +         /* compatibility with pc-0.13 and older */
 +         vga_init_vbe(s, pci_address_space(dev));
 +     }
 +
 +     return 0;
 +}
 +
 +static void maru_pci_vga_classinit(ObjectClass *klass, void *data)
 +{
 +    DeviceClass *dc = DEVICE_CLASS(klass);
 +    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 +
 +    k->no_hotplug = 1;
 +    k->init = maru_pci_vga_initfn;
 +    k->romfile = "vgabios-maruvga.bin";
 +    k->vendor_id = PCI_VENDOR_ID_QEMU;
 +    k->device_id = PCI_DEVICE_ID_QEMU_VGA;
 +    k->class_id = PCI_CLASS_DISPLAY_VGA;
 +    dc->vmsd = &vmstate_vga_pci;
++    dc->props = vga_pci_properties;
 +}
 +
 +static TypeInfo maru_vga_info = {
 +    .name = "MARU_VGA",
 +    .parent = TYPE_PCI_DEVICE,
 +    .instance_size = sizeof(PCIVGAState),
 +    .class_init = maru_pci_vga_classinit,
 +};
 +
 +#endif // CONFIG_MARU
 +
  static void vga_register_types(void)
  {
      type_register_static(&vga_info);
diff --cc hw/vga_int.h
  /* bochs VBE support */
  #define CONFIG_BOCHS_VBE
  
- #define VBE_DISPI_MAX_XRES              1600
+ #define VBE_DISPI_MAX_XRES              16000
 +#if CONFIG_MARU
 +#define VBE_DISPI_MAX_YRES              1600
 +#else
- #define VBE_DISPI_MAX_YRES              1200
+ #define VBE_DISPI_MAX_YRES              12000
 +#endif
  #define VBE_DISPI_MAX_BPP               32
  
  #define VBE_DISPI_INDEX_ID              0x0
@@@ -268,36 -272,3 +273,44 @@@ void virtio_balloon_exit(VirtIODevice *
      unregister_savevm(s->qdev, "virtio-balloon", s);
      virtio_cleanup(vdev);
  }
-     return virtio_init_transport(dev, vdev);
 +
 +/******************** VirtIOBaloon Device **********************/
 +
 +static int virtio_balloondev_init(DeviceState *dev)
 +{
 +    VirtIODevice *vdev;
++    VirtIOBaloonState *s = VIRTIO_BALLOON_FROM_QDEV(dev);
 +    vdev = virtio_balloon_init(dev);
 +    if (!vdev) {
 +        return -1;
 +    }
-     dc->bus_info = &virtio_transport_bus_info;
++
++    assert(s->trl != NULL);
++
++    return virtio_call_backend_init_cb(dev, s->trl, vdev);
 +}
 +
++static Property virtio_balloon_properties[] = {
++    DEFINE_PROP_END_OF_LIST(),
++};
++
 +static void virtio_balloon_class_init(ObjectClass *klass, void *data)
 +{
 +    DeviceClass *dc = DEVICE_CLASS(klass);
 +    dc->init = virtio_balloondev_init;
++    dc->props = virtio_balloon_properties;
 +}
 +
 +static TypeInfo virtio_balloon_info = {
 +    .name = "virtio-balloon",
 +    .parent = TYPE_DEVICE,
 +    .instance_size = sizeof(VirtIOBaloonState),
 +    .class_init = virtio_balloon_class_init,
 +};
 +
 +static void virtio_baloon_register_types(void)
 +{
 +    type_register_static(&virtio_balloon_info);
 +}
 +
 +type_init(virtio_baloon_register_types)
  #ifndef _QEMU_VIRTIO_BALLOON_H
  #define _QEMU_VIRTIO_BALLOON_H
  
 +#include "sysbus.h"
  #include "virtio.h"
  #include "pci.h"
++#include "virtio-transport.h"
  
  /* from Linux's linux/virtio_balloon.h */
  
@@@ -53,10 -52,4 +54,11 @@@ typedef struct VirtIOBalloonStat 
      uint64_t val;
  } QEMU_PACKED VirtIOBalloonStat;
  
 +typedef struct {
 +    DeviceState qdev;
++    VirtIOTransportLink *trl;
 +} VirtIOBaloonState;
 +
 +#define VIRTIO_BALLOON_FROM_QDEV(dev) DO_UPCAST(VirtIOBaloonState, qdev, dev)
 +
  #endif
diff --cc hw/virtio-blk.c
  #include "qemu-common.h"
  #include "qemu-error.h"
  #include "trace.h"
+ #include "hw/block-common.h"
  #include "blockdev.h"
 +#include "virtio-transport.h"
++#include "virtio-pci.h"
  #include "virtio-blk.h"
  #include "scsi-defs.h"
  #ifdef __linux__
@@@ -630,44 -665,3 +667,66 @@@ void virtio_blk_exit(VirtIODevice *vdev
      blockdev_mark_auto_del(s->bs);
      virtio_cleanup(vdev);
  }
-     VirtIOBlockState *proxy = VIRTIO_BLK_FROM_QDEV(dev);
-     vdev = virtio_blk_init(dev, &proxy->block);
 +
 +/******************** VirtIOBlk Device **********************/
 +
 +static int virtio_blkdev_init(DeviceState *dev)
 +{
 +    VirtIODevice *vdev;
-     return virtio_init_transport(dev, vdev);
++    VirtIOBlockState *s = VIRTIO_BLK_FROM_QDEV(dev);
++
++    assert(s->trl != NULL);
++
++    vdev = virtio_blk_init(dev, &s->blk);
 +    if (!vdev) {
 +        return -1;
 +    }
-     DEFINE_BLOCK_PROPERTIES(VirtIOBlockState, block.conf),
-     DEFINE_PROP_STRING("serial", VirtIOBlockState, block.serial),
++
++    /* Pass default host_features to transport */
++    s->trl->host_features = s->host_features;
++
++    if (virtio_call_backend_init_cb(dev, s->trl, vdev) != 0) {
++        return -1;
++    }
++
++    /* Binding should be ready here, let's get final features */
++    if (vdev->binding->get_features) {
++       s->host_features = vdev->binding->get_features(vdev->binding_opaque);
++    }
++    return 0;
 +}
 +
 +static Property virtio_blkdev_properties[] = {
-     dc->bus_info = &virtio_transport_bus_info;
++    DEFINE_BLOCK_PROPERTIES(VirtIOBlockState, blk.conf),
++    DEFINE_BLOCK_CHS_PROPERTIES(VirtIOBlockState, blk.conf),
++    DEFINE_PROP_STRING("serial", VirtIOBlockState, blk.serial),
++#ifdef __linux__
++    DEFINE_PROP_BIT("scsi", VirtIOBlockState, blk.scsi, 0, true),
++#endif
++    DEFINE_PROP_BIT("config-wce", VirtIOBlockState, blk.config_wce, 0, true),
++    DEFINE_VIRTIO_BLK_FEATURES(VirtIOBlockState, host_features),
++
++    DEFINE_PROP_TRANSPORT("transport", VirtIOBlockState, trl),
 +    DEFINE_PROP_END_OF_LIST(),
 +};
 +
 +static void virtio_blkdev_class_init(ObjectClass *klass, void *data)
 +{
 +    DeviceClass *dc = DEVICE_CLASS(klass);
 +    dc->init = virtio_blkdev_init;
 +    dc->props = virtio_blkdev_properties;
 +}
 +
 +static TypeInfo virtio_blkdev_info = {
 +    .name = "virtio-blk",
 +    .parent = TYPE_DEVICE,
 +    .instance_size = sizeof(VirtIOBlockState),
 +    .class_init = virtio_blkdev_class_init,
 +};
 +
 +static void virtio_blk_register_types(void)
 +{
 +    type_register_static(&virtio_blkdev_info);
 +}
 +
 +type_init(virtio_blk_register_types)
diff --cc hw/virtio-blk.h
  #ifndef _QEMU_VIRTIO_BLK_H
  #define _QEMU_VIRTIO_BLK_H
  
 +#include "sysbus.h"
  #include "virtio.h"
- #include "block.h"
++#include "virtio-transport.h"
+ #include "hw/block-common.h"
  
  /* from Linux's linux/virtio_blk.h */
  
@@@ -106,15 -108,7 +110,20 @@@ struct VirtIOBlkCon
  };
  
  #define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
-         DEFINE_VIRTIO_COMMON_FEATURES(_state, _field)
+         DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
+         DEFINE_PROP_BIT("config-wce", _state, _field, VIRTIO_BLK_F_CONFIG_WCE, true)
  
-     VirtIOBlkConf block;
 +
 +typedef struct {
 +    DeviceState qdev;
 +    /* virtio-blk */
++    VirtIOBlkConf blk;
++
++    uint32_t host_features;
++
++    VirtIOTransportLink *trl;
 +} VirtIOBlockState;
 +
 +#define VIRTIO_BLK_FROM_QDEV(dev) DO_UPCAST(VirtIOBlockState, qdev, dev)
 +
  #endif
index c210806,0000000..88e5d9f
mode 100644,000000..100644
--- /dev/null
@@@ -1,439 -1,0 +1,400 @@@
- #define VIRTIO_MMIO "virtio-mmio"
- #define VIRTIO_MMIO_BUS "virtio-mmio-bus"
- struct BusInfo virtio_mmio_bus_info = {
-     .name = VIRTIO_MMIO_BUS,
-     .size = sizeof(BusState),
- };
 +/*
 + * Virtio MMIO bindings
 + *
 + * Copyright (c) 2011 Linaro Limited
 + *
 + * Authors:
 + *  Peter Maydell <peter.maydell@linaro.org>
 + *  Evgeny Voevodin <e.voevodin@samsung.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License; 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, see <http://www.gnu.org/licenses/>.
 + */
 +
 +/* TODO:
 + *  * save/load support
 + *  * test net, serial, balloon
 + */
 +
 +#include "sysbus.h"
 +#include "virtio.h"
 +#include "virtio-transport.h"
 +#include "virtio-blk.h"
 +#include "virtio-net.h"
 +#include "virtio-serial.h"
 +#include "host-utils.h"
 +
 +/* #define DEBUG_VIRTIO_MMIO */
 +
 +#ifdef DEBUG_VIRTIO_MMIO
 +
 +#define DPRINTF(fmt, ...) \
 +do { printf("virtio_mmio: " fmt , ## __VA_ARGS__); } while (0)
 +#else
 +#define DPRINTF(fmt, ...) do {} while (0)
 +#endif
 +
 +/* Memory mapped register offsets */
 +#define VIRTIO_MMIO_MAGIC 0x0
 +#define VIRTIO_MMIO_VERSION 0x4
 +#define VIRTIO_MMIO_DEVICEID 0x8
 +#define VIRTIO_MMIO_VENDORID 0xc
 +#define VIRTIO_MMIO_HOSTFEATURES 0x10
 +#define VIRTIO_MMIO_HOSTFEATURESSEL 0x14
 +#define VIRTIO_MMIO_GUESTFEATURES 0x20
 +#define VIRTIO_MMIO_GUESTFEATURESSEL 0x24
 +#define VIRTIO_MMIO_GUESTPAGESIZE 0x28
 +#define VIRTIO_MMIO_QUEUESEL 0x30
 +#define VIRTIO_MMIO_QUEUENUMMAX 0x34
 +#define VIRTIO_MMIO_QUEUENUM 0x38
 +#define VIRTIO_MMIO_QUEUEALIGN 0x3c
 +#define VIRTIO_MMIO_QUEUEPFN 0x40
 +#define VIRTIO_MMIO_QUEUENOTIFY 0x50
 +#define VIRTIO_MMIO_INTERRUPTSTATUS 0x60
 +#define VIRTIO_MMIO_INTERRUPTACK 0x64
 +#define VIRTIO_MMIO_STATUS 0x70
 +/* Device specific config space starts here */
 +#define VIRTIO_MMIO_CONFIG 0x100
 +
 +#define VIRT_MAGIC 0x74726976 /* 'virt' */
 +#define VIRT_VERSION 1
 +#define VIRT_VENDOR 0x554D4551 /* 'QEMU' */
 +
- } VirtIOMMIOTransportState;
 +enum VIRTIO_MMIO_MAPPINGS {
 +    VIRTIO_MMIO_IOMAP,
 +    VIRTIO_MMIO_IOMEM,
 +};
 +
 +typedef struct {
 +    SysBusDevice busdev;
 +    VirtIODevice *vdev;
++    VirtIOTransportLink *trl;
++
 +    MemoryRegion iomap; /* hold base address */
 +    MemoryRegion iomem; /* hold io funcs */
 +    MemoryRegion alias;
 +    qemu_irq irq;
 +    uint32_t int_enable;
 +    uint32_t host_features;
 +    uint32_t host_features_sel;
 +    uint32_t guest_features_sel;
 +    uint32_t guest_page_shift;
-     VirtIOMMIOTransportState *transport = (VirtIOMMIOTransportState *)opaque;
-     VirtIODevice *vdev = transport->vdev;
++} VirtIOMMIO;
 +
 +static uint64_t virtio_mmio_read(void *opaque, target_phys_addr_t offset,
 +                                 unsigned size)
 +{
-         if (transport->host_features_sel) {
++    VirtIOMMIO *s = (VirtIOMMIO *)opaque;
++    VirtIODevice *vdev = s->vdev;
 +    DPRINTF("virtio_mmio_read offset 0x%x\n", (int)offset);
 +    if (offset >= VIRTIO_MMIO_CONFIG) {
 +        offset -= VIRTIO_MMIO_CONFIG;
 +        switch (size) {
 +        case 1:
 +            return virtio_config_readb(vdev, offset);
 +        case 2:
 +            return virtio_config_readw(vdev, offset);
 +        case 4:
 +            return virtio_config_readl(vdev, offset);
 +        default:
 +            abort();
 +        }
 +    }
 +    if (size != 4) {
 +        DPRINTF("wrong size access to register!\n");
 +        return 0;
 +    }
 +    switch (offset) {
 +    case VIRTIO_MMIO_MAGIC:
 +        return VIRT_MAGIC;
 +    case VIRTIO_MMIO_VERSION:
 +        return VIRT_VERSION;
 +    case VIRTIO_MMIO_DEVICEID:
 +        return vdev->device_id;
 +    case VIRTIO_MMIO_VENDORID:
 +        return VIRT_VENDOR;
 +    case VIRTIO_MMIO_HOSTFEATURES:
-         return transport->host_features;
++        if (s->host_features_sel) {
 +            return 0;
 +        }
-             >> transport->guest_page_shift;
++        return s->host_features;
 +    case VIRTIO_MMIO_QUEUENUMMAX:
 +        return VIRTQUEUE_MAX_SIZE;
 +    case VIRTIO_MMIO_QUEUEPFN:
 +        return virtio_queue_get_addr(vdev, vdev->queue_sel)
-     VirtIOMMIOTransportState *transport = (VirtIOMMIOTransportState *)opaque;
-     VirtIODevice *vdev = transport->vdev;
++            >> s->guest_page_shift;
 +    case VIRTIO_MMIO_INTERRUPTSTATUS:
 +        return vdev->isr;
 +    case VIRTIO_MMIO_STATUS:
 +        return vdev->status;
 +    case VIRTIO_MMIO_HOSTFEATURESSEL:
 +    case VIRTIO_MMIO_GUESTFEATURES:
 +    case VIRTIO_MMIO_GUESTFEATURESSEL:
 +    case VIRTIO_MMIO_GUESTPAGESIZE:
 +    case VIRTIO_MMIO_QUEUESEL:
 +    case VIRTIO_MMIO_QUEUENUM:
 +    case VIRTIO_MMIO_QUEUEALIGN:
 +    case VIRTIO_MMIO_QUEUENOTIFY:
 +    case VIRTIO_MMIO_INTERRUPTACK:
 +        DPRINTF("read of write-only register\n");
 +        return 0;
 +    default:
 +        DPRINTF("bad register offset\n");
 +        return 0;
 +    }
 +    return 0;
 +}
 +
 +static void virtio_mmio_write(void *opaque, target_phys_addr_t offset,
 +                              uint64_t value, unsigned size)
 +{
-         transport->host_features_sel = value;
++    VirtIOMMIO *s = (VirtIOMMIO *)opaque;
++    VirtIODevice *vdev = s->vdev;
 +    DPRINTF("virtio_mmio_write offset 0x%x value 0x%" PRIx64 "\n",
 +            (int)offset, value);
 +    if (offset >= VIRTIO_MMIO_CONFIG) {
 +        offset -= VIRTIO_MMIO_CONFIG;
 +        switch (size) {
 +        case 1:
 +            virtio_config_writeb(vdev, offset, value);
 +            break;
 +        case 2:
 +            virtio_config_writew(vdev, offset, value);
 +            break;
 +        case 4:
 +            virtio_config_writel(vdev, offset, value);
 +            break;
 +        default:
 +            abort();
 +        }
 +        return;
 +    }
 +    if (size != 4) {
 +        DPRINTF("wrong size access to register!\n");
 +        return;
 +    }
 +    switch (offset) {
 +    case VIRTIO_MMIO_HOSTFEATURESSEL:
-         if (!transport->guest_features_sel) {
++        s->host_features_sel = value;
 +        break;
 +    case VIRTIO_MMIO_GUESTFEATURES:
-         transport->guest_features_sel = value;
++        if (!s->guest_features_sel) {
 +            virtio_set_features(vdev, value);
 +        }
 +        break;
 +    case VIRTIO_MMIO_GUESTFEATURESSEL:
-         transport->guest_page_shift = ctz32(value);
-         if (transport->guest_page_shift > 31) {
-             transport->guest_page_shift = 0;
++        s->guest_features_sel = value;
 +        break;
 +    case VIRTIO_MMIO_GUESTPAGESIZE:
-                 transport->guest_page_shift);
++        s->guest_page_shift = ctz32(value);
++        if (s->guest_page_shift > 31) {
++            s->guest_page_shift = 0;
 +        }
 +        DPRINTF("guest page size %" PRIx64 " shift %d\n", value,
-                                   value << transport->guest_page_shift);
++                s->guest_page_shift);
 +        break;
 +    case VIRTIO_MMIO_QUEUESEL:
 +        if (value < VIRTIO_PCI_QUEUE_MAX) {
 +            vdev->queue_sel = value;
 +        }
 +        break;
 +    case VIRTIO_MMIO_QUEUENUM:
 +        DPRINTF("mmio_queue write %d max %d\n", (int)value, VIRTQUEUE_MAX_SIZE);
 +        if (value <= VIRTQUEUE_MAX_SIZE) {
 +            DPRINTF("calling virtio_queue_set_num\n");
 +            virtio_queue_set_num(vdev, vdev->queue_sel, value);
 +        }
 +        break;
 +    case VIRTIO_MMIO_QUEUEALIGN:
 +        virtio_queue_set_align(vdev, vdev->queue_sel, value);
 +        break;
 +    case VIRTIO_MMIO_QUEUEPFN:
 +        if (value == 0) {
 +            virtio_reset(vdev);
 +        } else {
 +            virtio_queue_set_addr(vdev, vdev->queue_sel,
-     VirtIOMMIOTransportState *transport = opaque;
-     int level = (transport->vdev->isr != 0);
++                                  value << s->guest_page_shift);
 +        }
 +        break;
 +    case VIRTIO_MMIO_QUEUENOTIFY:
 +        if (value < VIRTIO_PCI_QUEUE_MAX) {
 +            virtio_queue_notify(vdev, value);
 +        }
 +        break;
 +    case VIRTIO_MMIO_INTERRUPTACK:
 +        vdev->isr &= ~value;
 +        virtio_update_irq(vdev);
 +        break;
 +    case VIRTIO_MMIO_STATUS:
 +        virtio_set_status(vdev, value & 0xff);
 +        if (vdev->status == 0) {
 +            virtio_reset(vdev);
 +        }
 +        break;
 +    case VIRTIO_MMIO_MAGIC:
 +    case VIRTIO_MMIO_VERSION:
 +    case VIRTIO_MMIO_DEVICEID:
 +    case VIRTIO_MMIO_VENDORID:
 +    case VIRTIO_MMIO_HOSTFEATURES:
 +    case VIRTIO_MMIO_QUEUENUMMAX:
 +    case VIRTIO_MMIO_INTERRUPTSTATUS:
 +        DPRINTF("write to readonly register\n");
 +        break;
 +
 +    default:
 +        DPRINTF("bad register offset\n");
 +    }
 +}
 +
 +static const MemoryRegionOps virtio_mem_ops = {
 +    .read = virtio_mmio_read,
 +    .write = virtio_mmio_write,
 +    .endianness = DEVICE_NATIVE_ENDIAN,
 +};
 +
 +static void virtio_mmio_update_irq(void *opaque, uint16_t vector)
 +{
-     qemu_set_irq(transport->irq, level);
++    VirtIOMMIO *s = opaque;
++    int level = (s->vdev->isr != 0);
 +    DPRINTF("virtio_mmio setting IRQ %d\n", level);
-     VirtIOMMIOTransportState *transport = opaque;
-     return transport->host_features;
++    qemu_set_irq(s->irq, level);
 +}
 +
 +static unsigned int virtio_mmio_get_features(void *opaque)
 +{
-     VirtIOMMIOTransportState *transport = opaque;
-     transport->int_enable = qemu_get_be32(f);
-     transport->host_features = qemu_get_be32(f);
-     transport->host_features_sel = qemu_get_be32(f);
-     transport->guest_features_sel = qemu_get_be32(f);
-     transport->guest_page_shift = qemu_get_be32(f);
++    VirtIOMMIO *s = opaque;
++    return s->host_features;
 +}
 +
 +static int virtio_mmio_load_config(void *opaque, QEMUFile *f)
 +{
-     VirtIOMMIOTransportState *transport = opaque;
-     qemu_put_be32(f, transport->int_enable);
-     qemu_put_be32(f, transport->host_features);
-     qemu_put_be32(f, transport->host_features_sel);
-     qemu_put_be32(f, transport->guest_features_sel);
-     qemu_put_be32(f, transport->guest_page_shift);
++    VirtIOMMIO *s = opaque;
++    s->int_enable = qemu_get_be32(f);
++    s->host_features = qemu_get_be32(f);
++    s->host_features_sel = qemu_get_be32(f);
++    s->guest_features_sel = qemu_get_be32(f);
++    s->guest_page_shift = qemu_get_be32(f);
 +    return 0;
 +}
 +
 +static void virtio_mmio_save_config(void *opaque, QEMUFile *f)
 +{
- static void virtio_mmio_attach_to_transport(DeviceState *dev)
++    VirtIOMMIO *s = opaque;
++    qemu_put_be32(f, s->int_enable);
++    qemu_put_be32(f, s->host_features);
++    qemu_put_be32(f, s->host_features_sel);
++    qemu_put_be32(f, s->guest_features_sel);
++    qemu_put_be32(f, s->guest_page_shift);
 +}
 +
 +static VirtIOBindings virtio_mmio_bindings = {
 +    .notify = virtio_mmio_update_irq,
 +    .get_features = virtio_mmio_get_features,
 +    .save_config = virtio_mmio_save_config,
 +    .load_config = virtio_mmio_load_config,
 +};
 +
-     DeviceState *transport_dev = qdev_get_parent_bus(dev)->parent;
-     SysBusDevice *transport_sysbus = sysbus_from_qdev(transport_dev);
-     VirtIOMMIOTransportState *transport =
-             FROM_SYSBUS(VirtIOMMIOTransportState, transport_sysbus);
++static int virtio_mmio_transport_cb(DeviceState *dev, VirtIODevice *vdev,
++        VirtIOTransportLink *trl)
 +{
-     /* Create alias and add it as subregion to transport iomem */
-     memory_region_init_alias(&transport->alias,
++    VirtIOMMIO *s =
++            FROM_SYSBUS(VirtIOMMIO, sysbus_from_qdev(trl->tr));
 +
-                              &transport->iomem,
++    virtio_plug_into_transport(dev, trl);
++
++    s->vdev = vdev;
++    s->vdev->nvectors = 0;
++    sysbus_init_irq(&s->busdev, &s->irq);
++    memory_region_init_io(&s->iomem, &virtio_mem_ops, s,
++                          "virtio-mmio-iomem", 0x1000);
++    sysbus_init_mmio(&s->busdev, &s->iomem);
++    virtio_bind_device(vdev, &virtio_mmio_bindings, s);
++    s->host_features |= (0x1 << VIRTIO_F_NOTIFY_ON_EMPTY);
++    s->host_features =
++            vdev->get_features(vdev, s->host_features);
++
++    /* Create alias and add it as subregion to s iomem */
++    memory_region_init_alias(&s->alias,
 +                             "virtio-mmio-alias",
-     /* add alias as subregion to transport iomap */
-     memory_region_add_subregion(&transport->iomap,
++                             &s->iomem,
 +                             0,
 +                             0x1000);
-                                 &transport->alias);
- }
- static int virtio_init_mmio_transport(DeviceState *dev, VirtIODevice *vdev)
- {
-     DeviceState *transport_dev = qdev_get_parent_bus(dev)->parent;
-     SysBusDevice *transport_sysbus = sysbus_from_qdev(transport_dev);
-     VirtIOMMIOTransportState *transport =
-             FROM_SYSBUS(VirtIOMMIOTransportState, transport_sysbus);
-     uint32_t i;
-     /* Find a free transport where we will not have any siblings */
-     i = virtio_count_siblings(qdev_get_parent_bus(dev), NULL);
-     if (i > 1) {
-         transport_dev =
-                 virtio_get_free_transport(qdev_get_parent_bus(transport_dev),
-                                           VIRTIO_MMIO);
-         assert(transport_dev != NULL);
-         transport_sysbus = sysbus_from_qdev(transport_dev);
-         transport = FROM_SYSBUS(VirtIOMMIOTransportState, transport_sysbus);
-         /* Reconnect back-end to free transport. Access by QLIST because we
-          * don't know actual suffix for virtio-pci.x */
-         QTAILQ_REMOVE(&qdev_get_parent_bus(dev)->children, dev, sibling);
-         qdev_set_parent_bus(dev, qdev_get_child_bus(transport_dev,
-                 ((BusState *)QLIST_FIRST(&transport_dev->child_bus))->name));
-     }
-     transport->vdev = vdev;
-     transport->vdev->nvectors = 0;
-     sysbus_init_irq(&transport->busdev, &transport->irq);
-     memory_region_init_io(&transport->iomem, &virtio_mem_ops, transport,
-                           "virtio-mmio-iomem", 0x1000);
-     sysbus_init_mmio(&transport->busdev, &transport->iomem);
-     virtio_bind_device(vdev, &virtio_mmio_bindings, transport);
-     transport->host_features |= (0x1 << VIRTIO_F_NOTIFY_ON_EMPTY);
-     transport->host_features =
-             vdev->get_features(vdev, transport->host_features);
-     virtio_mmio_attach_to_transport(dev);
++    /* add alias as subregion to s iomap */
++    memory_region_add_subregion(&s->iomap,
 +                                0,
- static void virtio_mmio_transport_handler(void *opaque, int irq, int level)
++                                &s->alias);
 +    return 0;
 +}
 +
-     VirtIOMMIOTransportState *s = (VirtIOMMIOTransportState *)opaque;
++static void virtio_mmio_handler(void *opaque, int irq, int level)
 +{
- static int virtio_mmio_transport_device_init(SysBusDevice *busdev)
++    VirtIOMMIO *s = (VirtIOMMIO *)opaque;
 +
 +    qemu_set_irq(s->irq, level);
 +
 +    return;
 +}
 +
-     VirtIOMMIOTransportState *s =
-             DO_UPCAST(VirtIOMMIOTransportState, busdev, busdev);
-     BusState *parent_bus = qdev_get_parent_bus(&busdev->qdev);
-     BusState *child_bus;
-     VirtIOTransportBusState *virtio_transport_bus;
++static int sice_init(SysBusDevice *busdev)
 +{
-     int len;
-     uint32_t i;
-     i = virtio_count_siblings(parent_bus, VIRTIO_MMIO);
++    VirtIOMMIO *s =
++            DO_UPCAST(VirtIOMMIO, busdev, busdev);
 +    char *buf;
-     len = strlen(VIRTIO_MMIO) + 16;
-     buf = g_malloc(len);
-     snprintf(buf, len, "%s.%d", VIRTIO_MMIO, i);
-     child_bus = qbus_create(&virtio_transport_bus_info, &busdev->qdev, buf);
 +
-     /* Populate mmio init transport function */
-     virtio_transport_bus = DO_UPCAST(VirtIOTransportBusState, bus, child_bus);
-     virtio_transport_bus->init_fn = virtio_init_mmio_transport;
-     qdev_init_gpio_in(&s->busdev.qdev, virtio_mmio_transport_handler, 1);
++    /* Count transports before we assigned a device ID to our new transport */
++    buf = virtio_init_transport(&busdev->qdev, &s->trl, VIRTIO_MMIO,
++            virtio_mmio_transport_cb);
 +
-     VirtIOMMIOTransportState *transport =
-             FROM_SYSBUS(VirtIOMMIOTransportState, sysbus_from_qdev(d));
-     if (transport->vdev) {
-         virtio_reset(transport->vdev);
++    /* assign new device id */
++    busdev->qdev.id = buf;
 +
++    qdev_init_gpio_in(&s->busdev.qdev, virtio_mmio_handler, 1);
 +    sysbus_init_irq(busdev, &s->irq);
 +    memory_region_init(&s->iomap, "virtio-mmio-iomap", 0x1000);
 +    sysbus_init_mmio(busdev, &s->iomap);
++
 +    return 0;
 +}
 +
 +static void virtio_mmio_reset(DeviceState *d)
 +{
- static void virtio_mmio_transport_class_init(ObjectClass *klass, void *data)
++    VirtIOMMIO *s = FROM_SYSBUS(VirtIOMMIO, sysbus_from_qdev(d));
++    if (s->vdev) {
++        virtio_reset(s->vdev);
 +    }
 +}
 +
-     k->init = virtio_mmio_transport_device_init;
++/******************** VirtIOMMIO Device *********************/
++
++static void virtio_mmio_class_init(ObjectClass *klass, void *data)
 +{
 +    DeviceClass *dc = DEVICE_CLASS(klass);
 +    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- static TypeInfo virtio_mmio_transport_info = {
-     .name = VIRTIO_MMIO_TRANSPORT,
++    k->init = sice_init;
 +    dc->reset = virtio_mmio_reset;
 +}
 +
-     .instance_size = sizeof(VirtIOMMIOTransportState),
-     .class_init = virtio_mmio_transport_class_init,
++static TypeInfo virtio_mmio_info = {
++    .name = VIRTIO_MMIO,
 +    .parent = TYPE_SYS_BUS_DEVICE,
-     type_register_static(&virtio_mmio_transport_info);
++    .instance_size = sizeof(VirtIOMMIO),
++    .class_init = virtio_mmio_class_init,
 +};
 +
++/************************************************************/
++
 +static void virtio_mmio_register_types(void)
 +{
++    type_register_static(&virtio_mmio_info);
 +}
 +
 +type_init(virtio_mmio_register_types)
diff --cc hw/virtio-net.c
@@@ -13,7 -13,6 +13,8 @@@
  
  #include "iov.h"
  #include "virtio.h"
 +#include "virtio-transport.h"
++#include "virtio-pci.h"
  #include "net.h"
  #include "net/checksum.h"
  #include "net/tap.h"
@@@ -1078,51 -1077,6 +1079,63 @@@ void virtio_net_exit(VirtIODevice *vdev
          qemu_bh_delete(n->tx_bh);
      }
  
-     qemu_del_vlan_client(&n->nic->nc);
+     qemu_del_net_client(&n->nic->nc);
      virtio_cleanup(&n->vdev);
  }
-     VirtIONetState *proxy = VIRTIO_NET_FROM_QDEV(dev);
-     vdev = virtio_net_init(dev, &proxy->nic, &proxy->net);
-     if (!vdev) {
 +
 +/******************** VirtIONet Device **********************/
 +
 +static int virtio_netdev_init(DeviceState *dev)
 +{
 +    VirtIODevice *vdev;
-     return virtio_init_transport(dev, vdev);
++    VirtIONetState *s = VIRTIO_NET_FROM_QDEV(dev);
++
++    assert(s->trl != NULL);
++
++    vdev = virtio_net_init(dev, &s->nic, &s->net);
++
++    /* Pass default host_features to transport */
++    s->trl->host_features = s->host_features;
++
++    if (virtio_call_backend_init_cb(dev, s->trl, vdev) != 0) {
 +        return -1;
 +    }
-     DEFINE_PROP_UINT32("x-txtimer", VirtIONetState,
-                        net.txtimer, TX_TIMER_INTERVAL),
-     DEFINE_PROP_INT32("x-txburst", VirtIONetState,
-                       net.txburst, TX_BURST),
++
++    /* Binding should be ready here, let's get final features */
++    if (vdev->binding->get_features) {
++       s->host_features = vdev->binding->get_features(vdev->binding_opaque);
++    }
++    return 0;
 +}
 +
 +static Property virtio_net_properties[] = {
++    DEFINE_VIRTIO_NET_FEATURES(VirtIONetState, host_features),
 +    DEFINE_NIC_PROPERTIES(VirtIONetState, nic),
-     dc->bus_info = &virtio_transport_bus_info;
++    DEFINE_PROP_UINT32("x-txtimer", VirtIONetState, net.txtimer,
++            TX_TIMER_INTERVAL),
++    DEFINE_PROP_INT32("x-txburst", VirtIONetState, net.txburst, TX_BURST),
 +    DEFINE_PROP_STRING("tx", VirtIONetState, net.tx),
++    DEFINE_PROP_TRANSPORT("transport", VirtIONetState, trl),
 +    DEFINE_PROP_END_OF_LIST(),
 +};
 +
 +static void virtio_net_class_init(ObjectClass *klass, void *data)
 +{
 +    DeviceClass *dc = DEVICE_CLASS(klass);
 +    dc->init = virtio_netdev_init;
 +    dc->props = virtio_net_properties;
 +}
 +
 +static TypeInfo virtio_net_info = {
 +    .name = "virtio-net",
 +    .parent = TYPE_DEVICE,
 +    .instance_size = sizeof(VirtIONetState),
 +    .class_init = virtio_net_class_init,
 +};
 +
 +static void virtio_net_register_types(void)
 +{
 +    type_register_static(&virtio_net_info);
 +}
 +
 +type_init(virtio_net_register_types)
diff --cc hw/virtio-net.h
@@@ -14,8 -14,7 +14,9 @@@
  #ifndef _QEMU_VIRTIO_NET_H
  #define _QEMU_VIRTIO_NET_H
  
 +#include "sysbus.h"
  #include "virtio.h"
++#include "virtio-transport.h"
  #include "net.h"
  #include "pci.h"
  
@@@ -188,14 -187,4 +189,18 @@@ struct virtio_net_ctrl_mac 
          DEFINE_PROP_BIT("ctrl_rx", _state, _field, VIRTIO_NET_F_CTRL_RX, true), \
          DEFINE_PROP_BIT("ctrl_vlan", _state, _field, VIRTIO_NET_F_CTRL_VLAN, true), \
          DEFINE_PROP_BIT("ctrl_rx_extra", _state, _field, VIRTIO_NET_F_CTRL_RX_EXTRA, true)
 +
 +typedef struct {
 +    DeviceState qdev;
 +    /* virtio-net */
 +    NICConf nic;
 +    virtio_net_conf net;
++
++    uint32_t host_features;
++
++    VirtIOTransportLink *trl;
 +} VirtIONetState;
 +
 +#define VIRTIO_NET_FROM_QDEV(dev) DO_UPCAST(VirtIONetState, qdev, dev)
 +
  #endif
index 0000000,0000000..04f0da4
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,925 @@@
++/*
++ * Virtio PCI Bindings
++ *
++ * Copyright IBM, Corp. 2007
++ * Copyright (c) 2009 CodeSourcery
++ *
++ * Authors:
++ *  Anthony Liguori   <aliguori@us.ibm.com>
++ *  Paul Brook        <paul@codesourcery.com>
++ *
++ * This work is licensed under the terms of the GNU GPL, version 2.  See
++ * the COPYING file in the top-level directory.
++ *
++ * Contributions after 2012-01-13 are licensed under the terms of the
++ * GNU GPL, version 2 or (at your option) any later version.
++ */
++
++#include <inttypes.h>
++
++#include "virtio.h"
++#include "virtio-transport.h"
++#include "virtio-blk.h"
++#include "virtio-net.h"
++#include "virtio-serial.h"
++#include "virtio-scsi.h"
++#include "virtio-balloon.h"
++#include "pci.h"
++#include "qemu-error.h"
++#include "msi.h"
++#include "msix.h"
++#include "net.h"
++#include "loader.h"
++#include "kvm.h"
++#include "blockdev.h"
++#include "virtio-pci.h"
++#include "range.h"
++
++/* from Linux's linux/virtio_pci.h */
++
++/* A 32-bit r/o bitmask of the features supported by the host */
++#define VIRTIO_PCI_HOST_FEATURES        0
++
++/* A 32-bit r/w bitmask of features activated by the guest */
++#define VIRTIO_PCI_GUEST_FEATURES       4
++
++/* A 32-bit r/w PFN for the currently selected queue */
++#define VIRTIO_PCI_QUEUE_PFN            8
++
++/* A 16-bit r/o queue size for the currently selected queue */
++#define VIRTIO_PCI_QUEUE_NUM            12
++
++/* A 16-bit r/w queue selector */
++#define VIRTIO_PCI_QUEUE_SEL            14
++
++/* A 16-bit r/w queue notifier */
++#define VIRTIO_PCI_QUEUE_NOTIFY         16
++
++/* An 8-bit device status register.  */
++#define VIRTIO_PCI_STATUS               18
++
++/* An 8-bit r/o interrupt status register.  Reading the value will return the
++ * current contents of the ISR and will also clear it.  This is effectively
++ * a read-and-acknowledge. */
++#define VIRTIO_PCI_ISR                  19
++
++/* MSI-X registers: only enabled if MSI-X is enabled. */
++/* A 16-bit vector for configuration changes. */
++#define VIRTIO_MSI_CONFIG_VECTOR        20
++/* A 16-bit vector for selected queue notifications. */
++#define VIRTIO_MSI_QUEUE_VECTOR         22
++
++/* Config space size */
++#define VIRTIO_PCI_CONFIG_NOMSI         20
++#define VIRTIO_PCI_CONFIG_MSI           24
++#define VIRTIO_PCI_REGION_SIZE(dev)     (msix_present(dev) ? \
++                                         VIRTIO_PCI_CONFIG_MSI : \
++                                         VIRTIO_PCI_CONFIG_NOMSI)
++
++/* The remaining space is defined by each driver as the per-driver
++ * configuration space */
++#define VIRTIO_PCI_CONFIG(dev)          (msix_enabled(dev) ? \
++                                         VIRTIO_PCI_CONFIG_MSI : \
++                                         VIRTIO_PCI_CONFIG_NOMSI)
++
++/* How many bits to shift physical queue address written to QUEUE_PFN.
++ * 12 is historical, and due to x86 page size. */
++#define VIRTIO_PCI_QUEUE_ADDR_SHIFT    12
++
++/* Flags track per-device state like workarounds for quirks in older guests. */
++#define VIRTIO_PCI_FLAG_BUS_MASTER_BUG  (1 << 0)
++
++/* QEMU doesn't strictly need write barriers since everything runs in
++ * lock-step.  We'll leave the calls to wmb() in though to make it obvious for
++ * KVM or if kqemu gets SMP support.
++ */
++#define wmb() do { } while (0)
++
++/* HACK for virtio to determine if it's running a big endian guest */
++bool virtio_is_big_endian(void);
++
++/* virtio device */
++
++static void virtio_pci_notify(void *opaque, uint16_t vector)
++{
++    VirtIOPCI *s = opaque;
++    if (msix_enabled(&s->pci_dev)) {
++        msix_notify(&s->pci_dev, vector);
++    }
++    else {
++        qemu_set_irq(s->pci_dev.irq[0], s->vdev->isr & 1);
++    }
++}
++
++static void virtio_pci_save_config(void * opaque, QEMUFile *f)
++{
++    VirtIOPCI *s = opaque;
++    pci_device_save(&s->pci_dev, f);
++    msix_save(&s->pci_dev, f);
++    if (msix_present(&s->pci_dev)) {
++        qemu_put_be16(f, s->vdev->config_vector);
++    }
++}
++
++static void virtio_pci_save_queue(void * opaque, int n, QEMUFile *f)
++{
++    VirtIOPCI *s = opaque;
++    if (msix_present(&s->pci_dev)) {
++        qemu_put_be16(f, virtio_queue_vector(s->vdev, n));
++    }
++}
++
++static int virtio_pci_load_config(void * opaque, QEMUFile *f)
++{
++    VirtIOPCI *s = opaque;
++    int ret;
++    ret = pci_device_load(&s->pci_dev, f);
++    if (ret) {
++        return ret;
++    }
++    msix_unuse_all_vectors(&s->pci_dev);
++    msix_load(&s->pci_dev, f);
++    if (msix_present(&s->pci_dev)) {
++        qemu_get_be16s(f, &s->vdev->config_vector);
++    } else {
++        s->vdev->config_vector = VIRTIO_NO_VECTOR;
++    }
++    if (s->vdev->config_vector != VIRTIO_NO_VECTOR) {
++        return msix_vector_use(&s->pci_dev, s->vdev->config_vector);
++    }
++    return 0;
++}
++
++static int virtio_pci_load_queue(void * opaque, int n, QEMUFile *f)
++{
++    VirtIOPCI *s = opaque;
++    uint16_t vector;
++    if (msix_present(&s->pci_dev)) {
++        qemu_get_be16s(f, &vector);
++    } else {
++        vector = VIRTIO_NO_VECTOR;
++    }
++    virtio_queue_set_vector(s->vdev, n, vector);
++    if (vector != VIRTIO_NO_VECTOR) {
++        return msix_vector_use(&s->pci_dev, vector);
++    }
++    return 0;
++}
++
++static int virtio_pci_set_host_notifier_internal(VirtIOPCI *s, int n,
++        bool assign, bool set_handler)
++{
++    VirtQueue *vq = virtio_get_queue(s->vdev, n);
++    EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
++    int r = 0;
++
++    if (assign) {
++        r = event_notifier_init(notifier, 1);
++        if (r < 0) {
++            error_report("%s: unable to init event notifier: %d", __func__, r);
++            return r;
++        }
++        virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
++        memory_region_add_eventfd(&s->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2, true, n,
++                notifier);
++    } else {
++        memory_region_del_eventfd(&s->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2, true, n,
++                notifier);
++        virtio_queue_set_host_notifier_fd_handler(vq, false, false);
++        event_notifier_cleanup(notifier);
++    }
++    return r;
++}
++
++static void virtio_pci_start_ioeventfd(VirtIOPCI *s)
++{
++    int n, r;
++
++    if (!(s->flags & VIRTIO_PCI_FLAG_USE_IOEVENTFD) ||
++        s->ioeventfd_disabled ||
++        s->ioeventfd_started) {
++        return;
++    }
++
++    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
++        if (!virtio_queue_get_num(s->vdev, n)) {
++            continue;
++        }
++
++        r = virtio_pci_set_host_notifier_internal(s, n, true, true);
++        if (r < 0) {
++            goto assign_error;
++        }
++    }
++    s->ioeventfd_started = true;
++    return;
++
++assign_error:
++    while (--n >= 0) {
++        if (!virtio_queue_get_num(s->vdev, n)) {
++            continue;
++        }
++
++        r = virtio_pci_set_host_notifier_internal(s, n, false, false);
++        assert(r >= 0);
++    }
++    s->ioeventfd_started = false;
++    error_report("%s: failed. Fallback to a userspace (slower).", __func__);
++}
++
++static void virtio_pci_stop_ioeventfd(VirtIOPCI *s)
++{
++    int r;
++    int n;
++
++    if (!s->ioeventfd_started) {
++        return;
++    }
++
++    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
++        if (!virtio_queue_get_num(s->vdev, n)) {
++            continue;
++        }
++
++        r = virtio_pci_set_host_notifier_internal(s, n, false, false);
++        assert(r >= 0);
++    }
++    s->ioeventfd_started = false;
++}
++
++void virtio_pci_reset_(DeviceState *d)
++{
++    VirtIOPCI *s =
++            container_of(d, VirtIOPCI, pci_dev.qdev);
++    virtio_pci_stop_ioeventfd(s);
++    if (s->vdev) {
++        virtio_reset(s->vdev);
++    }
++    msix_unuse_all_vectors(&s->pci_dev);
++    s->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
++}
++
++static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
++{
++    VirtIOPCI *s = opaque;
++    VirtIODevice *vdev = s->vdev;
++    target_phys_addr_t pa;
++
++    switch (addr) {
++    case VIRTIO_PCI_GUEST_FEATURES:
++      /* Guest does not negotiate properly?  We have to assume nothing. */
++      if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
++            val = vdev->bad_features ? vdev->bad_features(vdev) : 0;
++      }
++        virtio_set_features(vdev, val);
++        break;
++    case VIRTIO_PCI_QUEUE_PFN:
++        pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
++        if (pa == 0) {
++            virtio_pci_stop_ioeventfd(s);
++            virtio_reset(s->vdev);
++            msix_unuse_all_vectors(&s->pci_dev);
++        }
++        else
++            virtio_queue_set_addr(vdev, vdev->queue_sel, pa);
++        break;
++    case VIRTIO_PCI_QUEUE_SEL:
++        if (val < VIRTIO_PCI_QUEUE_MAX)
++            vdev->queue_sel = val;
++        break;
++    case VIRTIO_PCI_QUEUE_NOTIFY:
++        if (val < VIRTIO_PCI_QUEUE_MAX) {
++            virtio_queue_notify(vdev, val);
++        }
++        break;
++    case VIRTIO_PCI_STATUS:
++        if (!(val & VIRTIO_CONFIG_S_DRIVER_OK)) {
++            virtio_pci_stop_ioeventfd(s);
++        }
++
++        virtio_set_status(vdev, val & 0xFF);
++
++        if (val & VIRTIO_CONFIG_S_DRIVER_OK) {
++            virtio_pci_start_ioeventfd(s);
++        }
++
++        if (vdev->status == 0) {
++            virtio_reset(s->vdev);
++            msix_unuse_all_vectors(&s->pci_dev);
++        }
++
++        /* Linux before 2.6.34 sets the device as OK without enabling
++           the PCI device bus master bit. In this case we need to disable
++           some safety checks. */
++        if ((val & VIRTIO_CONFIG_S_DRIVER_OK) &&
++            !(s->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
++            s->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
++        }
++        break;
++    case VIRTIO_MSI_CONFIG_VECTOR:
++        msix_vector_unuse(&s->pci_dev, vdev->config_vector);
++        /* Make it possible for guest to discover an error took place. */
++        if (msix_vector_use(&s->pci_dev, val) < 0)
++            val = VIRTIO_NO_VECTOR;
++        vdev->config_vector = val;
++        break;
++    case VIRTIO_MSI_QUEUE_VECTOR:
++        msix_vector_unuse(&s->pci_dev,
++                          virtio_queue_vector(vdev, vdev->queue_sel));
++        /* Make it possible for guest to discover an error took place. */
++        if (msix_vector_use(&s->pci_dev, val) < 0)
++            val = VIRTIO_NO_VECTOR;
++        virtio_queue_set_vector(vdev, vdev->queue_sel, val);
++        break;
++    default:
++        error_report("%s: unexpected address 0x%x value 0x%x",
++                     __func__, addr, val);
++        break;
++    }
++}
++
++static uint32_t virtio_ioport_read(VirtIOPCI *s, uint32_t addr)
++{
++    VirtIODevice *vdev = s->vdev;
++    uint32_t ret = 0xFFFFFFFF;
++
++    switch (addr) {
++    case VIRTIO_PCI_HOST_FEATURES:
++        ret = s->host_features;
++        break;
++    case VIRTIO_PCI_GUEST_FEATURES:
++        ret = vdev->guest_features;
++        break;
++    case VIRTIO_PCI_QUEUE_PFN:
++        ret = virtio_queue_get_addr(vdev, vdev->queue_sel)
++              >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
++        break;
++    case VIRTIO_PCI_QUEUE_NUM:
++        ret = virtio_queue_get_num(vdev, vdev->queue_sel);
++        break;
++    case VIRTIO_PCI_QUEUE_SEL:
++        ret = vdev->queue_sel;
++        break;
++    case VIRTIO_PCI_STATUS:
++        ret = vdev->status;
++        break;
++    case VIRTIO_PCI_ISR:
++        /* reading from the ISR also clears it. */
++        ret = vdev->isr;
++        vdev->isr = 0;
++        qemu_set_irq(s->pci_dev.irq[0], 0);
++        break;
++    case VIRTIO_MSI_CONFIG_VECTOR:
++        ret = vdev->config_vector;
++        break;
++    case VIRTIO_MSI_QUEUE_VECTOR:
++        ret = virtio_queue_vector(vdev, vdev->queue_sel);
++        break;
++    default:
++        break;
++    }
++
++    return ret;
++}
++
++static uint32_t virtio_pci_config_readb(void *opaque, uint32_t addr)
++{
++    VirtIOPCI *s = opaque;
++    uint32_t config = VIRTIO_PCI_CONFIG(&s->pci_dev);
++    if (addr < config)
++        return virtio_ioport_read(s, addr);
++    addr -= config;
++    return virtio_config_readb(s->vdev, addr);
++}
++
++static uint32_t virtio_pci_config_readw(void *opaque, uint32_t addr)
++{
++    VirtIOPCI *s = opaque;
++    uint32_t config = VIRTIO_PCI_CONFIG(&s->pci_dev);
++    uint16_t val;
++    if (addr < config)
++        return virtio_ioport_read(s, addr);
++    addr -= config;
++    val = virtio_config_readw(s->vdev, addr);
++    if (virtio_is_big_endian()) {
++        /*
++         * virtio is odd, ioports are LE but config space is target native
++         * endian. However, in qemu, all PIO is LE, so we need to re-swap
++         * on BE targets
++         */
++        val = bswap16(val);
++    }
++    return val;
++}
++
++static uint32_t virtio_pci_config_readl(void *opaque, uint32_t addr)
++{
++    VirtIOPCI *s = opaque;
++    uint32_t config = VIRTIO_PCI_CONFIG(&s->pci_dev);
++    uint32_t val;
++    if (addr < config)
++        return virtio_ioport_read(s, addr);
++    addr -= config;
++    val = virtio_config_readl(s->vdev, addr);
++    if (virtio_is_big_endian()) {
++        val = bswap32(val);
++    }
++    return val;
++}
++
++static void virtio_pci_config_writeb(void *opaque, uint32_t addr, uint32_t val)
++{
++    VirtIOPCI *s = opaque;
++    uint32_t config = VIRTIO_PCI_CONFIG(&s->pci_dev);
++    if (addr < config) {
++        virtio_ioport_write(s, addr, val);
++        return;
++    }
++    addr -= config;
++    virtio_config_writeb(s->vdev, addr, val);
++}
++
++static void virtio_pci_config_writew(void *opaque, uint32_t addr, uint32_t val)
++{
++    VirtIOPCI *s = opaque;
++    uint32_t config = VIRTIO_PCI_CONFIG(&s->pci_dev);
++    if (addr < config) {
++        virtio_ioport_write(s, addr, val);
++        return;
++    }
++    addr -= config;
++    if (virtio_is_big_endian()) {
++        val = bswap16(val);
++    }
++    virtio_config_writew(s->vdev, addr, val);
++}
++
++static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val)
++{
++    VirtIOPCI *s = opaque;
++    uint32_t config = VIRTIO_PCI_CONFIG(&s->pci_dev);
++    if (addr < config) {
++        virtio_ioport_write(s, addr, val);
++        return;
++    }
++    addr -= config;
++    if (virtio_is_big_endian()) {
++        val = bswap32(val);
++    }
++    virtio_config_writel(s->vdev, addr, val);
++}
++
++static const MemoryRegionPortio virtio_portio[] = {
++    { 0, 0x10000, 1, .write = virtio_pci_config_writeb, },
++    { 0, 0x10000, 2, .write = virtio_pci_config_writew, },
++    { 0, 0x10000, 4, .write = virtio_pci_config_writel, },
++    { 0, 0x10000, 1, .read = virtio_pci_config_readb, },
++    { 0, 0x10000, 2, .read = virtio_pci_config_readw, },
++    { 0, 0x10000, 4, .read = virtio_pci_config_readl, },
++    PORTIO_END_OF_LIST()
++};
++
++static const MemoryRegionOps virtio_pci_config_ops = {
++    .old_portio = virtio_portio,
++    .endianness = DEVICE_LITTLE_ENDIAN,
++};
++
++static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
++                                uint32_t val, int len)
++{
++    VirtIOPCI *s = DO_UPCAST(VirtIOPCI,
++            pci_dev, pci_dev);
++
++    pci_default_write_config(pci_dev, address, val, len);
++
++    if (range_covers_byte(address, len, PCI_COMMAND) &&
++        !(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER) &&
++        !(s->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
++        virtio_pci_stop_ioeventfd(s);
++        virtio_set_status(s->vdev,
++                          s->vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
++    }
++}
++
++static unsigned virtio_pci_get_features(void *opaque)
++{
++    VirtIOPCI *s = opaque;
++    return s->host_features;
++}
++
++static int kvm_virtio_pci_vq_vector_use(VirtIOPCI *s,
++                                        unsigned int queue_no,
++                                        unsigned int vector,
++                                        MSIMessage msg)
++{
++    VirtQueue *vq = virtio_get_queue(s->vdev, queue_no);
++    EventNotifier *n = virtio_queue_get_guest_notifier(vq);
++    VirtIOIRQFD *irqfd = &s->vector_irqfd[vector];
++    int ret;
++
++    if (irqfd->users == 0) {
++        ret = kvm_irqchip_add_msi_route(kvm_state, msg);
++        if (ret < 0) {
++            return ret;
++        }
++        irqfd->virq = ret;
++    }
++    irqfd->users++;
++
++    ret = kvm_irqchip_add_irq_notifier(kvm_state, n, irqfd->virq);
++    if (ret < 0) {
++        if (--irqfd->users == 0) {
++            kvm_irqchip_release_virq(kvm_state, irqfd->virq);
++        }
++        return ret;
++    }
++
++    virtio_queue_set_guest_notifier_fd_handler(vq, true, true);
++    return 0;
++}
++
++static void kvm_virtio_pci_vq_vector_release(VirtIOPCI *s,
++                                             unsigned int queue_no,
++                                             unsigned int vector)
++{
++    VirtQueue *vq = virtio_get_queue(s->vdev, queue_no);
++    EventNotifier *n = virtio_queue_get_guest_notifier(vq);
++    VirtIOIRQFD *irqfd = &s->vector_irqfd[vector];
++    int ret;
++
++    ret = kvm_irqchip_remove_irq_notifier(kvm_state, n, irqfd->virq);
++    assert(ret == 0);
++
++    if (--irqfd->users == 0) {
++        kvm_irqchip_release_virq(kvm_state, irqfd->virq);
++    }
++
++    virtio_queue_set_guest_notifier_fd_handler(vq, true, false);
++}
++
++static int kvm_virtio_pci_vector_use(PCIDevice *dev, unsigned vector,
++                                     MSIMessage msg)
++{
++    VirtIOPCI *s = container_of(dev, VirtIOPCI, pci_dev);
++    VirtIODevice *vdev = s->vdev;
++    int ret, queue_no;
++
++    for (queue_no = 0; queue_no < VIRTIO_PCI_QUEUE_MAX; queue_no++) {
++        if (!virtio_queue_get_num(vdev, queue_no)) {
++            break;
++        }
++        if (virtio_queue_vector(vdev, queue_no) != vector) {
++            continue;
++        }
++        ret = kvm_virtio_pci_vq_vector_use(s, queue_no, vector, msg);
++        if (ret < 0) {
++            goto undo;
++        }
++    }
++    return 0;
++
++undo:
++    while (--queue_no >= 0) {
++        if (virtio_queue_vector(vdev, queue_no) != vector) {
++            continue;
++        }
++        kvm_virtio_pci_vq_vector_release(s, queue_no, vector);
++    }
++    return ret;
++}
++
++static void kvm_virtio_pci_vector_release(PCIDevice *dev, unsigned vector)
++{
++    VirtIOPCI *s = container_of(dev, VirtIOPCI, pci_dev);
++    VirtIODevice *vdev = s->vdev;
++    int queue_no;
++
++    for (queue_no = 0; queue_no < VIRTIO_PCI_QUEUE_MAX; queue_no++) {
++        if (!virtio_queue_get_num(vdev, queue_no)) {
++            break;
++        }
++        if (virtio_queue_vector(vdev, queue_no) != vector) {
++            continue;
++        }
++        kvm_virtio_pci_vq_vector_release(s, queue_no, vector);
++    }
++}
++
++static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
++{
++    VirtIOPCI *s = opaque;
++    VirtQueue *vq = virtio_get_queue(s->vdev, n);
++    EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
++
++    if (assign) {
++        int r = event_notifier_init(notifier, 0);
++        if (r < 0) {
++            return r;
++        }
++        virtio_queue_set_guest_notifier_fd_handler(vq, true, false);
++    } else {
++        virtio_queue_set_guest_notifier_fd_handler(vq, false, false);
++        event_notifier_cleanup(notifier);
++    }
++
++    return 0;
++}
++
++static bool virtio_pci_query_guest_notifiers(void *opaque)
++{
++    VirtIOPCI *s = opaque;
++    return msix_enabled(&s->pci_dev);
++}
++
++static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
++{
++    VirtIOPCI *s = opaque;
++    VirtIODevice *vdev = s->vdev;
++    int r, n;
++
++    /* Must unset vector notifier while guest notifier is still assigned */
++    if (kvm_msi_via_irqfd_enabled() && !assign) {
++        msix_unset_vector_notifiers(&s->pci_dev);
++        g_free(s->vector_irqfd);
++        s->vector_irqfd = NULL;
++    }
++
++    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
++        if (!virtio_queue_get_num(vdev, n)) {
++            break;
++        }
++
++        r = virtio_pci_set_guest_notifier(opaque, n, assign);
++        if (r < 0) {
++            goto assign_error;
++        }
++    }
++
++    /* Must set vector notifier after guest notifier has been assigned */
++    if (kvm_msi_via_irqfd_enabled() && assign) {
++        s->vector_irqfd =
++            g_malloc0(sizeof(*s->vector_irqfd) *
++                      msix_nr_vectors_allocated(&s->pci_dev));
++        r = msix_set_vector_notifiers(&s->pci_dev,
++                                      kvm_virtio_pci_vector_use,
++                                      kvm_virtio_pci_vector_release);
++        if (r < 0) {
++            goto assign_error;
++        }
++    }
++
++    return 0;
++
++assign_error:
++    /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
++    assert(assign);
++    while (--n >= 0) {
++        virtio_pci_set_guest_notifier(opaque, n, !assign);
++    }
++    return r;
++}
++
++static int virtio_pci_set_host_notifier(void *opaque, int n, bool assign)
++{
++    VirtIOPCI *s = opaque;
++
++    /* Stop using ioeventfd for virtqueue kick if the device starts using host
++     * notifiers.  This makes it easy to avoid stepping on each others' toes.
++     */
++    s->ioeventfd_disabled = assign;
++    if (assign) {
++        virtio_pci_stop_ioeventfd(s);
++    }
++    /* We don't need to start here: it's not needed because backend
++     * currently only stops on status change away from ok,
++     * reset, vmstop and such. If we do add code to start here,
++     * need to check vmstate, device state etc. */
++    return virtio_pci_set_host_notifier_internal(s, n, assign, false);
++}
++
++static void virtio_pci_vmstate_change(void *opaque, bool running)
++{
++    VirtIOPCI *s = opaque;
++
++    if (running) {
++        /* Try to find out if the guest has bus master disabled, but is
++           in ready state. Then we have a buggy guest OS. */
++        if ((s->vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
++            !(s->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
++            s->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
++        }
++        virtio_pci_start_ioeventfd(s);
++    } else {
++        virtio_pci_stop_ioeventfd(s);
++    }
++}
++
++static const VirtIOBindings virtio_pci_bindings = {
++    .notify = virtio_pci_notify,
++    .save_config = virtio_pci_save_config,
++    .load_config = virtio_pci_load_config,
++    .save_queue = virtio_pci_save_queue,
++    .load_queue = virtio_pci_load_queue,
++    .get_features = virtio_pci_get_features,
++    .query_guest_notifiers = virtio_pci_query_guest_notifiers,
++    .set_host_notifier = virtio_pci_set_host_notifier,
++    .set_guest_notifiers = virtio_pci_set_guest_notifiers,
++    .vmstate_change = virtio_pci_vmstate_change,
++};
++
++static void virtio_init_pci_(VirtIOPCI *s, VirtIODevice *vdev)
++{
++    uint8_t *config;
++    uint32_t size;
++
++    s->vdev = vdev;
++
++    config = s->pci_dev.config;
++
++    if (s->class_code) {
++        pci_config_set_class(config, s->class_code);
++    }
++    pci_set_word(config + PCI_SUBSYSTEM_VENDOR_ID,
++                 pci_get_word(config + PCI_VENDOR_ID));
++    pci_set_word(config + PCI_SUBSYSTEM_ID, vdev->device_id);
++    config[PCI_INTERRUPT_PIN] = 1;
++
++    if (vdev->nvectors &&
++        msix_init_exclusive_bar(&s->pci_dev, vdev->nvectors, 1)) {
++        vdev->nvectors = 0;
++    }
++
++    s->pci_dev.config_write = virtio_write_config;
++
++    size = VIRTIO_PCI_REGION_SIZE(&s->pci_dev) + vdev->config_len;
++    if (size & (size-1))
++        size = 1 << qemu_fls(size);
++
++    memory_region_init_io(&s->bar, &virtio_pci_config_ops, s,
++                          "virtio-pci", size);
++    pci_register_bar(&s->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO,
++                     &s->bar);
++
++    if (!kvm_has_many_ioeventfds()) {
++        s->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
++    }
++
++    virtio_bind_device(vdev, &virtio_pci_bindings, s);
++    s->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
++    s->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
++    s->host_features = vdev->get_features(vdev, s->host_features);
++}
++
++static void virtio_exit_pci(PCIDevice *pci_dev)
++{
++    VirtIOPCI *s = DO_UPCAST(VirtIOPCI, pci_dev, pci_dev);
++
++    memory_region_destroy(&s->bar);
++    msix_uninit_exclusive_bar(pci_dev);
++}
++
++static int virtio_pci_transport_cb(DeviceState *dev, VirtIODevice *vdev,
++        VirtIOTransportLink *trl)
++{
++    PCIDevice *pci_dev = DO_UPCAST(PCIDevice, qdev, trl->tr);
++    VirtIOPCI *s = DO_UPCAST(VirtIOPCI, pci_dev, pci_dev);
++
++    virtio_plug_into_transport(dev, trl);
++
++    // TODO: Figure out if props were explicitly set before
++
++    /* Get default host_features passed from back-end */
++    s->host_features = s->trl->host_features;
++
++    switch (vdev->device_id) {
++    case VIRTIO_ID_BLOCK:
++        s->flags |= VIRTIO_PCI_FLAG_USE_IOEVENTFD;
++        s->nvectors = 2;
++
++        if (s->class_code != PCI_CLASS_STORAGE_SCSI &&
++            s->class_code != PCI_CLASS_STORAGE_OTHER) {
++            s->class_code = PCI_CLASS_STORAGE_SCSI;
++        }
++
++        vdev->nvectors = s->nvectors;
++        pci_config_set_device_id(s->pci_dev.config, PCI_DEVICE_ID_VIRTIO_BLOCK);
++        pci_config_set_class(s->pci_dev.config, PCI_CLASS_STORAGE_SCSI);
++        virtio_init_pci_(s, vdev);
++        s->nvectors = vdev->nvectors;
++        break;
++    case VIRTIO_ID_NET:
++        s->nvectors = 3;
++
++        /* load rom */
++        pci_dev->romfile = g_strdup("pxe-virtio.rom");
++        pci_add_option_rom(pci_dev, false);
++
++        vdev->nvectors = s->nvectors;
++        pci_config_set_device_id(s->pci_dev.config, PCI_DEVICE_ID_VIRTIO_NET);
++        pci_config_set_class(s->pci_dev.config, PCI_CLASS_NETWORK_ETHERNET);
++        virtio_init_pci_(s, vdev);
++        s->nvectors = vdev->nvectors;
++        break;
++    case VIRTIO_ID_BALLOON:
++        break;
++    case VIRTIO_ID_SCSI:
++        break;
++    case VIRTIO_ID_CONSOLE:
++    {
++        break;
++    }
++    default:
++        fprintf(stderr,
++                "Unknown back-end device id: 0x%" PRIx16 "\n", vdev->device_id);
++        return -1;
++    }
++
++    return 0;
++}
++
++static int virtio_pci_device_init(PCIDevice *pci_dev)
++{
++    VirtIOPCI *s =
++            DO_UPCAST(VirtIOPCI, pci_dev, pci_dev);
++
++    virtio_init_transport(&pci_dev->qdev, &s->trl, VIRTIO_PCI,
++            virtio_pci_transport_cb);
++
++    return 0;
++}
++
++static void virtio_pci_device_exit(PCIDevice *pci_dev)
++{
++    VirtIOPCI *s =
++            DO_UPCAST(VirtIOPCI, pci_dev, pci_dev);
++
++    switch (s->vdev->device_id) {
++        case VIRTIO_ID_BLOCK:
++            virtio_pci_stop_ioeventfd(s);
++            virtio_blk_exit(s->vdev);
++            break;
++        case VIRTIO_ID_NET:
++            virtio_pci_stop_ioeventfd(s);
++            virtio_net_exit(s->vdev);
++            break;
++        case VIRTIO_ID_BALLOON:
++            virtio_pci_stop_ioeventfd(s);
++            virtio_balloon_exit(s->vdev);
++            break;
++        case VIRTIO_ID_SCSI:
++            virtio_scsi_exit(s->vdev);
++            break;
++        case VIRTIO_ID_CONSOLE:
++            virtio_pci_stop_ioeventfd(s);
++            virtio_serial_exit(s->vdev);
++            break;
++        default:
++            fprintf(stderr,
++                    "Unknown back-end device id: 0x%" PRIx16 "\n",
++                    s->vdev->device_id);
++            return;
++        }
++
++    virtio_exit_pci(pci_dev);
++
++    return;
++}
++
++/******************** VirtIOPCI Device **********************/
++
++static Property virtio_pci_properties[] = {
++    DEFINE_PROP_HEX32("class", VirtIOPCI, class_code, 0),
++    DEFINE_PROP_BIT("ioeventfd", VirtIOPCI, flags,
++            VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
++    DEFINE_PROP_UINT32("vectors", VirtIOPCI, nvectors, 0),
++    DEFINE_PROP_END_OF_LIST(),
++};
++
++static void virtio_pci_class_init(ObjectClass *klass, void *data)
++{
++    DeviceClass *dc = DEVICE_CLASS(klass);
++    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
++    k->init = virtio_pci_device_init;
++    k->exit = virtio_pci_device_exit;
++    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
++    k->revision = VIRTIO_PCI_ABI_VERSION;
++    k->class_id = PCI_CLASS_OTHERS;
++    dc->reset = virtio_pci_reset_;
++    dc->props = virtio_pci_properties;
++}
++
++static TypeInfo virtio_pci_info = {
++    .name = VIRTIO_PCI,
++    .parent = TYPE_PCI_DEVICE,
++    .instance_size = sizeof(VirtIOPCI),
++    .class_init = virtio_pci_class_init,
++};
++
++/************************************************************/
++
++static void virtio_pci_register_types(void)
++{
++    type_register_static(&virtio_pci_info);
++}
++
++type_init(virtio_pci_register_types)
diff --cc hw/virtio-pci.c
@@@ -811,50 -877,9 +881,50 @@@ static void virtio_balloon_exit_pci(PCI
  
      virtio_pci_stop_ioeventfd(proxy);
      virtio_balloon_exit(proxy->vdev);
-     return virtio_exit_pci(pci_dev);
+     virtio_exit_pci(pci_dev);
  }
  
- static int maru_virtio_touchscreen_exit_pci(PCIDevice *pci_dev)
 +#ifdef CONFIG_VIRTIO_GL
 +#if defined(CONFIG_MARU) && (!defined(CONFIG_DARWIN))
 +static int virtio_gl_init_pci(PCIDevice *pci_dev)
 +{
 +    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
 +    VirtIODevice *vdev;
 +
 +    vdev = virtio_gl_init(&pci_dev->qdev);
 +    if (!vdev) {
 +        return -1;
 +    }
 +    virtio_init_pci(proxy, vdev);
 +    return 0;
 +}
 +#endif
 +#endif
 +
 +#ifdef CONFIG_MARU
 +static int maru_virtio_touchscreen_init_pci(PCIDevice *pci_dev)
 +{
 +    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
 +    VirtIODevice *vdev;
 +
 +    vdev = maru_virtio_touchscreen_init(&pci_dev->qdev);
 +    if (!vdev) {
 +        return -1;
 +    }
 +    virtio_init_pci(proxy, vdev);
 +    return 0;
 +}
 +
-     return virtio_exit_pci(pci_dev);
++static void maru_virtio_touchscreen_exit_pci(PCIDevice *pci_dev)
 +{
 +    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
 +
 +    virtio_pci_stop_ioeventfd(proxy);
 +    maru_virtio_touchscreen_exit(proxy->vdev);
++    virtio_exit_pci(pci_dev);
 +}
 +#endif
 +
  static Property virtio_blk_properties[] = {
      DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
      DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, blk.conf),
diff --cc hw/virtio-pci.h
@@@ -44,10 -48,11 +48,29 @@@ typedef struct 
      VirtIOSCSIConf scsi;
      bool ioeventfd_disabled;
      bool ioeventfd_started;
+     VirtIOIRQFD *vector_irqfd;
  } VirtIOPCIProxy;
  
++typedef struct {
++    PCIDevice pci_dev;
++    VirtIODevice *vdev;
++    MemoryRegion bar;
++
++    uint32_t flags;
++    uint32_t class_code;
++    uint32_t nvectors;
++    uint32_t host_features;
++
++    VirtIOTransportLink *trl;
++
++    bool ioeventfd_disabled;
++    bool ioeventfd_started;
++    VirtIOIRQFD *vector_irqfd;
++} VirtIOPCI;
++
  void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev);
  void virtio_pci_reset(DeviceState *d);
++void virtio_pci_reset_(DeviceState *d);
  
  /* Virtio ABI version, if we increment this, we break the guest driver. */
  #define VIRTIO_PCI_ABI_VERSION          0
@@@ -1001,44 -1014,3 +1015,46 @@@ static void virtio_serial_register_type
  }
  
  type_init(virtio_serial_register_types)
-     VirtIOSerState *proxy = VIRTIO_SERIAL_FROM_QDEV(dev);
-     vdev = virtio_serial_init(dev, &proxy->serial);
 +
 +/******************** VirtIOSer Device **********************/
 +
 +static int virtio_serialdev_init(DeviceState *dev)
 +{
 +    VirtIODevice *vdev;
-     return virtio_init_transport(dev, vdev);
++    VirtIOSerState *s = VIRTIO_SERIAL_FROM_QDEV(dev);
++    vdev = virtio_serial_init(dev, &s->serial);
 +    if (!vdev) {
 +        return -1;
 +    }
-     dc->bus_info = &virtio_transport_bus_info;
++
++    assert(s->trl != NULL);
++
++    return virtio_call_backend_init_cb(dev, s->trl, vdev);
 +}
 +
 +static Property virtio_serial_properties[] = {
 +    DEFINE_PROP_UINT32("max_ports", VirtIOSerState,
 +                       serial.max_virtserial_ports, 31),
 +    DEFINE_PROP_END_OF_LIST(),
 +};
 +
 +static void virtio_serial_class_init(ObjectClass *klass, void *data)
 +{
 +    DeviceClass *dc = DEVICE_CLASS(klass);
 +    dc->init = virtio_serialdev_init;
 +    dc->props = virtio_serial_properties;
 +}
 +
 +static TypeInfo virtio_serial_info = {
 +    .name = "virtio-serial",
 +    .parent = TYPE_DEVICE,
 +    .instance_size = sizeof(VirtIOSerState),
 +    .class_init = virtio_serial_class_init,
 +};
 +
 +static void virtio_ser_register_types(void)
 +{
 +    type_register_static(&virtio_serial_info);
 +}
 +
 +type_init(virtio_ser_register_types)
  #ifndef _QEMU_VIRTIO_SERIAL_H
  #define _QEMU_VIRTIO_SERIAL_H
  
 +#include "sysbus.h"
  #include "qdev.h"
  #include "virtio.h"
++#include "virtio-transport.h"
  
  /* == Interface shared between the guest kernel and qemu == */
  
@@@ -174,14 -173,6 +175,15 @@@ struct VirtIOSerialPort 
      bool throttled;
  };
  
 +typedef struct {
 +    DeviceState qdev;
 +    /* virtio-serial */
 +    virtio_serial_conf serial;
++    VirtIOTransportLink *trl;
 +} VirtIOSerState;
 +
 +#define VIRTIO_SERIAL_FROM_QDEV(dev) DO_UPCAST(VirtIOSerState, qdev, dev)
 +
  /* Interface to the virtio-serial bus */
  
  /*
index 078c726,0000000..76360ba
mode 100644,000000..100644
--- /dev/null
@@@ -1,100 -1,0 +1,147 @@@
- struct BusInfo virtio_transport_bus_info = {
-     .name = VIRTIO_TRANSPORT_BUS,
-     .size = sizeof(VirtIOTransportBusState),
- };
 +/*
 + * Virtio transport bindings
 + *
 + * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd.
 + *
 + * Author:
 + *  Evgeny Voevodin <e.voevodin@samsung.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License; 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, see <http://www.gnu.org/licenses/>.
 + */
 +
 +#include "virtio-transport.h"
 +
 +#define VIRTIO_TRANSPORT_BUS "virtio-transport"
 +
- int virtio_init_transport(DeviceState *dev, VirtIODevice *vdev)
++static QTAILQ_HEAD(, VirtIOTransportLink) transport_links =
++        QTAILQ_HEAD_INITIALIZER(transport_links);
 +
-     DeviceState *transport_dev = qdev_get_parent_bus(dev)->parent;
-     BusState *bus;
-     VirtIOTransportBusState *virtio_transport_bus;
++/*
++ * Find transport device by its ID.
++ */
++VirtIOTransportLink* virtio_find_transport(const char *name)
 +{
-     /* transport device has single child bus */
-     bus = QLIST_FIRST(&transport_dev->child_bus);
-     virtio_transport_bus = DO_UPCAST(VirtIOTransportBusState, bus, bus);
++    VirtIOTransportLink *trl;
 +
-     if (virtio_transport_bus->init_fn) {
-         return virtio_transport_bus->init_fn(dev, vdev);
++    assert(name != NULL);
 +
-     return 0;
++    QTAILQ_FOREACH(trl, &transport_links, sibling) {
++        if (trl->tr->id != NULL) {
++            if (!strcmp(name, trl->tr->id)) {
++                return trl;
++            }
++        }
 +    }
 +
- uint32_t virtio_count_siblings(BusState *parent_bus, const char *child_bus)
++    return NULL;
 +}
 +
-     DeviceState *dev;
-     BusState *bus;
++/*
++ * Count transport devices by ID.
++ */
++uint32_t virtio_count_transports(const char *name)
 +{
-     char *buf;
-     int len;
-     if (child_bus) {
-         len = strlen(child_bus) + 1;
-         buf = g_malloc(len);
-         snprintf(buf, len, "%s.", child_bus);
-         len = strlen(buf);
-         QTAILQ_FOREACH(dev, &parent_bus->children, sibling) {
-             QLIST_FOREACH(bus, &dev->child_bus, sibling) {
-                 if (strncmp(buf, bus->name, len) == 0) {
-                     i++;
-                 }
-             }
-         }
++    VirtIOTransportLink *trl;
 +    uint32_t i = 0;
-     } else {
-         QTAILQ_FOREACH(dev, &parent_bus->children, sibling) {
 +
-     }
++    QTAILQ_FOREACH(trl, &transport_links, sibling) {
++        if (name == NULL) {
 +            i++;
++            continue;
 +        }
-  * Get transport device which does not have a child.
 +
++        if (trl->tr->id != NULL) {
++            if (!strncmp(name, trl->tr->id,strlen(name))) {
++                i++;
++            }
++        }
++    }
 +    return i;
 +}
 +
 +/*
- DeviceState* virtio_get_free_transport(BusState *parent_bus,
-                                        const char *child_bus)
++ * Initialize new transport device
 + */
-     DeviceState *dev;
-     BusState *bus;
++char* virtio_init_transport(DeviceState *dev, VirtIOTransportLink **trl,
++        const char* name, virtio_backend_init_cb cb)
 +{
-     assert(child_bus != NULL);
++    VirtIOTransportLink *link = g_malloc0(sizeof(VirtIOTransportLink));
++    char *buf;
++    size_t len;
++    uint32_t i;
 +
-     QTAILQ_FOREACH(dev, &parent_bus->children, sibling) {
-         QLIST_FOREACH(bus, &dev->child_bus, sibling) {
-             if (strncmp(child_bus, bus->name, strlen(child_bus)) == 0) {
-                 if (!virtio_count_siblings(bus, NULL)) {
-                     return dev;
-                 }
-             }
++    assert(dev != NULL);
++    assert(name != NULL);
++    assert(trl != NULL);
 +
-     return NULL;
++    i = virtio_count_transports(name);
++    len = strlen(name) + 16;
++    buf = g_malloc(len);
++    snprintf(buf, len, "%s.%d", name, i);
++    qbus_create(TYPE_VIRTIO_BUS, dev, buf);
++
++    /* Add new transport */
++    QTAILQ_INSERT_TAIL(&transport_links, link, sibling);
++    link->tr = dev;
++    link->cb = cb;
++    // TODO: Add a link property
++    *trl = link;
++    return buf;
++}
++
++/*
++ * Unplug back-end from system bus and plug it into transport bus.
++ */
++void virtio_plug_into_transport(DeviceState *dev, VirtIOTransportLink *trl)
++{
++    BusChild *kid;
++
++    /* Unplug back-end from system bus */
++    QTAILQ_FOREACH(kid, &qdev_get_parent_bus(dev)->children, sibling) {
++        if (kid->child == dev) {
++            QTAILQ_REMOVE(&qdev_get_parent_bus(dev)->children, kid, sibling);
++            break;
 +        }
 +    }
 +
++    /* Plug back-end into transport's bus */
++    qdev_set_parent_bus(dev, QLIST_FIRST(&trl->tr->child_bus));
++
++}
++
++/*
++ * Execute call-back on back-end initialization.
++ * Performs initialization of MMIO or PCI transport.
++ */
++int virtio_call_backend_init_cb(DeviceState *dev, VirtIOTransportLink *trl,
++        VirtIODevice *vdev)
++{
++    if (trl->cb) {
++        return trl->cb(dev, vdev, trl);
++    }
++
++    return 0;
++}
++
++static const TypeInfo virtio_bus_info = {
++    .name = TYPE_VIRTIO_BUS,
++    .parent = TYPE_BUS,
++    .instance_size = sizeof(BusState),
++};
++
++static void virtio_register_types(void)
++{
++    type_register_static(&virtio_bus_info);
 +}
++
++type_init(virtio_register_types)
index e41a2fa,0000000..43200dc
mode 100644,000000..100644
--- /dev/null
@@@ -1,47 -1,0 +1,74 @@@
- #include "sysbus.h"
- #include "virtio.h"
 +/*
 + * Virtio transport header
 + *
 + * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd.
 + *
 + * Author:
 + *  Evgeny Voevodin <e.voevodin@samsung.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License; 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, see <http://www.gnu.org/licenses/>.
 + */
 +
 +#ifndef VIRTIO_TRANSPORT_H_
 +#define VIRTIO_TRANSPORT_H_
 +
- #define VIRTIO_MMIO_TRANSPORT "virtio-mmio-transport"
++#include "qdev.h"
++#include "qemu-common.h"
 +
- extern struct BusInfo virtio_transport_bus_info;
++#define VIRTIO_MMIO "virtio-mmio"
++#define VIRTIO_PCI "virtio-pci"
 +
- typedef int (*virtio_init_transport_fn)(DeviceState *dev, VirtIODevice *vdev);
++#define TYPE_VIRTIO_BUS "virtio-bus"
++#define VIRTIO_BUS(obj) OBJECT_CHECK(virtio_bus, (obj), TYPE_VIRTIO_BUS)
 +
- typedef struct VirtIOTransportBusState {
-     BusState bus;
-     virtio_init_transport_fn init_fn;
- } VirtIOTransportBusState;
++struct VirtIOTransportLink;
 +
- int virtio_init_transport(DeviceState *dev, VirtIODevice *vdev);
- uint32_t virtio_count_siblings(BusState *parent_bus, const char *child_bus);
++typedef int (*virtio_backend_init_cb)(DeviceState *dev, VirtIODevice *vdev,
++             struct VirtIOTransportLink *trl);
++
++typedef struct VirtIOTransportLink {
++    DeviceState *tr;
++    virtio_backend_init_cb cb;
++    uint32_t host_features;
++    QTAILQ_ENTRY(VirtIOTransportLink) sibling;
++} VirtIOTransportLink;
++
++/*
++ * Find transport device by its ID.
++ */
++VirtIOTransportLink* virtio_find_transport(const char *name);
++
++/*
++ * Count transport devices by ID.
++ */
++uint32_t virtio_count_transports(const char *name);
++
++/*
++ * Initialize new transport device
++ */
++char* virtio_init_transport(DeviceState *dev, VirtIOTransportLink **trl,
++        const char* name, virtio_backend_init_cb cb);
++
++/*
++ * Unplug back-end from system bus and plug it into transport bus.
++ */
++void virtio_plug_into_transport(DeviceState *dev, VirtIOTransportLink *trl);
 +
-  * Get transport device which does not have a child.
 +/*
- DeviceState* virtio_get_free_transport(BusState *parent_bus,
-                                        const char *child_bus);
++ * Execute call-back on back-end initialization.
++ * Performs initialization of MMIO or PCI transport.
 + */
++int virtio_call_backend_init_cb(DeviceState *dev, VirtIOTransportLink *trl,
++        VirtIODevice *vdev);
 +
 +#endif /* VIRTIO_TRANSPORT_H_ */
diff --cc hw/virtio.c
Simple merge
diff --cc hw/virtio.h
Simple merge
index 6ab3476,0000000..a1723e7
mode 100644,000000..100644
--- /dev/null
@@@ -1,313 -1,0 +1,311 @@@
- static int yagl_device_exit(PCIDevice *dev)
 +#include "yagl_server.h"
 +#include "yagl_log.h"
 +#include "yagl_handle_gen.h"
 +#include "yagl_marshal.h"
 +#include "yagl_stats.h"
 +#include "cpu-all.h"
 +#include "hw.h"
 +#include "pci.h"
 +
 +#define PCI_VENDOR_ID_YAGL 0x19B1
 +#define PCI_DEVICE_ID_YAGL 0x1010
 +
 +#define YAGL_REG_BUFFPTR 0
 +#define YAGL_REG_TRIGGER 4
 +#define YAGL_REGS_SIZE   8
 +
 +#define YAGL_MEM_SIZE 0x1000
 +
 +#define YAGL_MAX_USERS (YAGL_MEM_SIZE / YAGL_REGS_SIZE)
 +
 +struct yagl_user
 +{
 +    uint8_t *buff;
 +    yagl_pid process_id;
 +    yagl_tid thread_id;
 +};
 +
 +typedef struct YaGLState
 +{
 +    PCIDevice dev;
 +    MemoryRegion iomem;
 +    struct yagl_server_state *ss;
 +    struct yagl_user users[YAGL_MAX_USERS];
 +
 +    /*
 +     * YAGL_MARSHAL_MAX_RESPONSE byte buffer to hold the response.
 +     */
 +    uint8_t *in_buff;
 +} YaGLState;
 +
 +#define TYPE_YAGL_DEVICE "yagl"
 +
 +static void yagl_device_operate(YaGLState *s,
 +                                int user_index,
 +                                target_phys_addr_t buff_pa)
 +{
 +    yagl_pid target_pid;
 +    yagl_tid target_tid;
 +    target_phys_addr_t buff_len = YAGL_MARSHAL_SIZE;
 +    uint8_t *buff = NULL, *tmp = NULL;
 +
 +    YAGL_LOG_FUNC_ENTER_NPT(yagl_device_operate,
 +                            "user_index = %d, buff_ptr = 0x%X",
 +                            user_index,
 +                            (uint32_t)buff_pa);
 +
 +    if (buff_pa && s->users[user_index].buff) {
 +        YAGL_LOG_CRITICAL("user %d is already activated", user_index);
 +        goto out;
 +    }
 +
 +    if (!buff_pa && !s->users[user_index].buff) {
 +        YAGL_LOG_CRITICAL("user %d is not activated", user_index);
 +        goto out;
 +    }
 +
 +    if (buff_pa) {
 +        /*
 +         * Activate user.
 +         */
 +
 +        buff = cpu_physical_memory_map(buff_pa, &buff_len, false);
 +
 +        if (!buff || (buff_len != YAGL_MARSHAL_SIZE)) {
 +            YAGL_LOG_CRITICAL("cpu_physical_memory_map(read) failed for user %d, buff_ptr = 0x%X",
 +                              user_index,
 +                              (uint32_t)buff_pa);
 +            goto out;
 +        }
 +
 +        tmp = buff;
 +
 +        yagl_marshal_skip(&tmp);
 +
 +        target_pid = yagl_marshal_get_pid(&tmp);
 +        target_tid = yagl_marshal_get_tid(&tmp);
 +
 +        YAGL_LOG_TRACE("pid = %u, tid = %u", target_pid, target_tid);
 +
 +        if (!target_pid || !target_tid) {
 +            YAGL_LOG_CRITICAL(
 +                "target-host protocol error, zero pid or tid from target");
 +            goto out;
 +        }
 +
 +        if (yagl_server_dispatch_init(s->ss,
 +                                      target_pid,
 +                                      target_tid,
 +                                      buff,
 +                                      s->in_buff)) {
 +
 +            memcpy(buff, s->in_buff, YAGL_MARSHAL_MAX_RESPONSE);
 +
 +            s->users[user_index].buff = buff;
 +            s->users[user_index].process_id = target_pid;
 +            s->users[user_index].thread_id = target_tid;
 +
 +            buff = NULL;
 +
 +            YAGL_LOG_INFO("user %d activated", user_index);
 +        }
 +    } else {
 +        /*
 +         * Deactivate user.
 +         */
 +
 +        yagl_server_dispatch_exit(s->ss,
 +                                  s->users[user_index].process_id,
 +                                  s->users[user_index].thread_id);
 +
 +        cpu_physical_memory_unmap(s->users[user_index].buff,
 +                                  YAGL_MARSHAL_SIZE,
 +                                  0,
 +                                  YAGL_MARSHAL_SIZE);
 +
 +        memset(&s->users[user_index], 0, sizeof(s->users[user_index]));
 +
 +        YAGL_LOG_INFO("user %d deactivated", user_index);
 +    }
 +
 +out:
 +    if (buff) {
 +        cpu_physical_memory_unmap(buff,
 +                                  YAGL_MARSHAL_SIZE,
 +                                  0,
 +                                  YAGL_MARSHAL_SIZE);
 +    }
 +
 +    YAGL_LOG_FUNC_EXIT(NULL);
 +}
 +
 +static void yagl_device_trigger(YaGLState *s, int user_index)
 +{
 +    YAGL_LOG_FUNC_ENTER_NPT(yagl_device_trigger, "%d", user_index);
 +
 +    if (!s->users[user_index].buff) {
 +        YAGL_LOG_CRITICAL("user %d not activated", user_index);
 +        goto out;
 +    }
 +
 +    yagl_server_dispatch(s->ss,
 +                         s->users[user_index].process_id,
 +                         s->users[user_index].thread_id,
 +                         s->users[user_index].buff,
 +                         s->in_buff);
 +
 +    memcpy(s->users[user_index].buff, s->in_buff, YAGL_MARSHAL_MAX_RESPONSE);
 +
 +out:
 +    YAGL_LOG_FUNC_EXIT(NULL);
 +}
 +
 +static uint64_t yagl_device_read(void *opaque, target_phys_addr_t offset,
 +                                 unsigned size)
 +{
 +    return 0;
 +}
 +
 +static void yagl_device_write(void *opaque, target_phys_addr_t offset,
 +                              uint64_t value, unsigned size)
 +{
 +    YaGLState *s = (YaGLState*)opaque;
 +    int user_index = (offset / YAGL_REGS_SIZE);
 +    offset -= user_index * YAGL_REGS_SIZE;
 +
 +    assert(user_index < YAGL_MAX_USERS);
 +
 +    if (user_index >= YAGL_MAX_USERS) {
 +        YAGL_LOG_CRITICAL("bad user index = %d", user_index);
 +        return;
 +    }
 +
 +    switch (offset) {
 +    case YAGL_REG_BUFFPTR:
 +        yagl_device_operate(s, user_index, value);
 +        break;
 +    case YAGL_REG_TRIGGER:
 +        yagl_device_trigger(s, user_index);
 +        break;
 +    default:
 +        YAGL_LOG_CRITICAL("user %d, bad offset = %d", user_index, offset);
 +        break;
 +    }
 +}
 +
 +static const MemoryRegionOps yagl_device_ops =
 +{
 +    .read = yagl_device_read,
 +    .write = yagl_device_write,
 +    .endianness = DEVICE_NATIVE_ENDIAN,
 +};
 +
 +static int yagl_device_init(PCIDevice *dev)
 +{
 +    YaGLState *s = DO_UPCAST(YaGLState, dev, dev);
 +
 +    yagl_log_init();
 +
 +    YAGL_LOG_FUNC_ENTER_NPT(yagl_device_init, NULL);
 +
 +    memory_region_init_io(&s->iomem,
 +                          &yagl_device_ops,
 +                          s,
 +                          TYPE_YAGL_DEVICE,
 +                          YAGL_MEM_SIZE);
 +
 +    yagl_handle_gen_init();
 +
 +    yagl_stats_init();
 +
 +    s->ss = yagl_server_state_create();
 +
 +    if (!s->ss) {
 +        yagl_stats_cleanup();
 +
 +        yagl_handle_gen_cleanup();
 +
 +        YAGL_LOG_FUNC_EXIT(NULL);
 +
 +        yagl_log_cleanup();
 +
 +        return -1;
 +    }
 +
 +    s->in_buff = g_malloc(YAGL_MARSHAL_MAX_RESPONSE);
 +
 +    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->iomem);
 +
 +    YAGL_LOG_FUNC_EXIT(NULL);
 +
 +    return 0;
 +}
 +
 +static void yagl_device_reset(DeviceState *d)
 +{
 +    YaGLState *s = container_of(d, YaGLState, dev.qdev);
 +    int i;
 +
 +    YAGL_LOG_FUNC_ENTER_NPT(yagl_device_reset, NULL);
 +
 +    yagl_server_reset(s->ss);
 +
 +    yagl_handle_gen_reset();
 +
 +    for (i = 0; i < YAGL_MAX_USERS; ++i) {
 +        memset(&s->users[i], 0, sizeof(s->users[i]));
 +    }
 +
 +    YAGL_LOG_FUNC_EXIT(NULL);
 +}
 +
-     return 0;
++static void yagl_device_exit(PCIDevice *dev)
 +{
 +    YaGLState *s = DO_UPCAST(YaGLState, dev, dev);
 +
 +    YAGL_LOG_FUNC_ENTER_NPT(yagl_device_exit, NULL);
 +
 +    memory_region_destroy(&s->iomem);
 +
 +    g_free(s->in_buff);
 +    s->in_buff = NULL;
 +
 +    yagl_server_state_destroy(s->ss);
 +
 +    yagl_stats_cleanup();
 +
 +    yagl_handle_gen_cleanup();
 +
 +    YAGL_LOG_FUNC_EXIT(NULL);
 +
 +    yagl_log_cleanup();
 +}
 +
 +static void yagl_class_init(ObjectClass *klass, void *data)
 +{
 +    DeviceClass *dc = DEVICE_CLASS(klass);
 +    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = yagl_device_init;
 +    k->exit = yagl_device_exit;
 +    k->vendor_id = PCI_VENDOR_ID_YAGL;
 +    k->device_id = PCI_DEVICE_ID_YAGL;
 +    k->class_id = PCI_CLASS_OTHERS;
 +    dc->reset = yagl_device_reset;
 +    dc->desc = "YaGL device";
 +}
 +
 +static TypeInfo yagl_device_info =
 +{
 +    .name          = TYPE_YAGL_DEVICE,
 +    .parent        = TYPE_PCI_DEVICE,
 +    .instance_size = sizeof(YaGLState),
 +    .class_init    = yagl_class_init,
 +};
 +
 +static void yagl_register_types(void)
 +{
 +    type_register_static(&yagl_device_info);
 +}
 +
 +type_init(yagl_register_types)
diff --cc kvm.h
Simple merge
diff --cc net/tap-win32.c
Simple merge
diff --cc os-win32.c
Simple merge
diff --cc oslib-posix.c
Simple merge
diff --cc qemu-char.c
Simple merge
diff --cc qemu-options.hx
Simple merge
Simple merge
diff --cc sysemu.h
Simple merge
@@@ -965,17 -2424,32 +2424,40 @@@ static int get_phys_addr_mpu(CPUARMStat
      return 0;
  }
  
 -static inline int get_phys_addr(CPUARMState *env, uint32_t address,
+ /* get_phys_addr - get the physical address for this virtual address
+  *
+  * Find the physical address corresponding to the given virtual address,
+  * by doing a translation table walk on MMU based systems or using the
+  * MPU state on MPU based systems.
+  *
+  * Returns 0 if the translation was successful. Otherwise, phys_ptr,
+  * prot and page_size are not filled in, and the return value provides
+  * information on why the translation aborted, in the format of a
+  * DFSR/IFSR fault register, with the following caveats:
+  *  * we honour the short vs long DFSR format differences.
+  *  * the WnR bit is never set (the caller must do this).
+  *  * for MPU based systems we don't bother to return a full FSR format
+  *    value.
+  *
+  * @env: CPUARMState
+  * @address: virtual address to get physical address for
+  * @access_type: 0 for read, 1 for write, 2 for execute
+  * @is_user: 0 for privileged access, 1 for user
+  * @phys_ptr: set to the physical address corresponding to the virtual address
+  * @prot: set to the permissions for the page containing phys_ptr
+  * @page_size: set to the size of the page containing phys_ptr
+  */
-                                 uint32_t *phys_ptr, int *prot,
 +#ifdef CONFIG_BUILD_GLES
 +int get_phys_addr(CPUARMState *env, uint32_t address,
 +                                int access_type, int is_user,
++                                target_phys_addr_t *phys_ptr, int *prot,
 +                                target_ulong *page_size);
 +#else
 +static inline
 +#endif
 +int get_phys_addr(CPUARMState *env, uint32_t address,
                                  int access_type, int is_user,
-                                 uint32_t *phys_ptr, int *prot,
+                                 target_phys_addr_t *phys_ptr, int *prot,
                                  target_ulong *page_size)
  {
      /* Fast Context Switch Extension.  */
Simple merge
Simple merge
diff --cc tcg/tcg.c
Simple merge
diff --cc tcg/tcg.h
Simple merge
index a98eabd,0000000..46e7cc4
mode 100755,000000..100755
--- /dev/null
@@@ -1,76 -1,0 +1,76 @@@
-  --enable-ldst-optimization \
 +#!/bin/sh
 +# OS specific
 +targetos=`uname -s`
 +targetarch=`echo | gcc -E -dM - | grep __x86_64`
 +bindir="i386"
 +ffmpegarc="x86"
 +if test "$targetarch" != ""
 +then
 +      bindir="x86_64"
 +      ffmpegarc="x86_64"
 +fi
 +
 +echo "##### checking for os... targetos $targetos"
 +
 +case $targetos in
 +Linux*)
 +cd distrib/libav
 +echo ""
 +echo "##### FFMPEG configure for emulator"
 +./configure \
 + --prefix=./$bindir --arch=${ffmpegarc} --enable-static --enable-pic --enable-optimizations --disable-doc --disable-gpl --disable-yasm --disable-postproc --disable-swscale --disable-ffmpeg --disable-ffprobe --disable-ffserver --disable-ffplay --disable-decoders --disable-encoders --disable-muxers --disable-demuxers --disable-parsers --disable-protocols --disable-network --disable-bsfs --disable-devices --disable-filters --enable-encoder=h263 --enable-encoder=h263p --enable-encoder=mpeg4 --enable-encoder=msmpeg4v2 --enable-encoder=msmpeg4v3 --enable-decoder=aac --enable-decoder=h263 --enable-decoder=h264 --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mpeg4 --enable-decoder=mpegvideo --enable-decoder=msmpeg4v1 --enable-decoder=msmpeg4v2 --enable-decoder=msmpeg4v3 --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmv3 --enable-decoder=vc1
 +cd ../.. 
 +
 +cd ..
 +
 +echo ""
 +echo "##### QEMU configure for emulator"
 +exec ./configure \
 + --disable-werror \
 + --audio-drv-list=alsa \
 + --audio-card-list=ac97 \
-  --enable-ldst-optimization \
 + --enable-maru \
 + --disable-vnc \
 + --disable-pie $1
++ # --enable-ldst-optimization \
 +;;
 +MINGW*)
 +cd distrib/libav
 +echo ""
 +echo "##### FFMPEG configure for emulator"
 +./configure \
 + --prefix=./$bindir --arch=x86 --enable-static --enable-w32threads --enable-optimizations --enable-memalign-hack --disable-doc --disable-gpl --disable-yasm --disable-postproc --disable-swscale --disable-ffmpeg --disable-ffprobe --disable-ffserver --disable-ffplay --disable-decoders --disable-encoders --disable-muxers --disable-demuxers --disable-parsers --disable-protocols --disable-network --disable-bsfs --disable-devices --disable-filters --enable-encoder=h263 --enable-encoder=h263p --enable-encoder=mpeg4 --enable-encoder=msmpeg4v2 --enable-encoder=msmpeg4v3 --enable-decoder=aac --enable-decoder=h263 --enable-decoder=h264 --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mpeg4 --enable-decoder=mpegvideo --enable-decoder=msmpeg4v1 --enable-decoder=msmpeg4v2 --enable-decoder=msmpeg4v3 --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmv3 --enable-decoder=vc1
 +cd ../..
 +
 +cd ..
 +echo ""
 +echo "##### QEMU configure for emulator"
 +exec ./configure \
 + --audio-drv-list=winwave \
 + --audio-card-list=ac97 \
 + --enable-hax \
 + --enable-maru \
 + --disable-vnc $1
++ # --enable-ldst-optimization \
 +;;
 +Darwin*)
 +cd distrib/libav
 +echo ""
 +echo "##### FFMPEG configure for emulator"
 +./configure \
 +--prefix=./$bindir --arch=x86 --enable-static --enable-pic --enable-optimizations --disable-doc --disable-gpl --disable-yasm --disable-postproc --disable-swscale --disable-ffmpeg --disable-ffprobe --disable-ffserver --disable-ffplay --disable-decoders --disable-encoders --disable-muxers --disable-demuxers --disable-parsers --disable-protocols --disable-network --disable-bsfs --disable-devices --disable-filters --enable-encoder=h263 --enable-encoder=h263p --enable-encoder=mpeg4 --enable-encoder=msmpeg4v2 --enable-encoder=msmpeg4v3 --enable-decoder=aac --enable-decoder=h263 --enable-decoder=h264 --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mpeg4 --enable-decoder=mpegvideo --enable-decoder=msmpeg4v1 --enable-decoder=msmpeg4v2 --enable-decoder=msmpeg4v3 --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmv3 --enable-decoder=vc1 --cc=cc
 +cd ../..
 +
 +cd ..
 +echo ""
 +echo "##### QEMU configure for emulator"
 +./configure \
 + --audio-drv-list=coreaudio \
 + --enable-mixemu \
 + --audio-card-list=ac97 \
 + --enable-maru \
 + --enable-hax \
 + --disable-vnc \
 + --disable-sdl $1
 +;;
 +esac
index 6c69d10,0000000..e66e9c8
mode 100755,000000..100755
--- /dev/null
@@@ -1,145 -1,0 +1,139 @@@
- obj-i386-y += maru_board.o
- obj-i386-y += maru_overlay.o
- obj-i386-y += maru_pm.o
- obj-i386-y += maru_vga.o
- obj-arm-y += maru_arm_soc.o
- obj-arm-y += maru_arm_board.o
- obj-arm-y += maru_arm_vpci.o
- obj-arm-y += maru_arm_pmu.o
 +# Makefile.tizen
 +# for TIZEN-maru board
 +
 +
 +$(call set-vpath, $(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/tizen/src:$(SRC_PATH)/tizen/src/hw:$(SRC_PATH)/tizen/src/skin)
 +
 +QEMU_CFLAGS += -I$(SRC_PATH)/hw -I$(SRC_PATH)/tizen/src
 +QEMU_CFLAGS += -I$(SRC_PATH)/tizen/distrib/libav/$(ARCH)/include
 +QEMU_CFLAGS += -L$(SRC_PATH)/tizen/distrib/libav/$(ARCH)/lib
 +QEMU_CFLAGS += $(SDL_CFLAGS)
 +QEMU_CFLAGS += $(GLIB_CFLAGS)
 +ifdef CONFIG_DARWIN
 +QEMU_CFLAGS += -framework Foundation -framework SystemConfiguration
 +endif
 +ifndef CONFIG_DEBUG_EXEC
 +CFLAGS += -g -O2
 +else
 +CFLAGS += -g -O0
 +endif
 +
 +ifdef CONFIG_WIN32
 +LIBS += -lavformat -lavcodec -lavutil -lm -lcurl -lopengl32 -lglu32 -lgdi32
 +endif
 +ifdef CONFIG_LINUX
 +LIBS += -lavformat -lavcodec -lavutil -lm -lcurl -lGL -lXcomposite -lXext
 +endif
 +ifdef CONFIG_DARWIN
 +# FIXME: disabled codec on Mac now
 +# LIBS += -lavformat -lavcodec -lavutil -lm
 +endif
 +
 +ifdef CONFIG_DEBUG_EXEC
 +GL_CFLAGS := -Wall -g -O0 -fno-strict-aliasing
 +else
 +GL_CFLAGS := -Wall -g -O2 -fno-strict-aliasing
 +endif
 +
 +ifndef CONFIG_DARWIN
 +###########################################################
 +## Build openGL
 +# i386
 +ifdef CONFIG_GL
 +
 +GL_CUR_PATH = $(SRC_PATH)/tizen/src/hw
 +
 +GL_CFLAGS += -I$(GL_CUR_PATH) -I$(SRC_PATH)/fpu
 +GL_CFLAGS += -I$(SRC_PATH)/i386-softmmu $(QEMU_CFLAGS) $(CFLAGS)
 +
 +parse_gl_h: parse_gl_h.c
 +      $(CC) -g -o $@ $<
 +server_stub.c: parse_gl_h
 +      ./parse_gl_h 2>/dev/null
 +gl_func.h: parse_gl_h
 +      ./parse_gl_h 2>/dev/null
 +opengl_func.h: gl_func.h
 +helper_opengl.o: helper_opengl.c opengl_func.h server_stub.c opengl_process.h
 +      $(CC) $(GL_CFLAGS) $(DEFINES) $(GL_LDFLAGS) -c -o $@ $<
 +gl_beginend.h: $(GL_CUR_PATH)/beginend_funcs.sh
 +      $< > $@
 +mesa_mipmap.o : mesa_mipmap.c
 +      $(CC) $(GL_CFLAGS) $(DEFINES) $(GL_LDFLAGS) -c -o $@ $<
 +opengl_exec.o : opengl_exec.c server_stub.c opengl_func.h gl_beginend.h opengl_process.h mesa_mipmap.o
 +      $(CC) $(GL_CFLAGS) $(DEFINES) $(GL_LDFLAGS) -c -o $@ $<
 +
 +endif #CONFIG_GL
 +
 +ifdef CONFIG_OPENGLES
 +
 +parse_gl_h: parse_gl_h.c
 +      $(CC) -g -o $@ $<
 +
 +gl_mangled.h: parse_gl_h
 +      ./parse_gl_h mangle 2>/dev/null
 +
 +gl_mangled.c: gl_mangled.h
 +      ./parse_gl_h mangle 2>/dev/null
 +
 +gloffscreen_glx.o gloffscreen_wgl.o gloffscreen_xcomposite.o: gl_mangled.h
 +maru_sdl.o gloffscreen_test.o gloffscreen_common.o: gl_mangled.h
 +
 +obj-y += gl_mangled.o
 +
 +endif #CONFIG_OPENGLES
 +###########################################################
 +endif #!CONFIG_DARWIN
 +
 +# maru loader
 +obj-y += emulator.o emul_state.o option.o maru_err_table.o
 +
 +# maru display
 +obj-y += maru_display.o maru_shm.o
 +ifndef CONFIG_DARWIN
 +obj-y += maru_sdl.o SDL_rotozoom.o maru_finger.o
 +endif
 +
 +# sdb
 +obj-y += sdb.o
 +
 +# mloop event
 +obj-y += mloop_event.o
 +
 +# debug channel
 +obj-y += debug_ch.o
 +
 +# maru hardware
++include $(SRC_PATH)/tizen/src/Makefile.tizen.$(TARGET_BASE_ARCH)
++
 +obj-y += maru_brightness.o
 +obj-y += maru_usb_touchscreen.o maru_virtio_touchscreen.o
 +ifndef CONFIG_DARWIN
 +obj-y += maru_codec.o
 +obj-$(CONFIG_PCI) += maru_camera_common_pci.o
 +obj-$(CONFIG_LINUX) += maru_camera_linux_pci.o
 +obj-$(CONFIG_WIN32) += maru_camera_win32_pci.o
 +endif
 +
 +ifdef CONFIG_LINUX # libs for maru camera on linux host
 +LIBS += -lv4l2 -lv4lconvert
 +endif
 +
 +ifdef CONFIG_WIN32 # libs for maru camera on windows host
 +LIBS += -lole32 -loleaut32 -luuid -lstrmiids
 +endif
 +
 +# maru skin
 +obj-y += maruskin_client.o maruskin_server.o maruskin_operation.o maruskin_keymap.o
 +
 +# guest server
 +obj-y += guest_server.o
 +
 +ifndef CONFIG_DARWIN
 +###########################################################
 +## opengl library for i386
 +obj-$(CONFIG_GL) += virtio-gl.o 
 +obj-$(CONFIG_GL) += helper_opengl.o opengl_exec.o mesa_mipmap.o gloffscreen_wgl.o
 +obj-$(CONFIG_NO_GL) += virtio-gl-stub.o 
 +obj-y += gloffscreen_test.o gloffscreen_xcomposite.o gloffscreen_common.o
 +###########################################################
 +endif
index 0000000,0000000..c5c0172
new file mode 100755 (executable)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,7 @@@
++# Makefile.tizen
++# for TIZEN-maru board
++
++obj-y += maru_arm_soc.o
++obj-y += maru_arm_board.o
++obj-y += maru_arm_vpci.o
++obj-y += maru_arm_pmu.o
index 0000000,0000000..c599b0f
new file mode 100755 (executable)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,7 @@@
++# Makefile.tizen
++# for TIZEN-maru-x86 board
++
++obj-y += maru_board.o
++obj-y += maru_overlay.o
++obj-y += maru_pm.o
++obj-y += maru_vga.o
index 8651fc3,0000000..6fa1a9d
mode 100644,000000..100644
--- /dev/null
@@@ -1,38 -1,0 +1,38 @@@
- void maru_arm_write_secondary(CPUARMState *env,
 +/*
 + *  Samsung Maru ARM SoC emulation
 + *
 + *  Copyright (c) 2012 Samsung Electronics Co., Ltd.
 + *    Evgeny Voevodin <e.voevodin@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, see <http://www.gnu.org/licenses/>.
 + *
 + */
 +
 +#ifndef MARU_ARM_H_
 +#define MARU_ARM_H_
 +
 +#include "qemu-common.h"
 +#include "memory.h"
 +#include "exynos4210.h"
 +
++void maru_arm_write_secondary(ARMCPU *cpu,
 +        const struct arm_boot_info *info);
 +
 +Exynos4210State *maru_arm_soc_init(MemoryRegion *system_mem,
 +        unsigned long ram_size);
 +
 +int codec_init(PCIBus *bus);
 +int maru_camera_pci_init(PCIBus *bus);
 +
 +#endif /* MARU_ARM_H_ */
index c4c656f,0000000..32953f6
mode 100644,000000..100644
--- /dev/null
@@@ -1,138 -1,0 +1,138 @@@
-     arm_load_kernel(first_cpu, &maru_arm_board_binfo);
 +/*
 + * TIZEN ARM base board
 + *
 + * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd.
 + *
 + * Based on maru_board.c, exynos4210.c and exynos4210_boards.c
 + *
 + * Author:
 + *  Evgeny Voevodin <e.voevodin@samsung.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License; 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, see <http://www.gnu.org/licenses/>.
 + */
 +
 +#include <glib.h>
 +
 +#include "boards.h"
 +#include "arm-misc.h"
 +#include "sysbus.h"
 +#include "pci.h"
 +#include "maru_arm.h"
 +#include "i2c.h"
 +#include "exec-memory.h"
 +#include "../tizen/src/hw/maru_brightness.h"
 +#include "arch_init.h"
 +
 +#undef DEBUG
 +//#define DEBUG
 +#ifdef DEBUG
 +    #undef PRINT_DEBUG
 +    #define  PRINT_DEBUG(fmt, args...) \
 +        do { \
 +            fprintf(stderr, "  [%s:%d]   "fmt, __func__, __LINE__, ##args); \
 +        } while (0)
 +#else
 +    #define  PRINT_DEBUG(fmt, args...)  do {} while (0)
 +#endif
 +
 +#ifndef DEBUG_LOG_PATH
 +#define DEBUG_LOG_PATH                     "./debug.log"
 +#endif
 +
 +#define EXYNOS4210_WM8994_ADDR             0x1A
 +#define MARU_ARM_BOARD_ID                  0xF3B
 +#define MARU_ARM_BOARD_SMP_BOOTREG_ADDR    EXYNOS4210_SECOND_CPU_BOOTREG
 +#define MARU_ARM_BOARD_RAMSIZE_MIN         0x20000000
 +#define MARU_ARM_BOARD_RAMSIZE_DEFAULT     0x40000000
 +
 +static struct arm_boot_info maru_arm_board_binfo = {
 +    .loader_start     = EXYNOS4210_BASE_BOOT_ADDR,
 +    .smp_loader_start = EXYNOS4210_SMP_BOOT_ADDR,
 +    .nb_cpus          = EXYNOS4210_NCPUS,
 +    .write_secondary_boot = maru_arm_write_secondary,
 +};
 +
 +static void maru_arm_machine_init(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)
 +{
 +    Exynos4210State *s;
 +    DeviceState *dev, *i2c_dev;
 +    PCIBus *pci_bus;
 +
 +    if (ram_size < MARU_ARM_BOARD_RAMSIZE_MIN) {
 +      ram_size = MARU_ARM_BOARD_RAMSIZE_DEFAULT;
 +      fprintf(stderr, "RAM size is too small, setting to default value 0x%lx",
 +                      (long unsigned int)ram_size);
 +    }
 +
 +    maru_arm_board_binfo.ram_size = ram_size;
 +    maru_arm_board_binfo.board_id = MARU_ARM_BOARD_ID;
 +    maru_arm_board_binfo.smp_bootreg_addr = MARU_ARM_BOARD_SMP_BOOTREG_ADDR;
 +    maru_arm_board_binfo.kernel_filename = kernel_filename;
 +    maru_arm_board_binfo.initrd_filename = initrd_filename;
 +    maru_arm_board_binfo.kernel_cmdline = kernel_cmdline;
 +    maru_arm_board_binfo.gic_cpu_if_addr =
 +                        EXYNOS4210_SMP_PRIVATE_BASE_ADDR + 0x100;
 +
 +    PRINT_DEBUG("\n ram_size: %luMiB [0x%08lx]\n"
 +            " kernel_filename: %s\n"
 +            " kernel_cmdline: %s\n"
 +            " initrd_filename: %s\n",
 +            (long unsigned int)ram_size / 1048576,
 +            (long unsigned int)ram_size,
 +            kernel_filename,
 +            kernel_cmdline,
 +            initrd_filename);
 +    s = maru_arm_soc_init(get_system_memory(), ram_size);
 +
 +    /* PCI config */
 +    dev = qdev_create(NULL, "tizen_vpci");
 +    s->vpci_bus = sysbus_from_qdev(dev);
 +    qdev_init_nofail(dev);
 +    sysbus_mmio_map(s->vpci_bus, 0, EXYNOS4210_VPCI_CFG_BASE_ADDR);
 +    sysbus_connect_irq(s->vpci_bus, 0, s->irq_table[exynos4210_get_irq(38, 0)]);
 +    sysbus_connect_irq(s->vpci_bus, 1, s->irq_table[exynos4210_get_irq(38, 1)]);
 +    sysbus_connect_irq(s->vpci_bus, 2, s->irq_table[exynos4210_get_irq(38, 2)]);
 +    sysbus_connect_irq(s->vpci_bus, 3, s->irq_table[exynos4210_get_irq(38, 3)]);
 +    pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
 +
 +    pci_create_simple(pci_bus, -1, "pci-ohci");
 +    maru_camera_pci_init(pci_bus);
 +    codec_init(pci_bus);
 +    pci_maru_brightness_init(pci_bus);
 +#ifdef CONFIG_YAGL
 +    pci_create_simple(pci_bus, -1, "yagl");
 +#endif
 +
 +    audio_init(NULL, pci_bus);
 +
++    arm_load_kernel(arm_env_get_cpu(first_cpu), &maru_arm_board_binfo);
 +}
 +
 +static QEMUMachine maru_arm_machine = {
 +    .name = "maru-arm-machine",
 +    .desc = "maru board(ARM)",
 +    .init = maru_arm_machine_init,
 +    .max_cpus = 255,
 +};
 +
 +static void maru_machine_init(void)
 +{
 +    qemu_register_machine(&maru_arm_machine);
 +}
 +
 +machine_init(maru_machine_init);
index b229365,0000000..61976df
mode 100644,000000..100644
--- /dev/null
@@@ -1,444 -1,0 +1,440 @@@
- void maru_arm_write_secondary(CPUARMState *env,
 +/*
 + *  Samsung Maru ARM SoC emulation
 + *
 + *  Based on exynos4210.c
 + *
 + *  Copyright (c) 2011 Samsung Electronics Co., Ltd.
 + *    Maksim Kozlov <m.kozlov@samsung.com>
 + *    Evgeny Voevodin <e.voevodin@samsung.com>
 + *    Igor Mitsyanko  <i.mitsyanko@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, see <http://www.gnu.org/licenses/>.
 + *
 + */
 +
 +#include "boards.h"
 +#include "arm-misc.h"
 +#include "sysbus.h"
 +#include "pci.h"
 +#include "maru_arm.h"
 +#include "i2c.h"
 +#include "exec-memory.h"
 +#ifdef CONFIG_BUILD_GLES
 +#include "gles2.h"
 +#endif
 +
 +#include "loader.h"
 +#include "virtio-transport.h"
 +#include "exynos4210_i2s.h"
 +
 +#define EXYNOS4210_CHIPID_ADDR         0x10000000
 +
 +/* CMUs */
 +#define EXYNOS4210_CMU_LEFTBUS_BASE_ADDR     0x10034000
 +#define EXYNOS4210_CMU_RIGHTBUS_BASE_ADDR    0x10038000
 +#define EXYNOS4210_CMU_TOP_BASE_ADDR         0x1003C000
 +#define EXYNOS4210_CMU_DMC_BASE_ADDR         0x10040000
 +#define EXYNOS4210_CMU_CPU_BASE_ADDR         0x10044000
 +
 +/* PWM */
 +#define EXYNOS4210_PWM_BASE_ADDR       0x139D0000
 +
 +/* RTC */
 +#define EXYNOS4210_RTC_BASE_ADDR       0x10070000
 +
 +/* MCT */
 +#define EXYNOS4210_MCT_BASE_ADDR       0x10050000
 +
 +/* DMA */
 +#define EXYNOS4210_DMAMEM_BASE_ADDR    0x12840000
 +#define EXYNOS4210_DMAPERI0_BASE_ADDR  0x12680000
 +#define EXYNOS4210_DMAPERI1_BASE_ADDR  0x12690000
 +
 +/* I2C */
 +#define EXYNOS4210_I2C_SHIFT           0x00010000
 +#define EXYNOS4210_I2C_BASE_ADDR       0x13860000
 +/* Interrupt Group of External Interrupt Combiner for I2C */
 +#define EXYNOS4210_I2C_INTG            27
 +#define EXYNOS4210_HDMI_INTG           16
 +
 +/* There are two set of touch screen interfaces, which share one ADC */
 +#define EXYNOS4210_TS0_BASE_ADDR       0x13910000
 +#define EXYNOS4210_TS1_BASE_ADDR       0x13911000
 +#define EXYNOS4210_TS_INTG             19
 +
 +/* UART's definitions */
 +#define EXYNOS4210_UART0_BASE_ADDR     0x13800000
 +#define EXYNOS4210_UART1_BASE_ADDR     0x13810000
 +#define EXYNOS4210_UART2_BASE_ADDR     0x13820000
 +#define EXYNOS4210_UART3_BASE_ADDR     0x13830000
 +#define EXYNOS4210_UART0_FIFO_SIZE     256
 +#define EXYNOS4210_UART1_FIFO_SIZE     64
 +#define EXYNOS4210_UART2_FIFO_SIZE     16
 +#define EXYNOS4210_UART3_FIFO_SIZE     16
 +/* Interrupt Group of External Interrupt Combiner for UART */
 +#define EXYNOS4210_UART_INT_GRP        26
 +
 +/* External GIC */
 +#define EXYNOS4210_EXT_GIC_CPU_BASE_ADDR    0x10480000
 +#define EXYNOS4210_EXT_GIC_DIST_BASE_ADDR   0x10490000
 +
 +/* Combiner */
 +#define EXYNOS4210_EXT_COMBINER_BASE_ADDR   0x10440000
 +#define EXYNOS4210_INT_COMBINER_BASE_ADDR   0x10448000
 +
 +/* SD/MMC host controllers SFR base addresses */
 +#define EXYNOS4210_SDHC0_BASE_ADDR          0x12510000
 +#define EXYNOS4210_SDHC1_BASE_ADDR          0x12520000
 +#define EXYNOS4210_SDHC2_BASE_ADDR          0x12530000
 +#define EXYNOS4210_SDHC3_BASE_ADDR          0x12540000
 +
 +/* PMU SFR base address */
 +#define EXYNOS4210_PMU_BASE_ADDR            0x10020000
 +
 +/* Display controllers (FIMD) */
 +#define EXYNOS4210_FIMD0_BASE_ADDR          0x11C00000
 +#define EXYNOS4210_FIMD1_BASE_ADDR          0x12000000
 +
 +/* MALI400 (G3D) */
 +#define EXYNOS4210_G3D_BASE_ADDR            0x13000000
 +#define EXYNOS4210_G3D_PIXEL_PROC_0_IRQ     0
 +#define EXYNOS4210_G3D_PIXEL_PROC_1_IRQ     1
 +#define EXYNOS4210_G3D_PIXEL_PROC_2_IRQ     2
 +#define EXYNOS4210_G3D_PIXEL_PROC_3_IRQ     3
 +#define EXYNOS4210_G3D_GEOM_PROC_IRQ        4
 +#define EXYNOS4210_G3D_PMU_IRQ              5
 +#define EXYNOS4210_G3D_PPMMU0_IRQ           0
 +#define EXYNOS4210_G3D_PPMMU1_IRQ           1
 +#define EXYNOS4210_G3D_PPMMU2_IRQ           2
 +#define EXYNOS4210_G3D_PPMMU3_IRQ           3
 +#define EXYNOS4210_G3D_GPMMU_IRQ            4
 +
 +/* PPMU */
 +#define EXYNOS4210_PPMU_CPU_BASE_ADDR       0x106C0000
 +/* DMC */
 +#define EXYNOS4210_DMC0_BASE_ADDR           0x10400000
 +#define EXYNOS4210_DMC1_BASE_ADDR           0x10410000
 +
 +/* I2S */
 +#define EXYNOS4210_I2S0_BASE_ADDR           0x03830000
 +
 +/* VirtIO MMIO */
 +#define EXYNOS4210_VIRTIO_MMIO0_BASE_ADDR   0x10AD0000
 +#define EXYNOS4210_VIRTIO_MMIO1_BASE_ADDR   0x10AC0000
 +
 +/* pl050 ps/2 interface */
 +#define EXYNOS4210_PL050_BASE_ADDR          0x12E30000
 +
 +static uint8_t chipid_and_omr[TARGET_PAGE_SIZE] = { 0x11, 0x02, 0x21, 0x43,
 +                                    0x09, 0x00, 0x00, 0x00 };
 +
-     qemu_irq cpu_irq[4];
-     int n;
++void maru_arm_write_secondary(ARMCPU *cpu,
 +        const struct arm_boot_info *info)
 +{
 +    int n;
 +    uint32_t smpboot[] = {
 +        0xe59f3024, /* ldr r3, External gic_cpu_if */
 +        0xe59f2024, /* ldr r2, Internal gic_cpu_if */
 +        0xe59f0024, /* ldr r0, startaddr */
 +        0xe3a01001, /* mov r1, #1 */
 +        0xe5821000, /* str r1, [r2] */
 +        0xe5831000, /* str r1, [r3] */
 +        0xe320f003, /* wfi */
 +        0xe5901000, /* ldr     r1, [r0] */
 +        0xe1110001, /* tst     r1, r1 */
 +        0x0afffffb, /* beq     <wfi> */
 +        0xe12fff11, /* bx      r1 */
 +        EXYNOS4210_EXT_GIC_CPU_BASE_ADDR,
 +        0,          /* gic_cpu_if: base address of Internal GIC CPU interface */
 +        0           /* bootreg: Boot register address is held here */
 +    };
 +    smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
 +    smpboot[ARRAY_SIZE(smpboot) - 2] = info->gic_cpu_if_addr;
 +    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
 +        smpboot[n] = tswap32(smpboot[n]);
 +    }
 +    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
 +                       info->smp_loader_start);
 +}
 +
 +Exynos4210State *maru_arm_soc_init(MemoryRegion *system_mem,
 +        unsigned long ram_size)
 +{
-     qemu_irq gate_irq[EXYNOS4210_IRQ_GATE_NINPUTS];
++    qemu_irq cpu_irq[EXYNOS4210_NCPUS];
++    int i, n;
 +    Exynos4210State *s = g_new(Exynos4210State, 1);
 +    qemu_irq *irqp;
-         s->env[n] = cpu_init("cortex-a9");
-         if (!s->env[n]) {
++    qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
 +    unsigned long mem_size;
 +    DeviceState *dev;
 +    SysBusDevice *busdev;
 +
 +    for (n = 0; n < EXYNOS4210_NCPUS; n++) {
-         irqp = arm_pic_init_cpu(s->env[n]);
++        s->cpu[n] = cpu_arm_init("cortex-a9");
++        if (!s->cpu[n]) {
 +            fprintf(stderr, "Unable to find CPU %d definition\n", n);
 +            exit(1);
 +        }
++
 +        /* Create PIC controller for each processor instance */
-     dev = qdev_create(NULL, "exynos4210.irq_gate");
-     qdev_prop_set_uint32(dev, "n_out", EXYNOS4210_NCPUS);
-     qdev_prop_set_uint32(dev, "n_in", EXYNOS4210_IRQ_GATE_NINPUTS);
-     qdev_init_nofail(dev);
-     /* Get IRQ Gate input in gate_irq */
-     for (n = 0; n < EXYNOS4210_IRQ_GATE_NINPUTS; n++) {
-         gate_irq[n] = qdev_get_gpio_in(dev, n);
-     }
-     busdev = sysbus_from_qdev(dev);
-     /* Connect IRQ Gate output to cpu_irq */
-     for (n = 0; n < EXYNOS4210_NCPUS; n++) {
-         sysbus_connect_irq(busdev, n, cpu_irq[n]);
++        irqp = arm_pic_init_cpu(s->cpu[n]);
 +
 +        /*
 +         * Get GICs gpio_in cpu_irq to connect a combiner to them later.
 +         * Use only IRQ for a while.
 +         */
 +        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
 +    }
 +
 +    /*** IRQs ***/
 +
 +    s->irq_table = exynos4210_init_irq(&s->irqs);
 +
 +    /* IRQ Gate */
-         sysbus_connect_irq(busdev, n, gate_irq[n * 4]);
++    for (i = 0; i < EXYNOS4210_NCPUS; i++) {
++        dev = qdev_create(NULL, "exynos4210.irq_gate");
++        qdev_prop_set_uint32(dev, "n_in", EXYNOS4210_IRQ_GATE_NINPUTS);
++        qdev_init_nofail(dev);
++        /* Get IRQ Gate input in gate_irq */
++        for (n = 0; n < EXYNOS4210_IRQ_GATE_NINPUTS; n++) {
++            gate_irq[i][n] = qdev_get_gpio_in(dev, n);
++        }
++        busdev = sysbus_from_qdev(dev);
++
++        /* Connect IRQ Gate output to cpu_irq */
++        sysbus_connect_irq(busdev, 0, cpu_irq[i]);
 +    }
 +
 +    /* Private memory region and Internal GIC */
 +    dev = qdev_create(NULL, "a9mpcore_priv");
 +    qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
 +    qdev_init_nofail(dev);
 +    busdev = sysbus_from_qdev(dev);
 +    sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
 +    for (n = 0; n < EXYNOS4210_NCPUS; n++) {
-         sysbus_connect_irq(busdev, n, gate_irq[n * 4 + 1]);
++        sysbus_connect_irq(busdev, n, gate_irq[n][0]);
 +    }
 +    for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
 +        s->irqs.int_gic_irq[n] = qdev_get_gpio_in(dev, n);
 +    }
 +
 +    /* Cache controller */
 +    sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
 +
 +    /* External GIC */
 +    dev = qdev_create(NULL, "exynos4210.gic");
 +    qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
 +    qdev_init_nofail(dev);
 +    busdev = sysbus_from_qdev(dev);
 +    /* Map CPU interface */
 +    sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_GIC_CPU_BASE_ADDR);
 +    /* Map Distributer interface */
 +    sysbus_mmio_map(busdev, 1, EXYNOS4210_EXT_GIC_DIST_BASE_ADDR);
 +    for (n = 0; n < EXYNOS4210_NCPUS; n++) {
-     vmstate_register_ram_global(&s->chipid_mem);
++        sysbus_connect_irq(busdev, n, gate_irq[n][1]);
 +    }
 +    for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
 +        s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
 +    }
 +
 +    /* Internal Interrupt Combiner */
 +    dev = qdev_create(NULL, "exynos4210.combiner");
 +    qdev_init_nofail(dev);
 +    busdev = sysbus_from_qdev(dev);
 +    for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
 +        sysbus_connect_irq(busdev, n, s->irqs.int_gic_irq[n]);
 +    }
 +    exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
 +    sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
 +
 +    /* External Interrupt Combiner */
 +    dev = qdev_create(NULL, "exynos4210.combiner");
 +    qdev_prop_set_uint32(dev, "external", 1);
 +    qdev_init_nofail(dev);
 +    busdev = sysbus_from_qdev(dev);
 +    for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
 +        sysbus_connect_irq(busdev, n, s->irqs.ext_gic_irq[n]);
 +    }
 +    exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
 +    sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
 +
 +    /* Initialize board IRQs. */
 +    exynos4210_init_board_irqs(&s->irqs);
 +
 +    /*** Memory ***/
 +
 +    /* Chip-ID and OMR */
 +    memory_region_init_ram_ptr(&s->chipid_mem, "exynos4210.chipid",
 +            sizeof(chipid_and_omr), chipid_and_omr);
 +    memory_region_set_readonly(&s->chipid_mem, true);
-     vmstate_register_ram_global(&s->irom_mem);
 +    memory_region_add_subregion(system_mem, EXYNOS4210_CHIPID_ADDR,
 +                                &s->chipid_mem);
 +
 +    /* Internal ROM */
 +    memory_region_init_ram(&s->irom_mem, "exynos4210.irom",
 +                           EXYNOS4210_IROM_SIZE);
 +    memory_region_set_readonly(&s->irom_mem, true);
-     /*** Clock devices ***/
-     /* PMU. Must be initialized before CMU.
-      * The only reason of existence at the moment is that secondary CPU boot
-      * loader uses PMU INFORM5 register as a holding pen.
-      */
 +    memory_region_add_subregion(system_mem, EXYNOS4210_IROM_BASE_ADDR,
 +                                &s->irom_mem);
 +    /* mirror of iROM */
 +    memory_region_init_alias(&s->irom_alias_mem, "exynos4210.irom_alias",
 +                             &s->irom_mem,
 +                             0,
 +                             EXYNOS4210_IROM_SIZE);
 +    memory_region_set_readonly(&s->irom_alias_mem, true);
 +    memory_region_add_subregion(system_mem, EXYNOS4210_IROM_MIRROR_BASE_ADDR,
 +                                &s->irom_alias_mem);
 +
 +    /* Internal RAM */
 +    memory_region_init_ram(&s->iram_mem, "exynos4210.iram",
 +                           EXYNOS4210_IRAM_SIZE);
 +    vmstate_register_ram_global(&s->iram_mem);
 +    memory_region_add_subregion(system_mem, EXYNOS4210_IRAM_BASE_ADDR,
 +                                &s->iram_mem);
 +
 +    /* DRAM */
 +    mem_size = ram_size;
 +    if (mem_size > EXYNOS4210_DRAM_MAX_SIZE) {
 +        memory_region_init_ram(&s->dram1_mem, "exynos4210.dram1",
 +                mem_size - EXYNOS4210_DRAM_MAX_SIZE);
 +        vmstate_register_ram_global(&s->dram1_mem);
 +        memory_region_add_subregion(system_mem, EXYNOS4210_DRAM1_BASE_ADDR,
 +                &s->dram1_mem);
 +        mem_size = EXYNOS4210_DRAM_MAX_SIZE;
 +    }
 +    memory_region_init_ram(&s->dram0_mem, "exynos4210.dram0", mem_size);
 +    vmstate_register_ram_global(&s->dram0_mem);
 +    memory_region_add_subregion(system_mem, EXYNOS4210_DRAM0_BASE_ADDR,
 +            &s->dram0_mem);
 +
 +    /* Audio Subsystem Internal Memory */
 +    memory_region_init_ram(&s->audss_intmem, "exynos4210.audss",
 +                           EXYNOS4210_AUDSS_INTMEM_SIZE);
 +    vmstate_register_ram_global(&s->audss_intmem);
 +    memory_region_add_subregion(system_mem, EXYNOS4210_AUDSS_INTMEM_BASE_ADDR,
 +                                &s->audss_intmem);
 +
-             s->irq_table[exynos4210_get_irq(22, 0)],
-             s->irq_table[exynos4210_get_irq(22, 1)],
-             s->irq_table[exynos4210_get_irq(22, 2)],
-             s->irq_table[exynos4210_get_irq(22, 3)],
-             s->irq_table[exynos4210_get_irq(22, 4)],
-             NULL);
++   /* PMU.
++    * The only reason of existence at the moment is that secondary CPU boot
++    * loader uses PMU INFORM5 register as a holding pen.
++    */
 +    sysbus_create_simple("maru_arm.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL);
 +
 +    /* CMUs */
 +    exynos4210_cmu_create(EXYNOS4210_CMU_LEFTBUS_BASE_ADDR,
 +                                                       EXYNOS4210_CMU_LEFTBUS);
 +    exynos4210_cmu_create(EXYNOS4210_CMU_RIGHTBUS_BASE_ADDR,
 +                                                      EXYNOS4210_CMU_RIGHTBUS);
 +    exynos4210_cmu_create(EXYNOS4210_CMU_TOP_BASE_ADDR, EXYNOS4210_CMU_TOP);
 +    exynos4210_cmu_create(EXYNOS4210_CMU_DMC_BASE_ADDR, EXYNOS4210_CMU_DMC);
 +    exynos4210_cmu_create(EXYNOS4210_CMU_CPU_BASE_ADDR, EXYNOS4210_CMU_CPU);
 +
 +    /* PWM */
 +    sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR,
-             s->irq_table[exynos4210_get_irq(23, 0)],
-             s->irq_table[exynos4210_get_irq(23, 1)],
-             NULL);
++                          s->irq_table[exynos4210_get_irq(22, 0)],
++                          s->irq_table[exynos4210_get_irq(22, 1)],
++                          s->irq_table[exynos4210_get_irq(22, 2)],
++                          s->irq_table[exynos4210_get_irq(22, 3)],
++                          s->irq_table[exynos4210_get_irq(22, 4)],
++                          NULL);
 +    /* RTC */
 +    sysbus_create_varargs("exynos4210.rtc", EXYNOS4210_RTC_BASE_ADDR,
-                     s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 0)]);
++                          s->irq_table[exynos4210_get_irq(23, 0)],
++                          s->irq_table[exynos4210_get_irq(23, 1)],
++                          NULL);
 +
 +    /* Multi Core Timer */
 +    dev = qdev_create(NULL, "exynos4210.mct");
 +    qdev_init_nofail(dev);
 +    busdev = sysbus_from_qdev(dev);
 +    for (n = 0; n < 4; n++) {
 +        /* Connect global timer interrupts to Combiner gpio_in */
 +        sysbus_connect_irq(busdev, n,
 +                s->irq_table[exynos4210_get_irq(1, 4 + n)]);
 +    }
 +    /* Connect local timer interrupts to Combiner gpio_in */
 +    sysbus_connect_irq(busdev, 4,
 +            s->irq_table[exynos4210_get_irq(51, 0)]);
 +    sysbus_connect_irq(busdev, 5,
 +            s->irq_table[exynos4210_get_irq(35, 3)]);
 +    sysbus_mmio_map(busdev, 0, EXYNOS4210_MCT_BASE_ADDR);
 +
 +    /*** I2C ***/
 +    for (n = 0; n < EXYNOS4210_I2C_NUMBER; n++) {
 +        uint32_t addr = EXYNOS4210_I2C_BASE_ADDR + EXYNOS4210_I2C_SHIFT * n;
 +        qemu_irq i2c_irq;
 +
 +        if (n < 8) {
 +            i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_I2C_INTG, n)];
 +        } else {
 +            i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_HDMI_INTG, 1)];
 +        }
 +
 +        dev = qdev_create(NULL, "exynos4210.i2c");
 +        qdev_init_nofail(dev);
 +        busdev = sysbus_from_qdev(dev);
 +        sysbus_connect_irq(busdev, 0, i2c_irq);
 +        sysbus_mmio_map(busdev, 0, addr);
 +        s->i2c_if[n] = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
 +    }
 +
++
 +    /*** UARTs ***/
 +    exynos4210_uart_create(EXYNOS4210_UART0_BASE_ADDR,
 +                           EXYNOS4210_UART0_FIFO_SIZE, 0, NULL,
-                     s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 1)]);
++                  s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 0)]);
 +
 +    exynos4210_uart_create(EXYNOS4210_UART1_BASE_ADDR,
 +                           EXYNOS4210_UART1_FIFO_SIZE, 1, NULL,
-                     s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 2)]);
++                  s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 1)]);
 +
 +    exynos4210_uart_create(EXYNOS4210_UART2_BASE_ADDR,
 +                           EXYNOS4210_UART2_FIFO_SIZE, 2, NULL,
-                     s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 3)]);
++                  s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 2)]);
 +
 +    exynos4210_uart_create(EXYNOS4210_UART3_BASE_ADDR,
 +                           EXYNOS4210_UART3_FIFO_SIZE, 3, NULL,
-     sysbus_create_simple(VIRTIO_MMIO_TRANSPORT,
-             EXYNOS4210_VIRTIO_MMIO0_BASE_ADDR,
-             s->irq_table[exynos4210_get_irq(37, 3)]);
++                  s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 3)]);
 +
 +    /*** Display controller (FIMD) ***/
 +    sysbus_create_varargs("exynos4210.fimd", EXYNOS4210_FIMD0_BASE_ADDR,
 +            s->irq_table[exynos4210_get_irq(11, 0)],
 +            s->irq_table[exynos4210_get_irq(11, 1)],
 +            s->irq_table[exynos4210_get_irq(11, 2)],
 +            NULL);
 +
 +    /*** GPU openGLES passthrough device ***/
 +#ifdef CONFIG_BUILD_GLES
 +    gles2_init(first_cpu);
 +#endif
 +
 +    /* I2S0 */
 +    s->i2s_bus[0] = exynos4210_i2s_bus_new("exynos4210.i2s",
 +                                 EXYNOS4210_I2S0_BASE_ADDR,
 +                                 s->irqs.ext_gic_irq[97]);
 +
-     sysbus_create_simple(VIRTIO_MMIO_TRANSPORT,
-             EXYNOS4210_VIRTIO_MMIO1_BASE_ADDR,
-             s->irq_table[exynos4210_get_irq(37, 2)]);
++    sysbus_create_simple(VIRTIO_MMIO,
++                         EXYNOS4210_VIRTIO_MMIO0_BASE_ADDR,
++                         s->irq_table[exynos4210_get_irq(37, 3)]);
 +
-               s->irq_table[exynos4210_get_irq(28, 2)]);
++    sysbus_create_simple(VIRTIO_MMIO,
++                         EXYNOS4210_VIRTIO_MMIO1_BASE_ADDR,
++                         s->irq_table[exynos4210_get_irq(37, 2)]);
 +
 +    /* PL050 PS/2 if keyboard */
 +    sysbus_create_simple("pl050_keyboard", EXYNOS4210_PL050_BASE_ADDR,
++            s->irq_table[exynos4210_get_irq(28, 2)]);
 +
 +    return s;
 +}
index 6ae533c,0000000..5a55a22
mode 100644,000000..100644
--- /dev/null
@@@ -1,367 -1,0 +1,365 @@@
- i2c_bus *maru_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
-                        qemu_irq sci_irq, qemu_irq smi_irq,
-                        int kvm_enabled);
 +/*
 + * TIZEN base board
 + *
 + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
 + *
 + * Contact:
 + * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
 + * DongKyun Yun <dk77.yun@samsung.com>
 + * DoHyung Hong <don.hong@samsung.com>
 + * SeokYeon Hwang <syeon.hwang@samsung.com>
 + * Hyunjun Son <hj79.son@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> 
 + *
 + * 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.h"
 +#include "pc.h"
 +#include "apic.h"
 +#include "pci.h"
++#include "pci_ids.h"
++#include "usb.h"
 +#include "net.h"
 +#include "boards.h"
 +#include "ide.h"
 +#include "kvm.h"
 +#include "kvm/clock.h"
 +#include "sysemu.h"
 +#include "sysbus.h"
 +#include "arch_init.h"
 +#include "blockdev.h"
 +#include "smbus.h"
 +#include "xen.h"
 +#include "memory.h"
 +#include "exec-memory.h"
 +#ifdef CONFIG_XEN
 +#  include <xen/hvm/hvm_info_table.h>
 +#endif
 +
 +#include "guest_debug.h"
++#include "maru_pm.h"
 +
 +int codec_init(PCIBus *bus);
-     int ret, i;
++
 +
 +#define MAX_IDE_BUS 2
 +
 +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 kvm_piix3_setup_irq_routing(bool pci_enabled)
 +{
 +#ifdef CONFIG_KVM
 +    KVMState *s = kvm_state;
-             kvm_irqchip_add_route(s, i, KVM_IRQCHIP_PIC_MASTER, i);
++    int i;
 +
 +    if (kvm_check_extension(s, KVM_CAP_IRQ_ROUTING)) {
 +        for (i = 0; i < 8; ++i) {
 +            if (i == 2) {
 +                continue;
 +            }
-             kvm_irqchip_add_route(s, i, KVM_IRQCHIP_PIC_SLAVE, i - 8);
++            kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_MASTER, i);
 +        }
 +        for (i = 8; i < 16; ++i) {
-                     kvm_irqchip_add_route(s, i, KVM_IRQCHIP_IOAPIC, 2);
++            kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_SLAVE, i - 8);
 +        }
 +        if (pci_enabled) {
 +            for (i = 0; i < 24; ++i) {
 +                if (i == 0) {
-                     kvm_irqchip_add_route(s, i, KVM_IRQCHIP_IOAPIC, i);
++                    kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, 2);
 +                } else if (i != 2) {
-         ret = kvm_irqchip_commit_routes(s);
-         if (ret < 0) {
-             hw_error("KVM IRQ routing setup failed");
-         }
++                    kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, i);
 +                }
 +            }
 +        }
-         pc_memory_init(system_memory,
 +    }
 +#endif /* CONFIG_KVM */
 +}
 +
 +static void kvm_piix3_gsi_handler(void *opaque, int n, int level)
 +{
 +    GSIState *s = opaque;
 +
 +    if (n < ISA_NUM_IRQS) {
 +        /* Kernel will forward to both PIC and IOAPIC */
 +        qemu_set_irq(s->i8259_irq[n], level);
 +    } else {
 +        qemu_set_irq(s->ioapic_irq[n], level);
 +    }
 +}
 +
 +static void ioapic_init(GSIState *gsi_state)
 +{
 +    DeviceState *dev;
 +    SysBusDevice *d;
 +    unsigned int i;
 +
 +    if (kvm_irqchip_in_kernel()) {
 +        dev = qdev_create(NULL, "kvm-ioapic");
 +    } else {
 +        dev = qdev_create(NULL, "ioapic");
 +    }
 +    /* FIXME: this should be under the piix3.  */
 +    object_property_add_child(object_resolve_path("i440fx", NULL),
 +                              "ioapic", OBJECT(dev), NULL);
 +    qdev_init_nofail(dev);
 +    d = sysbus_from_qdev(dev);
 +    sysbus_mmio_map(d, 0, 0xfec00000);
 +
 +    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
 +        gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i);
 +    }
 +}
 +
 +MemoryRegion *global_ram_memory;
 +
 +MemoryRegion *get_ram_memory(void)
 +{
 +    return global_ram_memory;
 +}
 +
 +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)
 +{
 +    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;
++    void *fw_cfg = NULL;
 +
 +    pc_cpus_init(cpu_model);
 +
 +    if (kvmclock_enabled) {
 +        kvmclock_create();
 +    }
 +
 +    if (ram_size >= 0xe0000000 ) {
 +        above_4g_mem_size = ram_size - 0xe0000000;
 +        below_4g_mem_size = 0xe0000000;
 +    } 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, "pci", INT64_MAX);
 +        rom_memory = pci_memory;
 +    } else {
 +        pci_memory = NULL;
 +        rom_memory = system_memory;
 +    }
 +
 +    /* allocate ram and load rom/bios */
 +    if (!xen_enabled()) {
-                               gsi[9], *smi_irq, kvm_enabled());
++        fw_cfg = pc_memory_init(system_memory,
 +                       kernel_filename, kernel_cmdline, initrd_filename,
 +                       below_4g_mem_size, above_4g_mem_size,
 +                       pci_enabled ? rom_memory : system_memory, &ram_memory);
 +    }
 +
 +    // for ramdump...
 +    global_ram_memory = ram_memory;
 +
 +    gsi_state = g_malloc0(sizeof(*gsi_state));
 +    if (kvm_irqchip_in_kernel()) {
 +        kvm_piix3_setup_irq_routing(pci_enabled);
 +        gsi = qemu_allocate_irqs(kvm_piix3_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,
 +                              0x100000000ULL + above_4g_mem_size,
 +                              (sizeof(target_phys_addr_t) == 4
 +                               ? 0
 +                               : ((uint64_t)1 << 62)),
 +                              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_state);
 +    }
 +
 +
 +    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());
 +
 +    for(i = 0; i < nb_nics; i++) {
 +        NICInfo *nd = &nd_table[i];
 +
 +        if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
 +            pc_init_ne2k_isa(isa_bus, nd);
 +        else
 +            pci_nic_init_nofail(nd, "e1000", NULL);
 +    }
 +
 +    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(&dev->qdev, "ide.0");
 +        }
 +    }
 +
 +// commented out by caramis... for use 'tizen-ac97'...
 +// reopen for qemu 1.0 merging...
 +    audio_init(isa_bus, pci_enabled ? pci_bus : NULL);
 +
 +    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) {
 +        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.  */
 +#if defined(__x86_64__)
 +        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
-                               gsi[9], *smi_irq, kvm_enabled());
++                              gsi[9], *smi_irq, kvm_enabled(), fw_cfg);
 + 
 +#else
 +        smbus = maru_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
++                              gsi[9], *smi_irq, kvm_enabled(), fw_cfg);
 +#endif
 +        smbus_eeprom_init(smbus, 8, NULL, 0);
 +    }
 +
 +    if (pci_enabled) {
 +        pc_pci_device_init(pci_bus);
 +    }
 +
 +#ifndef CONFIG_DARWIN
 +    // maru specialized device init...
 +    if (pci_enabled) {
 +      //tizen_ac97_init(pci_bus);
 +              codec_init(pci_bus);        
 +    }
 +#endif
 +#ifdef CONFIG_YAGL
 +    pci_create_simple(pci_bus, -1, "yagl");
 +#endif
 +}
 +
 +static void maru_x86_board_init(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)
 +{
 +    maru_x86_machine_init(get_system_memory(),
 +             get_system_io(),
 +             ram_size, boot_device,
 +             kernel_filename, kernel_cmdline,
 +             initrd_filename, cpu_model, 1, 1);
 +}
 +
 +static QEMUMachine maru_x86_machine = {
 +    .name = "maru-x86-machine",
 +    .desc = "maru board(x86)",
 +    .init = maru_x86_board_init,
 +    .max_cpus = 255,
 +};
 +
 +static void maru_machine_init(void)
 +{
 +    qemu_register_machine(&maru_x86_machine);
 +}
 +
 +machine_init(maru_machine_init);
index 45fb35e,0000000..5b84bda
mode 100644,000000..100644
--- /dev/null
@@@ -1,655 -1,0 +1,673 @@@
-     DeviceState *qdev, *next;
 +/*
 + * Maru power management emulator
 + * Based on qemu/hw/acpi_piix4.c
 + *
 + * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
 + *
 + * Contact:
 + * Hyunjun Son <hj79.son@samsung.com>
 + * GiWoong Kim <giwoong.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 "maru_pm.h"
 +#include "hw.h"
 +#include "pc.h"
 +#include "apm.h"
 +#include "pm_smbus.h"
 +#include "pci.h"
 +#include "acpi.h"
 +#include "sysemu.h"
 +#include "range.h"
 +#include "ioport.h"
 +#include "debug_ch.h"
 +
++
 +//#define DEBUG
 +
 +#ifdef DEBUG
 +# define PIIX4_DPRINTF(format, ...)     printf(format, ## __VA_ARGS__)
 +#else
 +# define PIIX4_DPRINTF(format, ...)     do { } while (0)
 +#endif
 +
 +/* define debug channel */
 +MULTI_DEBUG_CHANNEL(qemu, maru_pm);
 +
 +#define ACPI_DBG_IO_ADDR  0xb044
 +
 +#define GPE_BASE 0xafe0
 +#define GPE_LEN 4
 +#define PCI_UP_BASE 0xae00
 +#define PCI_DOWN_BASE 0xae04
 +#define PCI_EJ_BASE 0xae08
 +#define PCI_RMV_BASE 0xae0c
 +
 +#define PIIX4_PCI_HOTPLUG_STATUS 2
 +
 +struct pci_status {
 +    uint32_t up; /* deprecated, maintained for migration compatibility */
 +    uint32_t down;
 +};
 +
 +typedef struct PIIX4PMState {
 +    PCIDevice dev;
 +    IORange ioport;
 +    ACPIREGS ar;
 +
 +    APMState apm;
 +
 +    PMSMBus smb;
 +    uint32_t smb_io_base;
 +
 +    qemu_irq irq;
 +    qemu_irq smi_irq;
 +    int kvm_enabled;
 +    Notifier machine_ready;
 +
 +    /* for pci hotplug */
 +    struct pci_status pci0_status;
 +    uint32_t pci0_hotplug_enable;
 +    uint32_t pci0_slot_device_present;
++
++    uint8_t disable_s3;
++    uint8_t disable_s4;
++    uint8_t s4_val;
 +} PIIX4PMState;
 +
 +static int is_suspended;
 +
 +static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s);
 +
 +#define ACPI_ENABLE 0xf1
 +#define ACPI_DISABLE 0xf0
 +
 +static void pm_update_sci(PIIX4PMState *s)
 +{
 +    int sci_level, pmsts;
 +
 +    pmsts = acpi_pm1_evt_get_sts(&s->ar);
 +    sci_level = (((pmsts & s->ar.pm1.evt.en) &
 +                  (ACPI_BITMASK_RT_CLOCK_ENABLE |
 +                   ACPI_BITMASK_POWER_BUTTON_ENABLE |
 +                   ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
 +                   ACPI_BITMASK_TIMER_ENABLE)) != 0) ||
 +        (((s->ar.gpe.sts[0] & s->ar.gpe.en[0])
 +          & PIIX4_PCI_HOTPLUG_STATUS) != 0);
 +
 +    qemu_set_irq(s->irq, sci_level);
 +    /* schedule a timer interruption if needed */
 +    acpi_pm_tmr_update(&s->ar, (s->ar.pm1.evt.en & ACPI_BITMASK_TIMER_ENABLE) &&
 +                       !(pmsts & ACPI_BITMASK_TIMER_STATUS));
 +}
 +
 +static void pm_tmr_timer(ACPIREGS *ar)
 +{
 +    PIIX4PMState *s = container_of(ar, PIIX4PMState, ar);
 +    pm_update_sci(s);
 +}
 +
 +void maru_pm1_cnt_write(ACPIREGS *ar, uint16_t val)
 +{
 +    ar->pm1.cnt.cnt = val & ~(ACPI_BITMASK_SLEEP_ENABLE);
 +
 +    if (val & ACPI_BITMASK_SLEEP_ENABLE) {
 +        /* change suspend type */
 +        uint16_t sus_typ = (val >> 10) & 7;
 +        switch(sus_typ) {
 +        case 0: /* soft power off */
 +            qemu_system_shutdown_request();
 +            break;
 +        case 1:
 +#if 0 // changed suspend operation for emulator
 +            qemu_system_suspend_request();
 +#else
 +            INFO( "suspend is requested.\n" );
 +            is_suspended = 1;
 +#endif// end : changed suspend operation for emulator
 +            break;
 +        default:
 +            break;
 +        }
 +    }
 +}
 +
 +static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width,
 +                            uint64_t val)
 +{
 +    PIIX4PMState *s = container_of(ioport, PIIX4PMState, ioport);
 +
 +    if (width != 2) {
 +        PIIX4_DPRINTF("PM write port=0x%04x width=%d val=0x%08x\n",
 +                      (unsigned)addr, width, (unsigned)val);
 +    }
 +
 +    switch(addr) {
 +    case 0x00:
 +        acpi_pm1_evt_write_sts(&s->ar, val);
 +        pm_update_sci(s);
 +        break;
 +    case 0x02:
 +        acpi_pm1_evt_write_en(&s->ar, val);
 +        pm_update_sci(s);
 +        break;
 +    case 0x04:
 +#if 0
 +        acpi_pm1_cnt_write(&s->ar, val);
 +#else
 +        maru_pm1_cnt_write(&s->ar, val);
 +#endif
 +        break;
 +    default:
 +        break;
 +    }
 +    PIIX4_DPRINTF("PM writew port=0x%04x val=0x%04x\n", (unsigned int)addr,
 +                  (unsigned int)val);
 +}
 +
 +static void pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width,
 +                            uint64_t *data)
 +{
 +    PIIX4PMState *s = container_of(ioport, PIIX4PMState, ioport);
 +    uint32_t val;
 +
 +    switch(addr) {
 +    case 0x00:
 +        val = acpi_pm1_evt_get_sts(&s->ar);
 +        break;
 +    case 0x02:
 +        val = s->ar.pm1.evt.en;
 +        break;
 +    case 0x04:
 +        val = s->ar.pm1.cnt.cnt;
 +        break;
 +    case 0x08:
 +        val = acpi_pm_tmr_get(&s->ar);
 +        break;
 +    default:
 +        val = 0;
 +        break;
 +    }
 +    PIIX4_DPRINTF("PM readw port=0x%04x val=0x%04x\n", (unsigned int)addr, val);
 +    *data = val;
 +}
 +
 +static const IORangeOps pm_iorange_ops = {
 +    .read = pm_ioport_read,
 +    .write = pm_ioport_write,
 +};
 +
 +static void apm_ctrl_changed(uint32_t val, void *arg)
 +{
 +    PIIX4PMState *s = arg;
 +
 +    /* ACPI specs 3.0, 4.7.2.5 */
 +    acpi_pm1_cnt_update(&s->ar, val == ACPI_ENABLE, val == ACPI_DISABLE);
 +
 +    if (s->dev.config[0x5b] & (1 << 1)) {
 +        if (s->smi_irq) {
 +            qemu_irq_raise(s->smi_irq);
 +        }
 +    }
 +}
 +
 +static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
 +{
 +    PIIX4_DPRINTF("ACPI: DBG: 0x%08x\n", val);
 +}
 +
 +static void pm_io_space_update(PIIX4PMState *s)
 +{
 +    uint32_t pm_io_base;
 +
 +    if (s->dev.config[0x80] & 1) {
 +        pm_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x40));
 +        pm_io_base &= 0xffc0;
 +
 +        /* XXX: need to improve memory and ioport allocation */
 +        PIIX4_DPRINTF("PM: mapping to 0x%x\n", pm_io_base);
 +        iorange_init(&s->ioport, &pm_iorange_ops, pm_io_base, 64);
 +        ioport_register(&s->ioport);
 +    }
 +}
 +
 +static void pm_write_config(PCIDevice *d,
 +                            uint32_t address, uint32_t val, int len)
 +{
 +    pci_default_write_config(d, address, val, len);
 +    if (range_covers_byte(address, len, 0x80))
 +        pm_io_space_update((PIIX4PMState *)d);
 +}
 +
 +static void vmstate_pci_status_pre_save(void *opaque)
 +{
 +    struct pci_status *pci0_status = opaque;
 +    PIIX4PMState *s = container_of(pci0_status, PIIX4PMState, pci0_status);
 +
 +    /* We no longer track up, so build a safe value for migrating
 +     * to a version that still does... of course these might get lost
 +     * by an old buggy implementation, but we try. */
 +    pci0_status->up = s->pci0_slot_device_present & s->pci0_hotplug_enable;
 +}
 +
 +static int vmstate_acpi_post_load(void *opaque, int version_id)
 +{
 +    PIIX4PMState *s = opaque;
 +
 +    pm_io_space_update(s);
 +    return 0;
 +}
 +
 +#define VMSTATE_GPE_ARRAY(_field, _state)                            \
 + {                                                                   \
 +     .name       = (stringify(_field)),                              \
 +     .version_id = 0,                                                \
 +     .num        = GPE_LEN,                                          \
 +     .info       = &vmstate_info_uint16,                             \
 +     .size       = sizeof(uint16_t),                                 \
 +     .flags      = VMS_ARRAY | VMS_POINTER,                          \
 +     .offset     = vmstate_offset_pointer(_state, _field, uint8_t),  \
 + }
 +
 +static const VMStateDescription vmstate_gpe = {
 +    .name = "gpe",
 +    .version_id = 1,
 +    .minimum_version_id = 1,
 +    .minimum_version_id_old = 1,
 +    .fields      = (VMStateField []) {
 +        VMSTATE_GPE_ARRAY(sts, ACPIGPE),
 +        VMSTATE_GPE_ARRAY(en, ACPIGPE),
 +        VMSTATE_END_OF_LIST()
 +    }
 +};
 +
 +static const VMStateDescription vmstate_pci_status = {
 +    .name = "pci_status",
 +    .version_id = 1,
 +    .minimum_version_id = 1,
 +    .minimum_version_id_old = 1,
 +    .pre_save = vmstate_pci_status_pre_save,
 +    .fields      = (VMStateField []) {
 +        VMSTATE_UINT32(up, struct pci_status),
 +        VMSTATE_UINT32(down, struct pci_status),
 +        VMSTATE_END_OF_LIST()
 +    }
 +};
 +
 +static const VMStateDescription vmstate_acpi = {
 +    .name = "piix4_pm",
 +    .version_id = 2,
 +    .minimum_version_id = 1,
 +    .minimum_version_id_old = 1,
 +    .post_load = vmstate_acpi_post_load,
 +    .fields      = (VMStateField []) {
 +        VMSTATE_PCI_DEVICE(dev, PIIX4PMState),
 +        VMSTATE_UINT16(ar.pm1.evt.sts, PIIX4PMState),
 +        VMSTATE_UINT16(ar.pm1.evt.en, PIIX4PMState),
 +        VMSTATE_UINT16(ar.pm1.cnt.cnt, PIIX4PMState),
 +        VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_apm, APMState),
 +        VMSTATE_TIMER(ar.tmr.timer, PIIX4PMState),
 +        VMSTATE_INT64(ar.tmr.overflow_time, PIIX4PMState),
 +        VMSTATE_STRUCT(ar.gpe, PIIX4PMState, 2, vmstate_gpe, ACPIGPE),
 +        VMSTATE_STRUCT(pci0_status, PIIX4PMState, 2, vmstate_pci_status,
 +                       struct pci_status),
 +        VMSTATE_END_OF_LIST()
 +    }
 +};
 +
 +static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
 +{
-     QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
++    BusChild *kid, *next;
 +    BusState *bus = qdev_get_parent_bus(&s->dev.qdev);
 +    int slot = ffs(slots) - 1;
 +    bool slot_free = true;
 +
 +    /* Mark request as complete */
 +    s->pci0_status.down &= ~(1U << slot);
 +
-                 object_unparent(OBJECT(dev));
++    QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
++        DeviceState *qdev = kid->child;
 +        PCIDevice *dev = PCI_DEVICE(qdev);
 +        PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
 +        if (PCI_SLOT(dev->devfn) == slot) {
 +            if (pc->no_hotplug) {
 +                slot_free = false;
 +            } else {
-     DeviceState *qdev, *next;
 +                qdev_free(qdev);
 +            }
 +        }
 +    }
 +    if (slot_free) {
 +        s->pci0_slot_device_present &= ~(1U << slot);
 +    }
 +}
 +
 +static void piix4_update_hotplug(PIIX4PMState *s)
 +{
 +    PCIDevice *dev = &s->dev;
 +    BusState *bus = qdev_get_parent_bus(&dev->qdev);
-     QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
++    BusChild *kid, *next;
 +
 +    /* Execute any pending removes during reset */
 +    while (s->pci0_status.down) {
 +        acpi_piix_eject_slot(s, s->pci0_status.down);
 +    }
 +
 +    s->pci0_hotplug_enable = ~0;
 +    s->pci0_slot_device_present = 0;
 +
-     pci_conf[0x40] = 0x01; /* PM io base read only bit */
++    QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
++        DeviceState *qdev = kid->child;
 +        PCIDevice *pdev = PCI_DEVICE(qdev);
 +        PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pdev);
 +        int slot = PCI_SLOT(pdev->devfn);
 +
 +        if (pc->no_hotplug) {
 +            s->pci0_hotplug_enable &= ~(1U << slot);
 +        }
 +
 +        s->pci0_slot_device_present |= (1U << slot);
 +    }
 +}
 +
 +static void piix4_reset(void *opaque)
 +{
 +    PIIX4PMState *s = opaque;
 +    uint8_t *pci_conf = s->dev.config;
 +
 +    pci_conf[0x58] = 0;
 +    pci_conf[0x59] = 0;
 +    pci_conf[0x5a] = 0;
 +    pci_conf[0x5b] = 0;
 +
++    pci_conf[0x40] = 0x01; /* PM io base read only bit */
++    pci_conf[0x80] = 0;
++
 +    if (s->kvm_enabled) {
 +        /* Mark SMM as already inited (until KVM supports SMM). */
 +        pci_conf[0x5B] = 0x02;
 +    }
 +    piix4_update_hotplug(s);
 +}
 +
 +static void piix4_powerdown(void *opaque, int irq, int power_failing)
 +{
 +    PIIX4PMState *s = opaque;
 +
 +    assert(s != NULL);
 +    acpi_pm1_evt_power_down(&s->ar);
 +}
 +
 +static void piix4_pm_machine_ready(Notifier *n, void *opaque)
 +{
 +    PIIX4PMState *s = container_of(n, PIIX4PMState, machine_ready);
 +    uint8_t *pci_conf;
 +
 +    pci_conf = s->dev.config;
 +    pci_conf[0x5f] = (isa_is_ioport_assigned(0x378) ? 0x80 : 0) | 0x10;
 +    pci_conf[0x63] = 0x60;
 +    pci_conf[0x67] = (isa_is_ioport_assigned(0x3f8) ? 0x08 : 0) |
 +    (isa_is_ioport_assigned(0x2f8) ? 0x90 : 0);
 +
 +}
 +
 +static int piix4_pm_initfn(PCIDevice *dev)
 +{
 +    PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev, dev);
 +    uint8_t *pci_conf;
 +
 +    pci_conf = s->dev.config;
 +    pci_conf[0x06] = 0x80;
 +    pci_conf[0x07] = 0x02;
 +    pci_conf[0x09] = 0x00;
 +    pci_conf[0x3d] = 0x01; // interrupt pin 1
 +
-                        int kvm_enabled)
 +    /* APM */
 +    apm_init(&s->apm, apm_ctrl_changed, s);
 +
 +    register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s);
 +
 +    if (s->kvm_enabled) {
 +        /* Mark SMM as already inited to prevent SMM from running.  KVM does not
 +         * support SMM mode. */
 +        pci_conf[0x5B] = 0x02;
 +    }
 +
 +    /* XXX: which specification is used ? The i82731AB has different
 +       mappings */
 +    pci_conf[0x90] = s->smb_io_base | 1;
 +    pci_conf[0x91] = s->smb_io_base >> 8;
 +    pci_conf[0xd2] = 0x09;
 +    register_ioport_write(s->smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
 +    register_ioport_read(s->smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
 +
 +    acpi_pm_tmr_init(&s->ar, pm_tmr_timer);
 +    acpi_gpe_init(&s->ar, GPE_LEN);
 +
 +    qemu_system_powerdown = *qemu_allocate_irqs(piix4_powerdown, s, 1);
 +
 +    pm_smbus_init(&s->dev.qdev, &s->smb);
 +    s->machine_ready.notify = piix4_pm_machine_ready;
 +    qemu_add_machine_init_done_notifier(&s->machine_ready);
 +    qemu_register_reset(piix4_reset, s);
 +    piix4_acpi_system_hot_add_init(dev->bus, s);
 +
 +    return 0;
 +}
 +
 +i2c_bus *maru_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
 +                       qemu_irq sci_irq, qemu_irq smi_irq,
++                       int kvm_enabled, void *fw_cfg)
 +{
 +    PCIDevice *dev;
 +    PIIX4PMState *s;
 +
 +    dev = pci_create(bus, devfn, "MARU_PM");
 +    qdev_prop_set_uint32(&dev->qdev, "smb_io_base", smb_io_base);
 +
 +    s = DO_UPCAST(PIIX4PMState, dev, dev);
 +    s->irq = sci_irq;
 +    acpi_pm1_cnt_init(&s->ar);
 +    s->smi_irq = smi_irq;
 +    s->kvm_enabled = kvm_enabled;
 +
 +    qdev_init_nofail(&dev->qdev);
 +
++    if (fw_cfg) {
++        uint8_t suspend[6] = {128, 0, 0, 129, 128, 128};
++        suspend[3] = 1 | ((!s->disable_s3) << 7);
++        suspend[4] = s->s4_val | ((!s->disable_s4) << 7);
++
++        fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup(suspend, 6), 6);
++    }
++
 +    return s->smb.smbus;
 +}
 +
 +static Property piix4_pm_properties[] = {
 +    DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
++    DEFINE_PROP_UINT8("disable_s3", PIIX4PMState, disable_s3, 0),
++    DEFINE_PROP_UINT8("disable_s4", PIIX4PMState, disable_s4, 0),
++    DEFINE_PROP_UINT8("s4_val", PIIX4PMState, s4_val, 2),
 +    DEFINE_PROP_END_OF_LIST(),
 +};
 +
 +static void piix4_pm_class_init(ObjectClass *klass, void *data)
 +{
 +    DeviceClass *dc = DEVICE_CLASS(klass);
 +    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 +
 +    k->no_hotplug = 1;
 +    k->init = piix4_pm_initfn;
 +    k->config_write = pm_write_config;
 +    k->vendor_id = PCI_VENDOR_ID_INTEL;
 +    k->device_id = PCI_DEVICE_ID_INTEL_82371AB_3;
 +    k->revision = 0x03;
 +    k->class_id = PCI_CLASS_BRIDGE_OTHER;
 +    dc->desc = "PM";
 +    dc->no_user = 1;
 +    dc->vmsd = &vmstate_acpi;
 +    dc->props = piix4_pm_properties;
 +}
 +
 +static TypeInfo piix4_pm_info = {
 +    .name          = "MARU_PM",
 +    .parent        = TYPE_PCI_DEVICE,
 +    .instance_size = sizeof(PIIX4PMState),
 +    .class_init    = piix4_pm_class_init,
 +};
 +
 +static void piix4_pm_register_types(void)
 +{
 +    type_register_static(&piix4_pm_info);
 +}
 +
 +type_init(piix4_pm_register_types)
 +
 +static uint32_t gpe_readb(void *opaque, uint32_t addr)
 +{
 +    PIIX4PMState *s = opaque;
 +    uint32_t val = acpi_gpe_ioport_readb(&s->ar, addr);
 +
 +    PIIX4_DPRINTF("gpe read %x == %x\n", addr, val);
 +    return val;
 +}
 +
 +static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
 +{
 +    PIIX4PMState *s = opaque;
 +
 +    acpi_gpe_ioport_writeb(&s->ar, addr, val);
 +    pm_update_sci(s);
 +
 +    PIIX4_DPRINTF("gpe write %x <== %d\n", addr, val);
 +}
 +
 +static uint32_t pci_up_read(void *opaque, uint32_t addr)
 +{
 +    PIIX4PMState *s = opaque;
 +    uint32_t val;
 +
 +    /* Manufacture an "up" value to cause a device check on any hotplug
 +     * slot with a device.  Extra device checks are harmless. */
 +    val = s->pci0_slot_device_present & s->pci0_hotplug_enable;
 +
 +    PIIX4_DPRINTF("pci_up_read %x\n", val);
 +    return val;
 +}
 +
 +static uint32_t pci_down_read(void *opaque, uint32_t addr)
 +{
 +    PIIX4PMState *s = opaque;
 +    uint32_t val = s->pci0_status.down;
 +
 +    PIIX4_DPRINTF("pci_down_read %x\n", val);
 +    return val;
 +}
 +
 +static uint32_t pci_features_read(void *opaque, uint32_t addr)
 +{
 +    /* No feature defined yet */
 +    PIIX4_DPRINTF("pci_features_read %x\n", 0);
 +    return 0;
 +}
 +
 +static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
 +{
 +    acpi_piix_eject_slot(opaque, val);
 +
 +    PIIX4_DPRINTF("pciej write %x <== %d\n", addr, val);
 +}
 +
 +static uint32_t pcirmv_read(void *opaque, uint32_t addr)
 +{
 +    PIIX4PMState *s = opaque;
 +
 +    return s->pci0_hotplug_enable;
 +}
 +
 +static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
 +                                PCIHotplugState state);
 +
 +static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
 +{
 +
 +    register_ioport_write(GPE_BASE, GPE_LEN, 1, gpe_writeb, s);
 +    register_ioport_read(GPE_BASE, GPE_LEN, 1,  gpe_readb, s);
 +    acpi_gpe_blk(&s->ar, GPE_BASE);
 +
 +    register_ioport_read(PCI_UP_BASE, 4, 4, pci_up_read, s);
 +    register_ioport_read(PCI_DOWN_BASE, 4, 4, pci_down_read, s);
 +
 +    register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, s);
 +    register_ioport_read(PCI_EJ_BASE, 4, 4,  pci_features_read, s);
 +
 +    register_ioport_read(PCI_RMV_BASE, 4, 4,  pcirmv_read, s);
 +
 +    pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev);
 +}
 +
 +static void enable_device(PIIX4PMState *s, int slot)
 +{
 +    s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
 +    s->pci0_slot_device_present |= (1U << slot);
 +}
 +
 +static void disable_device(PIIX4PMState *s, int slot)
 +{
 +    s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
 +    s->pci0_status.down |= (1U << slot);
 +}
 +
 +static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
 +                PCIHotplugState state)
 +{
 +    int slot = PCI_SLOT(dev->devfn);
 +    PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev,
 +                                PCI_DEVICE(qdev));
 +
 +    /* Don't send event when device is enabled during qemu machine creation:
 +     * it is present on boot, no hotplug event is necessary. We do send an
 +     * event when the device is disabled later. */
 +    if (state == PCI_COLDPLUG_ENABLED) {
 +        s->pci0_slot_device_present |= (1U << slot);
 +        return 0;
 +    }
 +
 +    if (state == PCI_HOTPLUG_ENABLED) {
 +        enable_device(s, slot);
 +    } else {
 +        disable_device(s, slot);
 +    }
 +
 +    pm_update_sci(s);
 +
 +    return 0;
 +}
 +
 +void resume(void)
 +{
 +    is_suspended = 0;
 +}
 +
 +int is_suspended_state( void ) {
 +    return is_suspended;
 +}
index 51356f1,0000000..8416fce
mode 100644,000000..100644
--- /dev/null
@@@ -1,54 -1,0 +1,54 @@@
-                        int kvm_enabled);
 +/*
 + * Maru power management emulator
 + * Based on qemu/hw/acpi_piix4.h
 + *
 + * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
 + *
 + * Contact:
 + * Hyunjun Son <hj79.son@samsung.com>
 + * GiWoong Kim <giwoong.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
 + *
 + */
 +
 +#ifndef MARU_PM_H_
 +#define MARU_PM_H_
 +
 +#include "qemu-common.h"
 +
 +i2c_bus *maru_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
 +                       qemu_irq sci_irq, qemu_irq smi_irq,
++                       int kvm_enabled, void *fw_cfg);
 +
 +#ifdef TARGET_ARM
 +static int is_suspended_state( void )
 +{
 +    return 0;
 +}
 +static void resume( void )
 +{
 +    return;
 +}
 +#else
 +void resume( void );
 +int is_suspended_state( void );
 +#endif
 +
 +#endif /* MARU_PM_H_ */
index 0c82c26,0000000..56fe261
mode 100644,000000..100644
--- /dev/null
@@@ -1,1649 -1,0 +1,1955 @@@
- static const char *screen_dump_filename;
- static DisplayChangeListener *screen_dump_dcl;
 +/*
 + * Maru vga device
 + * Based on qemu/hw/vga.c
 + *
 + * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
 + *
 + * Contact:
 + * HyunJun Son <hj79.son@samsung.com>
 + * GiWoong Kim <giwoong.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 "maru_common.h"
 +
 +#ifdef CONFIG_DARWIN
 +//shared memory
 +#define USE_SHM
 +#endif
 +
 +#include "hw.h"
++#include "vga.h"
 +#include "console.h"
 +#include "pc.h"
 +#include "pci.h"
 +#include "vga_int.h"
 +#include "pixel_ops.h"
 +#include "qemu-timer.h"
++#include "xen.h"
++#include "trace.h"
++
 +#include "maru_vga_int.h"
 +#include "maru_brightness.h"
 +#include "maru_overlay.h"
 +#include "emul_state.h"
 +#include "debug_ch.h"
 +
 +#ifdef USE_SHM
 +#include <sys/shm.h>
 +#endif
 +
 +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
 +
 +#define MARU_VGA
 +
 +#ifdef USE_SHM
 +/* shared memory */
 +void *shared_memory = (void*)0;
 +int shmid;
 +#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_screen_dump(void *opaque, const char *filename, bool cswitch);
-     htotal_chars = s->cr[0x00] + 5;
-     hretr_start_char = s->cr[0x04];
-     hretr_skew_chars = (s->cr[0x05] >> 5) & 3;
-     hretr_end_char = s->cr[0x05] & 0x1f;
++
++static void vga_update_memory_access(VGACommonState *s)
++{
++    MemoryRegion *region, *old_region = s->chain4_alias;
++    target_phys_addr_t base, offset, size;
++
++    s->chain4_alias = NULL;
++
++    if ((s->sr[VGA_SEQ_PLANE_WRITE] & VGA_SR02_ALL_PLANES) ==
++        VGA_SR02_ALL_PLANES && s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
++        offset = 0;
++        switch ((s->gr[VGA_GFX_MISC] >> 2) & 3) {
++        case 0:
++            base = 0xa0000;
++            size = 0x20000;
++            break;
++        case 1:
++            base = 0xa0000;
++            size = 0x10000;
++            offset = s->bank_offset;
++            break;
++        case 2:
++            base = 0xb0000;
++            size = 0x8000;
++            break;
++        case 3:
++        default:
++            base = 0xb8000;
++            size = 0x8000;
++            break;
++        }
++        base += isa_mem_base;
++        region = g_malloc(sizeof(*region));
++        memory_region_init_alias(region, "vga.chain4", &s->vram, offset, size);
++        memory_region_add_subregion_overlap(s->legacy_address_space, base,
++                                            region, 2);
++        s->chain4_alias = region;
++    }
++    if (old_region) {
++        memory_region_del_subregion(s->legacy_address_space, old_region);
++        memory_region_destroy(old_region);
++        g_free(old_region);
++        s->plane_updated = 0xf;
++    }
++}
 +
 +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;
 +
-     vtotal_lines = (s->cr[0x06]
-                     | (((s->cr[0x07] & 1) | ((s->cr[0x07] >> 4) & 2)) << 8)) + 2
-         ;
-     vretr_start_line = s->cr[0x10]
-         | ((((s->cr[0x07] >> 2) & 1) | ((s->cr[0x07] >> 6) & 2)) << 8)
-         ;
-     vretr_end_line = s->cr[0x11] & 0xf;
++    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;
 +
-     clocking_mode = (s->sr[0x01] >> 3) & 1;
++    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;
 +
-     div2 = (s->cr[0x17] >> 2) & 1;
-     sldiv2 = (s->cr[0x17] >> 3) & 1;
++    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
-         if (s->ar[0x10] & 0x80)
-             v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
-         else
-             v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
++    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;
 +
 +        cur_tick = qemu_get_clock_ns(vm_clock);
 +
 +        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);
 +}
 +
++#ifdef CONFIG_BOCHS_VBE
++static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
++{
++    VGACommonState *s = opaque;
++    uint32_t val;
++    val = s->vbe_index;
++    return val;
++}
++
++static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
++{
++    VGACommonState *s = opaque;
++    uint32_t val;
++
++    if (s->vbe_index < VBE_DISPI_INDEX_NB) {
++        if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
++            switch(s->vbe_index) {
++                /* XXX: do not hardcode ? */
++            case VBE_DISPI_INDEX_XRES:
++                val = VBE_DISPI_MAX_XRES;
++                break;
++            case VBE_DISPI_INDEX_YRES:
++                val = VBE_DISPI_MAX_YRES;
++                break;
++            case VBE_DISPI_INDEX_BPP:
++                val = VBE_DISPI_MAX_BPP;
++                break;
++            default:
++                val = s->vbe_regs[s->vbe_index];
++                break;
++            }
++        } else {
++            val = s->vbe_regs[s->vbe_index];
++        }
++    } else if (s->vbe_index == VBE_DISPI_INDEX_VIDEO_MEMORY_64K) {
++        val = s->vram_size / (64 * 1024);
++    } else {
++        val = 0;
++    }
++#ifdef DEBUG_BOCHS_VBE
++    printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
++#endif
++    return val;
++}
++
++static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
++{
++    VGACommonState *s = opaque;
++    s->vbe_index = val;
++}
++
++static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
++{
++    VGACommonState *s = opaque;
++
++    if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
++#ifdef DEBUG_BOCHS_VBE
++        printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
++#endif
++        switch(s->vbe_index) {
++        case VBE_DISPI_INDEX_ID:
++            if (val == VBE_DISPI_ID0 ||
++                val == VBE_DISPI_ID1 ||
++                val == VBE_DISPI_ID2 ||
++                val == VBE_DISPI_ID3 ||
++                val == VBE_DISPI_ID4) {
++                s->vbe_regs[s->vbe_index] = val;
++            }
++            break;
++        case VBE_DISPI_INDEX_XRES:
++            if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
++                s->vbe_regs[s->vbe_index] = val;
++            }
++            break;
++        case VBE_DISPI_INDEX_YRES:
++            if (val <= VBE_DISPI_MAX_YRES) {
++                s->vbe_regs[s->vbe_index] = val;
++            }
++            break;
++        case VBE_DISPI_INDEX_BPP:
++            if (val == 0)
++                val = 8;
++            if (val == 4 || val == 8 || val == 15 ||
++                val == 16 || val == 24 || val == 32) {
++                s->vbe_regs[s->vbe_index] = val;
++            }
++            break;
++        case VBE_DISPI_INDEX_BANK:
++            if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
++              val &= (s->vbe_bank_mask >> 2);
++            } else {
++              val &= s->vbe_bank_mask;
++            }
++            s->vbe_regs[s->vbe_index] = val;
++            s->bank_offset = (val << 16);
++            vga_update_memory_access(s);
++            break;
++        case VBE_DISPI_INDEX_ENABLE:
++            if ((val & VBE_DISPI_ENABLED) &&
++                !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
++                int h, shift_control;
++
++                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
++                    s->vbe_regs[VBE_DISPI_INDEX_XRES];
++                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
++                    s->vbe_regs[VBE_DISPI_INDEX_YRES];
++                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
++                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
++
++                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
++                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
++                else
++                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
++                        ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
++                s->vbe_start_addr = 0;
++
++                /* clear the screen (should be done in BIOS) */
++                if (!(val & VBE_DISPI_NOCLEARMEM)) {
++                    memset(s->vram_ptr, 0,
++                           s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
++                }
++
++                /* we initialize the VGA graphic mode (should be done
++                   in BIOS) */
++                /* graphic mode + memory map 1 */
++                s->gr[VGA_GFX_MISC] = (s->gr[VGA_GFX_MISC] & ~0x0c) | 0x04 |
++                    VGA_GR06_GRAPHICS_MODE;
++                s->cr[VGA_CRTC_MODE] |= 3; /* no CGA modes */
++                s->cr[VGA_CRTC_OFFSET] = s->vbe_line_offset >> 3;
++                /* width */
++                s->cr[VGA_CRTC_H_DISP] =
++                    (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
++                /* height (only meaningful if < 1024) */
++                h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
++                s->cr[VGA_CRTC_V_DISP_END] = h;
++                s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x42) |
++                    ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
++                /* line compare to 1023 */
++                s->cr[VGA_CRTC_LINE_COMPARE] = 0xff;
++                s->cr[VGA_CRTC_OVERFLOW] |= 0x10;
++                s->cr[VGA_CRTC_MAX_SCAN] |= 0x40;
++
++                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
++                    shift_control = 0;
++                    s->sr[VGA_SEQ_CLOCK_MODE] &= ~8; /* no double line */
++                } else {
++                    shift_control = 2;
++                    /* set chain 4 mode */
++                    s->sr[VGA_SEQ_MEMORY_MODE] |= VGA_SR04_CHN_4M;
++                    /* activate all planes */
++                    s->sr[VGA_SEQ_PLANE_WRITE] |= VGA_SR02_ALL_PLANES;
++                }
++                s->gr[VGA_GFX_MODE] = (s->gr[VGA_GFX_MODE] & ~0x60) |
++                    (shift_control << 5);
++                s->cr[VGA_CRTC_MAX_SCAN] &= ~0x9f; /* no double scan */
++            } else {
++                /* XXX: the bios should do that */
++                s->bank_offset = 0;
++            }
++            s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
++            s->vbe_regs[s->vbe_index] = val;
++            vga_update_memory_access(s);
++            break;
++        case VBE_DISPI_INDEX_VIRT_WIDTH:
++            {
++                int w, h, line_offset;
++
++                if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
++                    return;
++                w = val;
++                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
++                    line_offset = w >> 1;
++                else
++                    line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
++                h = s->vram_size / line_offset;
++                /* XXX: support weird bochs semantics ? */
++                if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
++                    return;
++                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
++                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
++                s->vbe_line_offset = line_offset;
++            }
++            break;
++        case VBE_DISPI_INDEX_X_OFFSET:
++        case VBE_DISPI_INDEX_Y_OFFSET:
++            {
++                int x;
++                s->vbe_regs[s->vbe_index] = val;
++                s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
++                x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
++                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
++                    s->vbe_start_addr += x >> 1;
++                else
++                    s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
++                s->vbe_start_addr >>= 2;
++            }
++            break;
++        default:
++            break;
++        }
++    }
++}
++#endif
++
 +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];
-         line_offset = s->cr[0x13];
++        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;
 +#ifdef CONFIG_BOCHS_VBE
 +    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
 +#endif
 +    {
 +        /* compute line_offset in bytes */
-         start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
++        line_offset = s->cr[VGA_CRTC_OFFSET];
 +        line_offset <<= 3;
 +
 +        /* starting address */
-         line_compare = s->cr[0x18] |
-             ((s->cr[0x07] & 0x10) << 4) |
-             ((s->cr[0x09] & 0x40) << 3);
++        start_addr = s->cr[VGA_CRTC_START_LO] |
++            (s->cr[VGA_CRTC_START_HI] << 8);
 +
 +        /* line compare */
-     cheight = (s->cr[9] & 0x1f) + 1;
++        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(DisplayState *s)
 +{
 +    switch(ds_get_bits_per_pixel(s)) {
 +    default:
 +    case 8:
 +        return 0;
 +    case 15:
 +        return 1;
 +    case 16:
 +        return 2;
 +    case 32:
 +        if (is_surface_bgr(s->surface))
 +            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 */
-     if (!(s->sr[1] & 0x01))
++    cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
 +    cwidth = 8;
-     if (s->sr[1] & 0x08)
++    if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
 +        cwidth = 9;
-     width = (s->cr[0x01] + 1);
-     if (s->cr[0x06] == 100) {
++    }
++    if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
 +        cwidth = 16; /* NOTE: no 18 pixel wide */
-         height = s->cr[0x12] |
-             ((s->cr[0x07] & 0x02) << 7) |
-             ((s->cr[0x07] & 0x40) << 3);
++    }
++    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 {
-     v = s->sr[3];
++        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)
 +{
 +    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;
++    int64_t now = qemu_get_clock_ms(vm_clock);
 +
 +    /* compute font data address (in plane 2) */
-     cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
++    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->ds, s->last_scr_width, s->last_scr_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(s->ds)];
 +    full_update |= update_palette16(s);
 +    palette = s->last_palette;
 +    x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
 +
-         s->cr[0xa] != s->cursor_start ||
-         s->cr[0xb] != s->cursor_end) {
++    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->cursor_start = s->cr[0xa];
-         s->cursor_end = s->cr[0xb];
++        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;
-             if (full_update || ch_attr != *ch_attr_ptr) {
++        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(s->ds);
 +    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 = ds_get_data(s->ds);
 +    linesize = ds_get_linesize(s->ds);
 +    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 (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
++            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;
-                     !(s->cr[0x0a] & 0x20)) {
++                    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 &&
-                     line_start = s->cr[0x0a] & 0x1f;
-                     line_last = s->cr[0x0b] & 0x1f;
++                    !(s->cr[VGA_CRTC_CURSOR_START] & 0x20) &&
++                    s->cursor_visible_phase) {
 +                    int line_start, line_last, h;
 +                    /* draw the cursor */
-         width = (s->cr[0x01] + 1) * 8;
-         height = s->cr[0x12] |
-             ((s->cr[0x07] & 0x02) << 7) |
-             ((s->cr[0x07] & 0x40) << 3);
++                    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_update(s->ds, 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;
 +#ifdef CONFIG_BOCHS_VBE
 +    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
 +        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
 +    } else
 +#endif
 +    {
 +        ret = 0;
 +    }
 +    return ret;
 +}
 +
 +static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
 +{
 +    int width, height;
 +
 +#ifdef CONFIG_BOCHS_VBE
 +    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
 +#endif
 +    {
-     shift_control = (s->gr[0x05] >> 5) & 3;
-     double_scan = (s->cr[0x09] >> 7);
++        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;
 +}
 +
 +static void vga_sync_dirty_bitmap(VGACommonState *s)
 +{
 +    memory_region_sync_dirty_bitmap(&s->vram);
 +}
 +
 +/*
 + * graphic modes
 + */
 +static void vga_draw_graphic(VGACommonState *s, int full_update)
 +{
 +    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;
 +
 +    full_update |= update_basic_params(s);
 +
 +    if (!full_update)
 +        vga_sync_dirty_bitmap(s);
 +
 +    s->get_resolution(s, &width, &height);
 +
 +    disp_width = width;
 +
-         multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
++    shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
++    double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
 +    if (shift_control != 1) {
-         if (s->sr[0x01] & 8) {
++        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[0x01] & 8) {
++        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
 +            disp_width <<= 1;
 +        }
 +    } else if (shift_control == 1) {
-         if (s->sr[0x01] & 8) {
++        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 defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
 +        if (depth == 16 || depth == 32) {
 +#else
 +        if (depth == 32) {
 +#endif
 +            qemu_free_displaysurface(s->ds);
 +
 +#ifdef MARU_VGA // create new sufrace by malloc in MARU VGA
 +
 +#ifdef USE_SHM
 +            s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
 +                    disp_width * 4, (uint8_t*)shared_memory);
 +#else
 +            s->ds->surface = qemu_create_displaysurface(s->ds, disp_width, height);
 +#endif //USE_SHM
 +
 +#else //MARU_VGA
 +            s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
 +                    s->line_offset,
 +                    s->vram_ptr + (s->start_addr * 4));
 +#endif //MARU_VGA
 +
 +#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
 +            s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
 +#endif
 +            dpy_resize(s->ds);
 +        } else {
 +            qemu_console_resize(s->ds, disp_width, height);
 +        }
 +        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;
 +#ifndef USE_SHM
 +    } else if (is_buffer_shared(s->ds->surface) &&
 +               (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
 +        s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
 +        dpy_setdata(s->ds);
 +    }
 +#else
 +    }
 +#endif
 +    s->rgb_to_pixel =
 +        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
 +
 +    if (shift_control == 0) {
 +        full_update |= update_palette16(s);
-         if (s->sr[0x01] & 8) {
++        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);
-            width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
++        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(s->ds)];
 +
 +#ifndef USE_SHM
 +    if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
 +#else
 +    if (s->cursor_invalidate)
 +#endif
 +        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",
-             mask = (s->cr[0x17] & 3) ^ 3;
++           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 = ds_get_data(s->ds);
 +    linesize = ds_get_linesize(s->ds);
 +    y1 = 0;
 +    for(y = 0; y < height; y++) {
 +        addr = addr1;
 +        if (!(s->cr[0x17] & 1)) {
 +            int shift;
 +            /* CGA compatibility handling */
 +            shift = 14 + ((s->cr[0x17] >> 6) & 1);
 +            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
 +        }
 +        if (!(s->cr[0x17] & 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;
 +#ifndef USE_SHM
 +            if (!(is_buffer_shared(s->ds->surface))) {
 +#endif
 +                maru_vga_draw_line(s, d, s->vram_ptr + addr, width);
 +                if (s->cursor_draw_line)
 +                    s->cursor_draw_line(s, d, y);
 +#ifndef USE_SHM
 +            }
 +#endif
 +
 +#ifdef MARU_VGA
 +
 +            int i;
 +            uint8_t *fb_sub;
 +            uint8_t *over_sub;
 +            uint8_t *dst_sub;
 +            uint8_t alpha, c_alpha;
 +            uint32_t *dst;
 +            uint16_t overlay_bottom;
 +
 +            if ( overlay0_power ) {
 +
 +                overlay_bottom = overlay0_top + overlay0_height;
 +
 +                if ( overlay0_top <= y && y < overlay_bottom ) {
 +
 +                    fb_sub = s->vram_ptr + addr + overlay0_left * 4;
 +                    over_sub = overlay_ptr + ( y - overlay0_top ) * overlay0_width * 4;
 +                    dst = (uint32_t*) ( s->ds->surface->data + addr + overlay0_left * 4 );
 +
 +                    for ( i = 0; i < overlay0_width; i++, fb_sub += 4, over_sub += 4, dst++ ) {
 +
 +                        alpha = fb_sub[3];
 +                        c_alpha = 0xff - alpha;
 +
 +                        *dst = ( ( c_alpha * over_sub[0] + alpha * fb_sub[0] ) >> 8 )
 +                            | ( ( c_alpha * over_sub[1] + alpha * fb_sub[1] ) & 0xFF00 )
 +                            | ( ( ( c_alpha * over_sub[2] + alpha * fb_sub[2] ) & 0xFF00 ) << 8 );
 +                    }
 +
 +                }
 +
 +            }
 +
 +            if ( overlay1_power ) {
 +
 +                overlay_bottom = overlay1_top + overlay1_height;
 +
 +                if ( overlay1_top <= y && y < overlay_bottom ) {
 +
 +                    fb_sub = s->vram_ptr + addr + overlay1_left * 4;
 +                    over_sub = overlay_ptr + ( y - overlay1_top ) * overlay1_width * 4 + 0x00400000;
 +                    dst = (uint32_t*) ( s->ds->surface->data + addr + overlay1_left * 4 );
 +
 +                    for ( i = 0; i < overlay1_width; i++, fb_sub += 4, over_sub += 4, dst++ ) {
 +
 +                        alpha = fb_sub[3];
 +                        c_alpha = 0xff - alpha;
 +
 +                        *dst = ( ( c_alpha * over_sub[0] + alpha * fb_sub[0] ) >> 8 )
 +                            | ( ( c_alpha * over_sub[1] + alpha * fb_sub[1] ) & 0xFF00 )
 +                            | ( ( ( c_alpha * over_sub[2] + alpha * fb_sub[2] ) & 0xFF00 ) << 8 );
 +                    }
 +
 +                }
 +
 +            }
 +
 +            if ( brightness_off ) {
 +
 +                dst_sub = s->ds->surface->data + addr;
 +                dst = (uint32_t*) ( s->ds->surface->data + addr );
 +
 +                for ( i = 0; i < disp_width; i++, dst_sub += 4, dst++ ) {
 +                    *dst = 0xFF000000; // black
 +                }
 +
 +            } else  {
 +
 +                if ( brightness_level < BRIGHTNESS_MAX ) {
 +
 +                    alpha = brightness_tbl[brightness_level];
 +
 +                    dst_sub = s->ds->surface->data + addr;
 +                    dst = (uint32_t*) ( s->ds->surface->data + addr );
 +
 +                    for ( i = 0; i < disp_width; i++, dst_sub += 4, dst++ ) {
 +                        *dst = ( ( alpha * dst_sub[0] ) >> 8 )
 +                                | ( ( alpha * dst_sub[1] ) & 0xFF00 )
 +                                | ( ( ( alpha * dst_sub[2] ) & 0xFF00 ) << 8 );
 +                    }
 +                }
 +
 +            }
 +
 +#endif /* MARU_VGA */
 +
 +        } else {
 +            if (y_start >= 0) {
 +                /* flush to display */
 +                dpy_update(s->ds, 0, y_start,
 +                           disp_width, y - y_start);
 +                y_start = -1;
 +            }
 +        }
 +        if (!multi_run) {
-             graphic_mode = s->gr[6] & 1;
++            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_update(s->ds, 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)
 +{
 +    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(s->ds)];
 +    if (ds_get_bits_per_pixel(s->ds) == 8)
 +        val = s->rgb_to_pixel(0, 0, 0);
 +    else
 +        val = 0;
 +    w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
 +    d = ds_get_data(s->ds);
 +    for(i = 0; i < s->last_scr_height; i++) {
 +        memset(d, val, w);
 +        d += ds_get_linesize(s->ds);
 +    }
 +    dpy_update(s->ds, 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;
 +    int full_update, graphic_mode;
 +
 +    qemu_flush_coalesced_mmio_buffer();
 +
 +    if (ds_get_bits_per_pixel(s->ds) == 0) {
 +        /* nothing to do */
 +    } else {
 +        full_update = 0;
 +        if (!(s->ar_index & 0x20)) {
 +            graphic_mode = GMODE_BLANK;
 +        } else {
-         graphic_mode = s->gr[6] & 1;
++            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_get_clock_ms(vm_clock);
 +            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;
 +}
 +
++static void vga_reset(void *opaque)
++{
++    VGACommonState *s =  opaque;
++    vga_common_reset(s);
++}
 +
 +#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 {
-         cheight = (s->cr[9] & 0x1f) + 1;
++        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 */
-         if (!(s->sr[1] & 0x01))
++        cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
 +        cw = 8;
-         if (s->sr[1] & 0x08)
++        if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
 +            cw = 9;
-         width = (s->cr[0x01] + 1);
-         if (s->cr[0x06] == 100) {
++        }
++        if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
 +            cw = 16; /* NOTE: no 18 pixel wide */
-             height = s->cr[0x12] | 
-                 ((s->cr[0x07] & 0x02) << 7) | 
-                 ((s->cr[0x07] & 0x40) << 3);
++        }
++        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 {
-         cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
++            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;
 +            s->ds->surface->width = width;
 +            s->ds->surface->height = height;
 +            dpy_resize(s->ds);
 +            s->last_width = width;
 +            s->last_height = height;
 +            s->last_ch = cheight;
 +            s->last_cw = cw;
 +            full_update = 1;
 +        }
 +
 +        /* Update "hardware" cursor */
-             s->cr[0xa] != s->cursor_start ||
-             s->cr[0xb] != s->cursor_end || full_update) {
-             cursor_visible = !(s->cr[0xa] & 0x20);
++        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->cursor_start = s->cr[0xa];
-             s->cursor_end = s->cr[0xb];
++            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_cursor(s->ds,
 +                           TEXTMODE_X(cursor_offset),
 +                           TEXTMODE_Y(cursor_offset));
 +            else
 +                dpy_cursor(s->ds, -1, -1);
 +            s->cursor_offset = cursor_offset;
- void maru_vga_common_init(VGACommonState *s, int vga_ram_size)
++            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_update(s->ds, 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_update(s->ds, 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_cursor(s->ds, -1, -1);
 +    s->ds->surface->width = s->last_width;
 +    s->ds->surface->height = height;
 +    dpy_resize(s->ds);
 +
 +    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_update(s->ds, 0, 0, s->last_width, height);
 +}
 +
-     memory_region_init_ram(&s->vram, "maru_vga.vram", vga_ram_size);
++
++static uint64_t vga_mem_read(void *opaque, target_phys_addr_t addr,
++                             unsigned size)
++{
++    VGACommonState *s = opaque;
++
++    return vga_mem_readb(s, addr);
++}
++
++static void vga_mem_write(void *opaque, target_phys_addr_t addr,
++                          uint64_t data, unsigned size)
++{
++    VGACommonState *s = opaque;
++
++    return vga_mem_writeb(s, addr, data);
++}
++
++static int vga_common_post_load(void *opaque, int version_id)
++{
++    VGACommonState *s = opaque;
++
++    /* force refresh */
++    s->graphic_mode = -1;
++    return 0;
++}
++
++void maru_vga_common_init(VGACommonState *s)
 +{
 +    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;
++
 +#ifdef CONFIG_BOCHS_VBE
 +    s->is_vbe_vmstate = 1;
 +#else
 +    s->is_vbe_vmstate = 0;
 +#endif
-     s->vram_size = vga_ram_size;
++    memory_region_init_ram(&s->vram, "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);
-             r = ((v >> ds->pf.rshift) & ds->pf.rmax) * 256 /
-                 (ds->pf.rmax + 1);
-             g = ((v >> ds->pf.gshift) & ds->pf.gmax) * 256 /
-                 (ds->pf.gmax + 1);
-             b = ((v >> ds->pf.bshift) & ds->pf.bmax) * 256 /
-                 (ds->pf.bmax + 1);
 +    s->get_bpp = vga_get_bpp;
 +    s->get_offsets = vga_get_offsets;
 +    s->get_resolution = vga_get_resolution;
 +    s->update = vga_update_display;
 +    s->invalidate = vga_invalidate_display;
 +    s->screen_dump = vga_screen_dump;
 +    s->text_update = vga_update_text;
 +    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);
 +
 +#ifdef USE_SHM
 +    int mykey = getuid();
 +    shmid = shmget((key_t)mykey, (size_t)vga_ram_size, 0666 | IPC_CREAT);
 +    if (shmid == -1) {
 +        fprintf(stderr, "shmget failed\n");
 +        exit(1);
 +    }
 +
 +    shared_memory = shmat(shmid, (void*)0, 0);
 +    if (shared_memory == (void *)-1) {
 +        fprintf(stderr, "shmat failed\n");
 +        exit(1);
 +    }
 +
 +    printf("Memory attached at %X\n", (int)shared_memory);
 +#endif
 +
 +}
 +
++
++static const MemoryRegionPortio vga_portio_list[] = {
++    { 0x04,  2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3b4 */
++    { 0x0a,  1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3ba */
++    { 0x10, 16, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3c0 */
++    { 0x24,  2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3d4 */
++    { 0x2a,  1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3da */
++    PORTIO_END_OF_LIST(),
++};
++
++#ifdef CONFIG_BOCHS_VBE
++static const MemoryRegionPortio vbe_portio_list[] = {
++    { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index },
++# ifdef TARGET_I386
++    { 1, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
++# else
++    { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
++# endif
++    PORTIO_END_OF_LIST(),
++};
++#endif /* CONFIG_BOCHS_VBE */
++
 +/********************************************************/
 +/* vga screen dump */
 +
 +static int maru_ppm_save(const char *filename, struct DisplaySurface *ds)
 +{
 +    FILE *f;
 +    uint8_t *d, *d1;
 +    uint32_t v;
 +    int y, x;
 +    uint8_t r, g, b;
 +    int ret;
 +    char *linebuf, *pbuf;
 +
++    trace_ppm_save(filename, ds);
 +    f = fopen(filename, "wb");
 +    if (!f)
 +        return -1;
 +    fprintf(f, "P6\n%d %d\n%d\n",
 +            ds->width, ds->height, 255);
 +    linebuf = g_malloc(ds->width * 3);
 +    d1 = ds->data;
 +    for(y = 0; y < ds->height; y++) {
 +        d = d1;
 +        pbuf = linebuf;
 +        for(x = 0; x < ds->width; x++) {
 +            if (ds->pf.bits_per_pixel == 32)
 +                v = *(uint32_t *)d;
 +            else
 +                v = (uint32_t) (*(uint16_t *)d);
- static void vga_save_dpy_update(DisplayState *ds,
-                                 int x, int y, int w, int h)
- {
-     if (screen_dump_filename) {
-         maru_ppm_save(screen_dump_filename, ds->surface);
-     }
- }
- static void vga_save_dpy_resize(DisplayState *s)
- {
- }
- static void vga_save_dpy_refresh(DisplayState *s)
- {
- }
- static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds)
- {
-     DisplayChangeListener *dcl;
-     dcl = g_malloc0(sizeof(DisplayChangeListener));
-     dcl->dpy_update = vga_save_dpy_update;
-     dcl->dpy_resize = vga_save_dpy_resize;
-     dcl->dpy_refresh = vga_save_dpy_refresh;
-     register_displaychangelistener(ds, dcl);
-     return dcl;
- }
++            /* Limited to 8 or fewer bits per channel: */
++            r = ((v >> ds->pf.rshift) & ds->pf.rmax) << (8 - ds->pf.rbits);
++            g = ((v >> ds->pf.gshift) & ds->pf.gmax) << (8 - ds->pf.gbits);
++            b = ((v >> ds->pf.bshift) & ds->pf.bmax) << (8 - ds->pf.bbits);
 +            *pbuf++ = r;
 +            *pbuf++ = g;
 +            *pbuf++ = b;
 +            d += ds->pf.bytes_per_pixel;
 +        }
 +        d1 += ds->linesize;
 +        ret = fwrite(linebuf, 1, pbuf - linebuf, f);
 +        (void)ret;
 +    }
 +    g_free(linebuf);
 +    fclose(f);
 +    return 0;
 +}
 +
-     if (!screen_dump_dcl)
-         screen_dump_dcl = vga_screen_dump_init(s->ds);
-     screen_dump_filename = filename;
-     vga_invalidate_display(s);
 +/* save the vga display in a PPM image even if no display is
 +   available */
 +static void vga_screen_dump(void *opaque, const char *filename, bool cswitch)
 +{
 +    VGACommonState *s = opaque;
 +
-     screen_dump_filename = NULL;
++    if (cswitch) {
++        vga_invalidate_display(s);
++    }
 +    vga_hw_update();
++    ppm_save(filename, s->ds->surface);
 +}
index 2beeb53,0000000..c8a052e
mode 100644,000000..100644
--- /dev/null
@@@ -1,49 -1,0 +1,49 @@@
- void maru_vga_common_init(VGACommonState *s, int vga_ram_size);
 +/*
 + * Maru vga device
 + * Based on qemu/hw/vga_int.h
 + *
 + * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
 + *
 + * Contact:
 + * Hyunjun Son <hj79.son@samsung.com>
 + * GiWoong Kim <giwoong.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
 + *
 + */
 +
 +#ifndef MARU_VGA_INT_H_
 +#define MARU_VGA_INT_H_
 +
++void maru_vga_common_init(VGACommonState *s);
 +
 +void maru_vga_draw_cursor_line_8(uint8_t *d1, const uint8_t *src1,
 +                            int poffset, int w,
 +                            unsigned int color0, unsigned int color1,
 +                            unsigned int color_xor);
 +void maru_vga_draw_cursor_line_16(uint8_t *d1, const uint8_t *src1,
 +                             int poffset, int w,
 +                             unsigned int color0, unsigned int color1,
 +                             unsigned int color_xor);
 +void maru_vga_draw_cursor_line_32(uint8_t *d1, const uint8_t *src1,
 +                             int poffset, int w,
 +                             unsigned int color0, unsigned int color1,
 +                             unsigned int color_xor);
 +
 +#endif /* MARU_VGA_INT_H_ */
index 128cacf,0000000..5bfac31
mode 100644,000000..100644
--- /dev/null
@@@ -1,49 -1,0 +1,47 @@@
- #ifndef _WIN32
- #include <error.h>
- #endif
 +/* 
 + * Emulator
 + *
 + * Copyright (C) 2011, 2012 Samsung Electronics Co., Ltd. All rights reserved.
 + *
 + * Contact: 
 + * SeokYeon Hwang <syeon.hwang@samsung.com>
 + * HyunJun Son <hj79.son@samsung.com>
 + * MunKyu Im <munkyu.im@samsung.com>
 + * GiWoong Kim <giwoong.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
 + *
 + */
 +
 +#ifndef __OPTION_H__
 +#define __OPTION_H__
 +
 +#include <glib.h>
++
 +#include <sys/types.h>
 +#include <dirent.h>
 +#include <unistd.h>
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +
 +int gethostDNS(char *dns1, char *dns2);
 +int gethostproxy(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy);
 +#endif
 +
diff --cc vl.c
--- 1/vl.c
--- 2/vl.c
+++ b/vl.c
@@@ -3355,29 -3282,12 +3436,35 @@@ int main(int argc, char **argv, char **
              case QEMU_OPTION_qtest_log:
                  qtest_log = optarg;
                  break;
+             case QEMU_OPTION_sandbox:
+                 opts = qemu_opts_parse(qemu_find_opts("sandbox"), optarg, 1);
+                 if (!opts) {
+                     exit(0);
+                 }
+                 break;
 +            case QEMU_OPTION_enable_hax:
 +#ifdef CONFIG_HAX_BACKEND
 +                olist = qemu_find_opts("machine");
 +                qemu_opts_reset(olist);
 +                hax_disable(0);
 +                //qemu_opts_parse(olist, "accel=hax", 0);
 +#else
 +                fprintf(stderr,
 +                        "HAX support is disabled, ignoring -enable-hax\n");
 +#endif
 +                break;
 +#ifdef CONFIG_MARU
 +            case QEMU_OPTION_max_touch_point:
 +                {
 +                    int cnt = atoi(optarg);
 +                    fprintf(stderr, "maxTouchPoint:%d\n", cnt);
 +                    set_emul_max_touch_point(cnt);
 +                    break;
 +                }
 +            case QEMU_OPTION_disable_skin:
 +                skin_disabled = 1;
 +                break;
 +#endif
              default:
                  os_parse_cmd_args(popt->index, optarg);
              }
          ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
      }
  
 +    hax_pre_init(ram_size);
 +
+     if (qemu_opts_foreach(qemu_find_opts("device"), device_help_func, NULL, 0)
+         != 0) {
+         exit(0);
+     }
      configure_accelerator();
  
      qemu_init_cpu_loop();
  #elif defined(CONFIG_VNC)
          vnc_display = "localhost:0,to=99";
          show_vnc_port = 1;
 +#elif defined(CONFIG_MARU) && defined (__APPLE__)
 +        display_type = DT_MARU;
  #else
-       display_type = DT_NONE;
+         display_type = DT_NONE;
  #endif
      }
  
          cocoa_display_init(ds, full_screen);
          break;
  #endif
 +#if defined(CONFIG_MARU) && defined(__APPLE__)
 +    case DT_MARU:
 +      maru_display_init(ds);
 +      if (skin_disabled == 1) {
 +      //do not start skin client process
 +          set_emul_skin_enable(0);
 +      } else {
 +        set_emul_skin_enable(1);
 +      }
 +    break;
 +#endif
      default:
-   break;
+         break;
      }
  
      /* must be after terminal init, SDL library changes signal handlers */